test/langtools/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java
changeset 47216 71c04702a3d5
parent 24895 dd091d389fbf
child 59285 7799a51dbe30
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/ClassfileTestHelper.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.annotation.*;
+import java.io.*;
+import java.net.URL;
+import java.util.List;
+
+import com.sun.tools.classfile.*;
+
+public class ClassfileTestHelper {
+    int expected_tinvisibles = 0;
+    int expected_tvisibles = 0;
+    int expected_invisibles = 0;
+    int expected_visibles = 0;
+
+    //Makes debugging much easier. Set to 'false' for less output.
+    public Boolean verbose = true;
+    void println(String msg) { if (verbose) System.err.println(msg); }
+    void print(String msg) { if (verbose) System.err.print(msg); }
+
+    File writeTestFile(String fname, String source) throws IOException {
+      File f = new File(fname);
+        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
+        out.println(source);
+        out.close();
+        return f;
+    }
+
+    File compile(File f) {
+        int rc = com.sun.tools.javac.Main.compile(new String[] {
+                "-g", f.getPath() });
+        if (rc != 0)
+            throw new Error("compilation failed. rc=" + rc);
+        String path = f.getPath();
+        return new File(path.substring(0, path.length() - 5) + ".class");
+    }
+
+    ClassFile getClassFile(String name) throws IOException, ConstantPoolException {
+        URL url = getClass().getResource(name);
+        InputStream in = url.openStream();
+        try {
+            return ClassFile.read(in);
+        } finally {
+            in.close();
+        }
+    }
+
+    ClassFile getClassFile(URL url) throws IOException, ConstantPoolException {
+        InputStream in = url.openStream();
+        try {
+            return ClassFile.read(in);
+        } finally {
+            in.close();
+        }
+    }
+
+    /************ Helper annotations counting methods ******************/
+    void test(ClassFile cf) {
+        test("CLASS",cf, null, null, Attribute.RuntimeVisibleTypeAnnotations, true);
+        test("CLASS",cf, null, null, Attribute.RuntimeInvisibleTypeAnnotations, false);
+        //RuntimeAnnotations since one annotation can result in two attributes.
+        test("CLASS",cf, null, null, Attribute.RuntimeVisibleAnnotations, true);
+        test("CLASS",cf, null, null, Attribute.RuntimeInvisibleAnnotations, false);
+    }
+
+    void test(ClassFile cf, Field f, Boolean local) {
+        if (!local) {
+            test("FIELD",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true);
+            test("FIELD",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false);
+            test("FIELD",cf, f, null, Attribute.RuntimeVisibleAnnotations, true);
+            test("FIELD",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false);
+        } else {
+            test("CODE",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true);
+            test("CODE",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false);
+            test("CODE",cf, f, null, Attribute.RuntimeVisibleAnnotations, true);
+            test("CODE",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false);
+        }
+    }
+
+    void test(ClassFile cf, Field f) {
+        test(cf, f, false);
+    }
+
+    // 'local' determines whether to look for annotations in code attribute or not.
+    void test(ClassFile cf, Method m, Boolean local) {
+        if (!local) {
+            test("METHOD",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true);
+            test("METHOD",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
+            test("METHOD",cf, null, m, Attribute.RuntimeVisibleAnnotations, true);
+            test("METHOD",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false);
+        } else  {
+            test("MCODE",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true);
+            test("MCODE",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
+            test("MCODE",cf, null, m, Attribute.RuntimeVisibleAnnotations, true);
+            test("MCODE",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false);
+        }
+    }
+
+    // default to not looking in code attribute
+    void test(ClassFile cf, Method m ) {
+        test(cf, m, false);
+    }
+
+    // Test the result of Attributes.getIndex according to expectations
+    // encoded in the class/field/method name; increment annotations counts.
+    void test(String ttype, ClassFile cf, Field f, Method m, String annName, boolean visible) {
+        String testtype = ttype;
+        String name = null;
+        int index = -1;
+        Attribute attr = null;
+        Code_attribute cAttr = null;
+        boolean isTAattr = annName.contains("TypeAnnotations");
+        try {
+            switch(testtype) {
+                case "FIELD":
+                    name = f.getName(cf.constant_pool);
+                    index = f.attributes.getIndex(cf.constant_pool, annName);
+                    if(index!= -1)
+                        attr = f.attributes.get(index);
+                    break;
+                case "CODE":
+                    name = f.getName(cf.constant_pool);
+                    //fetch index of and code attribute and annotations from code attribute.
+                    index = cf.attributes.getIndex(cf.constant_pool, Attribute.Code);
+                    if(index!= -1) {
+                        attr = cf.attributes.get(index);
+                        assert attr instanceof Code_attribute;
+                        cAttr = (Code_attribute)attr;
+                        index = cAttr.attributes.getIndex(cf.constant_pool, annName);
+                        if(index!= -1)
+                            attr = cAttr.attributes.get(index);
+                    }
+                    break;
+                case "METHOD":
+                    name = m.getName(cf.constant_pool);
+                    index = m.attributes.getIndex(cf.constant_pool, annName);
+                    if(index!= -1)
+                        attr = m.attributes.get(index);
+                    break;
+                case "MCODE":
+                    name = m.getName(cf.constant_pool);
+                    //fetch index of and code attribute and annotations from code attribute.
+                    index = m.attributes.getIndex(cf.constant_pool, Attribute.Code);
+                    if(index!= -1) {
+                        attr = m.attributes.get(index);
+                        assert attr instanceof Code_attribute;
+                        cAttr = (Code_attribute)attr;
+                        index = cAttr.attributes.getIndex(cf.constant_pool, annName);
+                        if(index!= -1)
+                            attr = cAttr.attributes.get(index);
+                    }
+                    break;
+                default:
+                    name = cf.getName();
+                    index = cf.attributes.getIndex(cf.constant_pool, annName);
+                    if(index!= -1) attr = cf.attributes.get(index);
+            }
+        } catch(ConstantPoolException cpe) { cpe.printStackTrace(); }
+
+        if (index != -1) {
+            if(isTAattr) { //count RuntimeTypeAnnotations
+                RuntimeTypeAnnotations_attribute tAttr =
+                        (RuntimeTypeAnnotations_attribute)attr;
+                println(testtype + ": " + name + ", " + annName + ": " +
+                        tAttr.annotations.length );
+                if (tAttr.annotations.length > 0) {
+                    for (int i = 0; i < tAttr.annotations.length; i++) {
+                        println("  types:" + tAttr.annotations[i].position.type);
+                    }
+                } else {
+                    println("");
+                }
+                allt += tAttr.annotations.length;
+                if (visible)
+                    tvisibles += tAttr.annotations.length;
+                else
+                    tinvisibles += tAttr.annotations.length;
+            } else {
+                RuntimeAnnotations_attribute tAttr =
+                        (RuntimeAnnotations_attribute)attr;
+                println(testtype + ": " + name + ", " + annName + ": " +
+                        tAttr.annotations.length );
+                all += tAttr.annotations.length;
+                if (visible)
+                    visibles += tAttr.annotations.length;
+                else
+                    invisibles += tAttr.annotations.length;
+            }
+        }
+    }
+
+    void countAnnotations() {
+        errors=0;
+        int expected_allt = expected_tvisibles + expected_tinvisibles;
+        int expected_all = expected_visibles + expected_invisibles;
+
+        if (expected_allt != allt) {
+            errors++;
+            System.err.println("Failure: expected " + expected_allt +
+                    " type annotations but found " + allt);
+        }
+        if (expected_all != all) {
+            errors++;
+            System.err.println("Failure: expected " + expected_all +
+                    " annotations but found " + all);
+        }
+        if (expected_tvisibles != tvisibles) {
+            errors++;
+            System.err.println("Failure: expected " + expected_tvisibles +
+                    " typevisible annotations but found " + tvisibles);
+        }
+
+        if (expected_tinvisibles != tinvisibles) {
+            errors++;
+            System.err.println("Failure: expected " + expected_tinvisibles +
+                    " typeinvisible annotations but found " + tinvisibles);
+        }
+        allt=0;
+        tvisibles=0;
+        tinvisibles=0;
+        all=0;
+        visibles=0;
+        invisibles=0;
+    }
+
+    int errors;
+    int allt;
+    int tvisibles;
+    int tinvisibles;
+    int all;
+    int visibles;
+    int invisibles;
+}