1/* 2 * Copyright (c) 2013, 2015, 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/* 25 * @test 26 * @bug 8005681 27 * @summary Repeated annotations on new,array,cast. 28 * @modules jdk.jdeps/com.sun.tools.classfile 29 */ 30import java.lang.annotation.*; 31import java.io.*; 32import java.util.List; 33import com.sun.tools.classfile.*; 34 35import java.lang.annotation.*; 36import static java.lang.annotation.RetentionPolicy.*; 37import static java.lang.annotation.ElementType.*; 38 39public class TestNewCastArray { 40 int errors = 0; 41 List<String> failedTests = new java.util.LinkedList<>(); 42 43 // 'b' tests fail with only even numbers of annotations (8005681). 44 String[] testclasses = {"Test1", 45 "Test2a", "Test3a", "Test4a", "Test5a", 46 "Test2b", "Test3b", "Test4b", "Test5b" 47 }; 48 49 public static void main(String[] args) throws Exception { 50 new TestNewCastArray().run(); 51 } 52 53 void check(String testcase, int expected, int actual) { 54 String res = testcase + ": (expected) " + expected + ", " + actual + " (actual): "; 55 if(expected == actual) { 56 res = res.concat("PASS"); 57 } else { 58 errors++; 59 res = res.concat("FAIL"); 60 failedTests.add(res); 61 } 62 System.out.println(res); 63 } 64 65 void report() { 66 if(errors!=0) { 67 System.err.println("Failed tests: " + errors + 68 "\nfailed test cases:\n"); 69 for(String t: failedTests) 70 System.err.println(" " + t); 71 throw new RuntimeException("FAIL: There were test failures."); 72 } else 73 System.out.println("PASS"); 74 } 75 76 void test(String clazz, String ttype, ClassFile cf, Method m, Field f, 77 String name, boolean codeattr) { 78 int actual = 0; 79 int expected = 0, cexpected = 0; 80 int index = 0; 81 String memberName = null; 82 Attribute attr = null; 83 Code_attribute cAttr = null; 84 String testcase = "undefined"; 85 try { 86 switch(ttype) { 87 case "METHOD": 88 index = m.attributes.getIndex(cf.constant_pool, name); 89 memberName = m.getName(cf.constant_pool); 90 if(index != -1) 91 attr = m.attributes.get(index); 92 break; 93 case "MCODE": 94 memberName = m.getName(cf.constant_pool); 95 //fetch index of and code attribute and annotations from code attribute. 96 index = m.attributes.getIndex(cf.constant_pool, Attribute.Code); 97 if(index!= -1) { 98 attr = m.attributes.get(index); 99 assert attr instanceof Code_attribute; 100 cAttr = (Code_attribute)attr; 101 index = cAttr.attributes.getIndex(cf.constant_pool, name); 102 if(index!= -1) 103 attr = cAttr.attributes.get(index); 104 } 105 break; 106 case "FIELD": 107 index = f.attributes.getIndex(cf.constant_pool, name); 108 memberName = f.getName(cf.constant_pool); 109 if(index != -1) 110 attr = f.attributes.get(index); 111 break; 112 case "CODE": 113 memberName = f.getName(cf.constant_pool); 114 //fetch index of and code attribute and annotations from code attribute. 115 index = cf.attributes.getIndex(cf.constant_pool, Attribute.Code); 116 if(index!= -1) { 117 attr = cf.attributes.get(index); 118 assert attr instanceof Code_attribute; 119 cAttr = (Code_attribute)attr; 120 index = cAttr.attributes.getIndex(cf.constant_pool, name); 121 if(index!= -1) 122 attr = cAttr.attributes.get(index); 123 } 124 break; 125 default: 126 break; 127 } 128 } catch(ConstantPoolException cpe) { cpe.printStackTrace(); } 129 testcase = clazz+" "+ttype + ": " + memberName + ", " + name; 130 if(index != -1) { 131 //count RuntimeTypeAnnotations 132 assert attr instanceof RuntimeTypeAnnotations_attribute; 133 RuntimeTypeAnnotations_attribute tAttr = 134 (RuntimeTypeAnnotations_attribute)attr; 135 actual += tAttr.annotations.length; 136 } 137 if(memberName.compareTo("<init>")==0) memberName=clazz+memberName; 138 switch ( memberName ) { 139 //METHOD: 140 case "Test1<init>": expected=0; break; 141 case "testr22_22": expected=4; break; 142 case "testr11_11": expected=4; break; 143 case "testr12_21": expected=4; break; 144 case "testr20_02": expected=2; break; 145 146 case "Test2a<init>": cexpected=0; break; 147 case "test00_00_11_11": cexpected=4; break; 148 case "test21_12_21_12": cexpected=8; break; 149 case "test_new1": cexpected=2; break; 150 case "test_new2": cexpected=2; break; 151 case "test_cast1": cexpected=2; break; 152 case "test_cast2": cexpected=2; break; 153 154 case "Test2b<init>": cexpected=0; break; 155 case "test20_02_20_02": cexpected=4; break; 156 case "test22_22_22_22": cexpected=8; break; 157 case "test_new3": cexpected=1; break; 158 case "test_new4": cexpected=1; break; 159 case "test_new5": cexpected=2; break; 160 case "test_cast3": cexpected=1; break; 161 case "test_cast4": cexpected=2; break; 162 163 case "Test3a<init>": cexpected=10; break; 164 case "SA_21_12c": cexpected = 0; break; 165 case "SA_01_10c": expected = 0; break; 166 case "SA_11_11c": expected = 0; break; 167 168 case "Test3b<init>": cexpected=6; break; 169 case "SA_22_22c": cexpected = 0; break; 170 case "SA_20_02c": cexpected = 0; break; 171 172 case "Test3c<init>": cexpected=8; break; 173 case "SA_10_10": cexpected = 0; break; 174 case "SA_10_01": cexpected = 0; break; 175 case "SA_21_12": cexpected = 0; break; 176 177 case "Test3d<init>": cexpected=6; break; 178 case "SA_20_02": cexpected = 0; break; 179 case "SA_22_22": cexpected = 0; break; 180 181 case "Test4a<init>": cexpected=4; break; 182 case "nS_21": cexpected = 0; break; 183 case "nS_12": cexpected = 0; break; 184 185 case "Test4b<init>": cexpected=4; break; 186 case "nS20": cexpected = 0; break; 187 case "nS02": cexpected = 0; break; 188 case "nS22": cexpected = 0; break; 189 190 case "Test5a<init>": cexpected=4; break; 191 case "ci11": expected = 0; break; 192 case "ci21": expected = 0; break; 193 194 case "Test5b<init>": cexpected=3; break; 195 case "ci2": expected = 0; break; 196 case "ci22": expected = 0; break; 197 198 default: expected = 0; break; 199 } 200 if(codeattr) 201 check(testcase, cexpected, actual); 202 else 203 check(testcase, expected, actual); 204 } 205 206 public void run() { 207 ClassFile cf = null; 208 InputStream in = null; 209 for( String clazz : testclasses) { 210 String testclazz = "TestNewCastArray$" + clazz + ".class"; 211 System.out.println("Testing " + testclazz); 212 try { 213 in = getClass().getResource(testclazz).openStream(); 214 cf = ClassFile.read(in); 215 in.close(); 216 } catch(Exception e) { e.printStackTrace(); } 217 218 if(clazz.startsWith("Test1")) { 219 for (Field f: cf.fields) 220 test(clazz, "FIELD", cf, null, f, Attribute.RuntimeVisibleTypeAnnotations, false); 221 for (Method m: cf.methods) 222 test(clazz, "METHOD", cf, m, null, Attribute.RuntimeVisibleTypeAnnotations, false); 223 } else { 224 for (Field f: cf.fields) 225 test(clazz, "CODE", cf, null, f, Attribute.RuntimeVisibleTypeAnnotations, true); 226 for (Method m: cf.methods) 227 test(clazz, "MCODE", cf, m, null, Attribute.RuntimeVisibleTypeAnnotations, true); 228 } 229 } 230 report(); 231 } 232 233 //////// test class ////////////////////////// 234 // "Test1" not in code attribute. 235 // on arrays on and in method return 236 static class Test1 { 237 Test1(){} 238 // OK expect 5, got 5 239 String @A @A @B @B[] @A @A @B @B [] testr22_22(Test1 this, String param, String ... vararg) { 240 String [][] sarray = new String [2][2]; 241 return sarray; 242 } 243 // OK expect 5, got 5 244 String @A @B [] @A @B [] testr11_11(Test1 this, String param, String ... vararg) { 245 String [][] sarray = new String [2][2]; 246 return sarray; 247 } 248 // OK expect 5, got 5 249 String @A @B @B []@B @B @A[] testr12_21(Test1 this, String param, String ... vararg) { 250 String [][] sarray = new String [2][2]; 251 return sarray; 252 } 253 // OK expect 3, got 3 254 String @A @A [] @B @B [] testr20_02(Test1 this, String param, String ... vararg) { 255 String [][] sarray = new String [2][2]; 256 return sarray; 257 } 258 } 259 260 // Inside method body (in method's code attribute) 261 static class Test2a { 262 Test2a(){} 263 Object o = new Integer(1); 264 // expect 4 265 String[][] test00_00_11_11(Test2a this, String param, String ... vararg) { 266 String [] [] sarray = new String @A @B[2] @A @B [2]; 267 return sarray; 268 } 269 270 // expect 8 271 String[][] test21_12_21_12(Test2a this, String param, String ... vararg) { 272 String @A @A @B [] @A @B @B [] sarray = new String @A @A @B[2] @A @B @B [2]; 273 return sarray; 274 } 275 276 void test_new1() { String nS_21 = new @A @A @B String("Hello"); } 277 void test_new2() { String nS_12 = new @A @B @B String("Hello"); } 278 void test_cast1() { String tcs11 = (@A @B String)o; } 279 void test_cast2() { String tcs21 = (@A @A @B String)o; } 280 } 281 282 static class Test2b { 283 Test2b(){} 284 Object o = new Integer(1); 285 // expect 4 286 String[][] test20_02_20_02(Test2b this, String param, String ... vararg) { 287 String @A @A [] @B @B [] sarray = new String @A @A[2] @B @B [2]; 288 return sarray; 289 } 290 291 // expect 8 292 String[][] test22_22_22_22(Test2b this, String param, String ... vararg) { 293 String @A @A @B @B [] @A @A @B @B [] sarray = new String @A @A @B @B [2] @A @A @B @B [2]; 294 return sarray; 295 } 296 297 void test_new3() { String nS20 = new @A @A String("Hello"); } 298 void test_new4() { String nS02 = new @B @B String("Hello"); } 299 void test_new5() { String nS22 = new @A @A @B @B String("Hello"); } 300 void test_cast3() { String tcs2 = (@A @A String)o; } 301 void test_cast4() { String tcs22 = (@A @A @B @B String)o;} 302 } 303 304 // array levels 305 static class Test3a { 306 Test3a(){} 307 // expect 4+2+4=10 308 String [][] SA_21_12c = new String @A @A @B [2] @A @B @B[2]; 309 String [][] SA_01_10c = new String @B [2] @A [2]; 310 String [][] SA_11_11c = new String @A @B [2] @A @B [2]; 311 } 312 313 static class Test3b { 314 Test3b(){} 315 // expect 4+2=6 316 String [][] SA_22_22c = new String @A @A @B @B[2] @A @A @B @B[2]; 317 String [][] SA_20_02c = new String @A @A [2] @B @B[2]; 318 } 319 static class Test3c { 320 Test3c(){} 321 // OK expect 4 322 String @A [] @A[] SA_10_10 = new String [2][2]; 323 String @A [] @B[] SA_10_01 = new String [2][2]; 324 String @A @A @B[] @A @B @B [] SA_21_12 = new String [2][2]; 325 } 326 327 static class Test3d { 328 Test3d(){} 329 // OK expect 4 330 String @A @A [] @B @B [] SA_20_02 = new String [2][2]; 331 String @A @A @B @B[] @A @A @B @B [] SA_22_22 = new String [2][2]; 332 } 333 334 // on new 335 static class Test4a { 336 Test4a(){} 337 // expect 2+2=4 338 String nS_21 = new @A @A @B String("Hello"); 339 String nS_12 = new @A @B @B String("Hello"); 340 } 341 342 static class Test4b { 343 Test4b(){} 344 // expect 1+1+2=4 345 String nS20 = new @A @A String("Hello"); 346 String nS02 = new @B @B String("Hello"); 347 String nS22 = new @A @A @B @B String("Hello"); 348 } 349 350 // Cast expressions 351 static class Test5a { 352 Test5a(){} 353 Object o = new Integer(1); 354 // expect 2+2=4 355 Integer ci11 = (@A @B Integer)o; // OK expect 3, got 3 356 Integer ci21 = (@A @A @B Integer)o; // OK expect 3, got 3 357 } 358 359 static class Test5b { 360 Test5b(){} 361 Object o = new Integer(1); 362 // Cast expressions 363 // expect 1+2=3 364 Integer ci2 = (@A @A Integer)o; // FAIL expect 2, got 1 365 Integer ci22 = (@A @A @B @B Integer)o; // FAIL expect 3, got 1 366 } 367 368@Retention(RUNTIME) @Target({TYPE_USE}) @Repeatable( AC.class ) @interface A { } 369@Retention(RUNTIME) @Target({TYPE_USE}) @Repeatable( BC.class ) @interface B { } 370@Retention(RUNTIME) @Target({FIELD}) @Repeatable( FC.class ) @interface F { } 371@Retention(RUNTIME) @Target({TYPE_USE}) @interface AC { A[] value(); } 372@Retention(RUNTIME) @Target({TYPE_USE}) @interface BC { B[] value(); } 373@Retention(RUNTIME) @Target({FIELD}) @interface FC { F[] value(); } 374 375} 376 377