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