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