1 /* 2 * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.*; 25 import java.lang.annotation.ElementType; 26 27 import com.sun.tools.classfile.*; 28 29 /* 30 * @test Presence 31 * @bug 6843077 32 * @summary test that all type annotations are present in the classfile 33 */ 34 35 public class Presence { 36 public static void main(String[] args) throws Exception { 37 new Presence().run(); 38 } 39 40 public void run() throws Exception { 41 File javaFile = writeTestFile(); 42 File classFile = compileTestFile(javaFile); 43 44 ClassFile cf = ClassFile.read(classFile); 45 test(cf); 46 for (Field f : cf.fields) { 47 test(cf, f); 48 } 49 for (Method m: cf.methods) { 50 test(cf, m); 51 } 52 53 countAnnotations(); 54 55 if (errors > 0) 56 throw new Exception(errors + " errors found"); 57 System.out.println("PASSED"); 58 } 59 60 void test(ClassFile cf) { 61 test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); 62 test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); 63 } 64 65 void test(ClassFile cf, Method m) { 66 test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); 67 test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); 68 } 69 70 void test(ClassFile cf, Field m) { 71 test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); 72 test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); 73 } 74 75 // test the result of Attributes.getIndex according to expectations 76 // encoded in the method's name 77 void test(ClassFile cf, String name, boolean visible) { 78 int index = cf.attributes.getIndex(cf.constant_pool, name); 79 if (index != -1) { 80 Attribute attr = cf.attributes.get(index); 81 assert attr instanceof RuntimeTypeAnnotations_attribute; 82 RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; 83 all += tAttr.annotations.length; 84 if (visible) 85 visibles += tAttr.annotations.length; 86 else 87 invisibles += tAttr.annotations.length; 88 } 89 } 90 91 // test the result of Attributes.getIndex according to expectations 92 // encoded in the method's name 93 void test(ClassFile cf, Method m, String name, boolean visible) { 94 Attribute attr = null; 95 Code_attribute cAttr = null; 96 RuntimeTypeAnnotations_attribute tAttr = null; 97 98 // collect annotations attributes on method 99 int index = m.attributes.getIndex(cf.constant_pool, name); 100 if (index != -1) { 101 attr = m.attributes.get(index); 102 assert attr instanceof RuntimeTypeAnnotations_attribute; 103 tAttr = (RuntimeTypeAnnotations_attribute)attr; 104 all += tAttr.annotations.length; 105 if (visible) 106 visibles += tAttr.annotations.length; 107 else 108 invisibles += tAttr.annotations.length; 109 } 110 // collect annotations from method's code attribute 111 index = m.attributes.getIndex(cf.constant_pool, Attribute.Code); 112 if(index!= -1) { 113 attr = m.attributes.get(index); 114 assert attr instanceof Code_attribute; 115 cAttr = (Code_attribute)attr; 116 index = cAttr.attributes.getIndex(cf.constant_pool, name); 117 if(index!= -1) { 118 attr = cAttr.attributes.get(index); 119 assert attr instanceof RuntimeTypeAnnotations_attribute; 120 tAttr = (RuntimeTypeAnnotations_attribute)attr; 121 all += tAttr.annotations.length; 122 if (visible) 123 visibles += tAttr.annotations.length; 124 else 125 invisibles += tAttr.annotations.length; 126 } 127 } 128 } 129 130 // test the result of Attributes.getIndex according to expectations 131 // encoded in the method's name 132 void test(ClassFile cf, Field m, String name, boolean visible) { 133 int index = m.attributes.getIndex(cf.constant_pool, name); 134 if (index != -1) { 135 Attribute attr = m.attributes.get(index); 136 assert attr instanceof RuntimeTypeAnnotations_attribute; 137 RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; 138 all += tAttr.annotations.length; 139 if (visible) 140 visibles += tAttr.annotations.length; 141 else 142 invisibles += tAttr.annotations.length; 143 } 144 } 145 146 File writeTestFile() throws IOException { 147 File f = new File("TestPresence.java"); 148 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); 149 out.println("import java.util.*;"); 150 out.println("import java.lang.annotation.*;"); 151 152 out.println("class TestPresence<@TestPresence.A T extends @TestPresence.A List<@TestPresence.A String>> { "); 153 out.println(" @Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); 154 out.println(" @interface A { }"); 155 156 out.println(" Map<@A String, Map<@A String, @A String>> f1;"); 157 158 out.println(" <@A TM extends @A List<@A String>>"); 159 out.println(" Map<@A String, @A List<@A String>>"); 160 out.println(" method(@A TestPresence<T> this, List<@A String> @A [] param1, String @A [] @A ... param2)"); 161 out.println(" throws @A Exception {"); 162 out.println(" @A String lc1 = null;"); 163 out.println(" @A List<@A String> lc2 = null;"); 164 out.println(" @A String @A [] [] @A[] lc3 = null;"); 165 out.println(" List<? extends @A List<@A String>> lc4 = null;"); 166 out.println(" Object lc5 = (@A List<@A String>) null;"); 167 out.println(" boolean lc6 = lc1 instanceof @A String;"); 168 out.println(" boolean lc7 = lc5 instanceof @A String @A [] @A [];"); 169 out.println(" new @A ArrayList<@A String>();"); 170 out.println(" Object lc8 = new @A String @A [4];"); 171 out.println(" try {"); 172 out.println(" Object lc10 = int.class;"); 173 out.println(" } catch (@A Exception e) { e.toString(); }"); 174 out.println(" return null;"); 175 out.println(" }"); 176 out.println(" void vararg1(String @A ... t) { } "); 177 out.println("}"); 178 out.close(); 179 return f; 180 } 181 182 File compileTestFile(File f) { 183 int rc = com.sun.tools.javac.Main.compile(new String[] {"-g", f.getPath() }); 184 if (rc != 0) 185 throw new Error("compilation failed. rc=" + rc); 186 String path = f.getPath(); 187 return new File(path.substring(0, path.length() - 5) + ".class"); 188 } 189 190 void countAnnotations() { 191 int expected_visibles = 0, expected_invisibles = 38; 192 int expected_all = expected_visibles + expected_invisibles; 193 194 if (expected_all != all) { 195 errors++; 196 System.err.println("expected " + expected_all 197 + " annotations but found " + all); 198 } 199 200 if (expected_visibles != visibles) { 201 errors++; 202 System.err.println("expected " + expected_visibles 203 + " visibles annotations but found " + visibles); 204 } 205 206 if (expected_invisibles != invisibles) { 207 errors++; 208 System.err.println("expected " + expected_invisibles 209 + " invisibles annotations but found " + invisibles); 210 } 211 212 } 213 214 int errors; 215 int all; 216 int visibles; 217 int invisibles; 218 }