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  */
30 import java.lang.annotation.*;
31 import java.io.*;
32 import java.util.List;
33 import com.sun.tools.classfile.*;
34 
35 import java.lang.annotation.*;
36 import static java.lang.annotation.RetentionPolicy.*;
37 import static java.lang.annotation.ElementType.*;
38 
39 public 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 
main(String[] args)49     public static void main(String[] args) throws Exception {
50         new TestNewCastArray().run();
51     }
52 
check(String testcase, int expected, int actual)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 
report()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 
test(String clazz, String ttype, ClassFile cf, Method m, Field f, String name, boolean codeattr)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 
run()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 {
Test1()237         Test1(){}
238         // OK expect 5, got 5
testr22_22(Test1 this, String param, String ... vararg)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
testr11_11(Test1 this, String param, String ... vararg)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
testr12_21(Test1 this, String param, String ... vararg)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
testr20_02(Test1 this, String param, String ... vararg)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 {
Test2a()262         Test2a(){}
263         Object o = new Integer(1);
264         // expect 4
test00_00_11_11(Test2a this, String param, String ... vararg)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
test21_12_21_12(Test2a this, String param, String ... vararg)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 
test_new1()276         void test_new1() { String nS_21 = new @A @A @B String("Hello");   }
test_new2()277         void test_new2() { String nS_12 = new @A @B @B String("Hello");   }
test_cast1()278         void test_cast1() { String tcs11 = (@A @B String)o;      }
test_cast2()279         void test_cast2() { String tcs21 = (@A @A @B String)o;   }
280     }
281 
282     static class Test2b {
Test2b()283         Test2b(){}
284         Object o = new Integer(1);
285         // expect 4
test20_02_20_02(Test2b this, String param, String ... vararg)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
test22_22_22_22(Test2b this, String param, String ... vararg)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 
test_new3()297         void test_new3() { String nS20 = new @A @A String("Hello");       }
test_new4()298         void test_new4() { String nS02 = new @B @B String("Hello");       }
test_new5()299         void test_new5() { String nS22 = new @A @A @B @B String("Hello"); }
test_cast3()300         void test_cast3() { String tcs2 =  (@A @A String)o;      }
test_cast4()301         void test_cast4() { String tcs22 = (@A @A @B @B String)o;}
302     }
303 
304     // array levels
305     static class Test3a {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 { }
value()371 @Retention(RUNTIME) @Target({TYPE_USE}) @interface AC { A[] value(); }
value()372 @Retention(RUNTIME) @Target({TYPE_USE}) @interface BC { B[] value(); }
value()373 @Retention(RUNTIME) @Target({FIELD}) @interface FC { F[] value(); }
374 
375 }
376 
377