CombinationsTargetTest1.java revision 2942:08092deced3f
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 8005085 8005877 8004829 8005681 8006734 8006775
27 * @summary Combinations of Target ElementTypes on (repeated)type annotations.
28 * @modules jdk.jdeps/com.sun.tools.classfile
29 */
30
31import com.sun.tools.classfile.*;
32import java.io.File;
33
34public class CombinationsTargetTest1 extends ClassfileTestHelper {
35
36    // Test count helps identify test case in event of failure.
37    int testcount = 0;
38
39    // Base test case template descriptions
40    enum srce  {
41        src1("(repeating) type annotations at class level"),
42        src2("(repeating) type annotations on method"),
43        src3("(repeating) type annotations on wildcard, type arguments in anonymous class"),
44        src4("(repeating) type annotations on type parameters, bounds and  type arguments on class decl"),
45        src5("(repeating) type annotations on type parameters, bounds and  type arguments on method"),
46        src6("(repeating) type annotations on type parameters, bounds and  type arguments in method");
47
48        String description;
49
50        srce(String desc) {
51            this.description = this + ": " +desc;
52        }
53    }
54
55    String[] ETypes={"TYPE", "FIELD", "METHOD", "PARAMETER", "CONSTRUCTOR",
56                     "LOCAL_VARIABLE", "ANNOTATION_TYPE", "PACKAGE"};
57
58    // local class tests will have an inner class.
59    Boolean hasInnerClass=false;
60    String innerClassname="";
61
62    public static void main(String[] args) throws Exception {
63        new CombinationsTargetTest1().run();
64    }
65
66    void run() throws Exception {
67        // Determines which repeat and order in source(ABMix).
68        Boolean As= false, BDs=true, ABMix=false;
69        int testrun=0;
70        Boolean [][] bRepeat = new Boolean[][]{{false,false,false},//no repeats
71                                               {true,false,false}, //repeat @A
72                                               {false,true,false}, //repeat @B
73                                               {true,true,false},  //repeat both
74                                               {false,false,true}  //repeat mix
75        };
76        for(Boolean[] bCombo : bRepeat) {
77            As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2];
78            for(String et : ETypes) {
79               switch(et) {
80                   case "METHOD":
81                       test( 8,  0, 2, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src1);
82                       test(10,  0, 2, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src2);
83                       test( 6,  0, 0, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src3);
84                       test(10,  0, 2, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src5);
85                       test( 0,  8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
86                       test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src2);
87                       test( 0,  6, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src3);
88                       test( 0, 10, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src5);
89                       break;
90                   case "CONSTRUCTOR":
91                   case "FIELD":
92                       test( 8,  0, 4, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src1);
93                       test( 6,  0, 3, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src4);
94                       test( 9,  0, 0, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src6);
95                       test( 0,  8, 0, 4, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
96                       test( 0,  6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src4);
97                       test( 0,  9, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src6);
98                       break;
99                   default:/*TYPE,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE*/
100                       test( 8,  0, 2, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src1);
101                       test( 6,  0, 3, 0, As, BDs, ABMix, "CLASS",   et, ++testrun, srce.src4);
102                       test( 0,  8, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
103                       test( 0,  6, 0, 3, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src4);
104               }
105            }
106        }
107    }
108
109    public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats,
110                     Boolean BDrepeats, Boolean ABmix, String rtn, String et2,
111                     Integer N, srce source) throws Exception {
112        ++testcount;
113        expected_tvisibles = tvis;
114        expected_tinvisibles = tinv;
115        expected_visibles = vis;
116        expected_invisibles = inv;
117        File testFile = null;
118        String tname="Test" + N.toString();
119        hasInnerClass=false;
120        String testDef = "Test " + testcount + " parameters: tinv=" + tinv +
121                ", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis +
122                ", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats +
123                ", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " +
124                et2 + ", src=" + source;
125
126        println(testDef);
127        // Create test source and File.
128        String sourceString = sourceString(tname, rtn, et2, Arepeats,
129                                           BDrepeats, ABmix, source);
130        testFile = writeTestFile(tname+".java", sourceString);
131        // Compile test source and read classfile.
132        File classFile = null;
133        try {
134            classFile = compile(testFile);
135        } catch (Error err) {
136            System.err.println("Failed compile. Source:\n" + sourceString);
137            throw err;
138        }
139        //if sourcString() set hasInnerClass it also set innerClassname.
140        if(hasInnerClass) {
141            StringBuffer sb = new StringBuffer(classFile.getAbsolutePath());
142            classFile=new File(sb.insert(sb.lastIndexOf(".class"),
143                                         innerClassname).toString());
144        }
145        ClassFile cf = ClassFile.read(classFile);
146
147        //Test class,fields and method counts.
148        test(cf);
149
150        for (Field f : cf.fields) {
151            test(cf, f);
152        }
153        for (Method m: cf.methods) {
154            test(cf, m);
155        }
156        countAnnotations();
157        if (errors > 0) {
158            System.err.println( testDef );
159            System.err.println( "Source:\n" + sourceString );
160            throw new Exception( errors + " errors found" );
161        }
162        println("Pass");
163    }
164
165    //
166    // Source for test cases
167    //
168    String sourceString(String testname, String retentn, String annot2,
169                        Boolean Arepeats, Boolean BDrepeats, Boolean ABmix,
170                        srce src) {
171
172        String As = "@A", Bs = "@B", Ds = "@D";
173        if(Arepeats) As = "@A @A";
174        if(BDrepeats) {
175            Bs = "@B @B";
176            Ds = "@D @D";
177        }
178        if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; }
179
180        // Source to check for TYPE_USE and TYPE_PARAMETER annotations.
181        // Source base (annotations) is same for all test cases.
182        String source = new String();
183        String imports = new String("import java.lang.annotation.*; \n" +
184            "import static java.lang.annotation.RetentionPolicy.*; \n" +
185            "import static java.lang.annotation.ElementType.*; \n" +
186            "import java.util.List; \n" +
187            "import java.util.HashMap; \n" +
188            "import java.util.Map; \n\n");
189
190            String sourceBase = new String("@Retention("+retentn+")\n" +
191            "@Target({TYPE_USE,_OTHER_})\n" +
192            "@Repeatable( AC.class )\n" +
193            "@interface A { }\n\n" +
194
195            "@Retention("+retentn+")\n" +
196            "@Target({TYPE_USE,_OTHER_})\n" +
197            "@interface AC { A[] value(); }\n\n" +
198
199            "@Retention("+retentn+")\n" +
200            "@Target({TYPE_USE,_OTHER_})\n" +
201            "@Repeatable( BC.class )\n" +
202            "@interface B { }\n\n" +
203
204            "@Retention("+retentn+")\n" +
205            "@Target({TYPE_USE,_OTHER_})\n" +
206            "@interface BC { B[] value(); } \n\n" +
207
208            "@Retention("+retentn+")\n" +
209            "@Target({TYPE_PARAMETER,_OTHER_})\n" +
210            "@interface C { }\n\n" +
211
212            "@Retention("+retentn+")\n" +
213            "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" +
214            "@Repeatable(DC.class)\n" +
215            "@interface D { }\n\n" +
216
217            "@Retention("+retentn+")\n" +
218            "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" +
219            "@interface DC { D[] value(); }\n");
220
221        // Test case sources with sample generated source.
222        switch(src) {
223            case src1: // repeating type annotations at class level
224                    /*
225                     * @A @B class Test1 {
226                     * @A @B Test1(){}
227                     * @A @B Integer i1 = 0;
228                     * String @A @B [] @A @B [] sa = null;
229                     * // type usage in method body
230                     * String test(Test1 this, String param, String ... vararg) {
231                     *     Object o = new  String  [3];
232                     *     return (String) null;
233                     * }}
234                     */
235                source = new String(
236                    "// " + src.description + "\n" +
237                    "_As_ _Bs_ class " + testname + " {\n" +
238                    "_As_ _Bs_ " + testname +"(){} \n" +
239                    "_As_ _Bs_ Integer i1 = 0; \n" +
240                    "String _As_ _Bs_ [] _As_ _Bs_ [] sa = null; \n" +
241                    "// type usage in method body \n" +
242                    "String test("+testname+" this, " +
243                       "String param, String ... vararg) { \n" +
244                    "    Object o = new  String  [3]; \n" +
245                    "    return (String) null; \n" +
246                    "}\n" +
247                    "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
248                    "\n";
249                break;
250            case src2: // (repeating) type annotations on method.
251                    /*
252                     * class Test12 {
253                     * Test12(){}
254                     * // type usage on method
255                     * @A @B String test(@A @B  Test12 this, @A @B  String param, @A @B  String @A @B  ... vararg) {
256                     *     Object o = new String [3];
257                     *     return (String) null;
258                     * }}
259                     */
260                source = new String(
261                    "// " + src.description + "\n" +
262                    "class " + testname + " {\n" +
263                    testname +"(){} \n" +
264                    "// type usage on method \n" +
265                    "_As_ _Bs_ String test(_As_ _Bs_  "+testname+" this, " +
266                       "_As_ _Bs_  String param, _As_ _Bs_  String _As_ _Bs_  ... vararg) { \n" +
267                    "    Object o = new String [3]; \n" +
268                    "    return (String) null; \n" +
269                    "}\n" +
270                    "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
271                    "\n";
272                break;
273            case src3: //(repeating) annotations on wildcard, type arguments in anonymous class.
274                    /*
275                     * class Test13<T extends Object> {
276                     *     public T data = null;
277                     *     T getData() { return data;}
278                     *     String mtest( Test13<String> t){ return t.getData(); }
279                     *     public void test() {
280                     *         mtest( new Test13<String>() {
281                     *                  void m1(List<@A @B ? extends @A @B  Object> lst) {}
282                     *                  void m2() throws@A @B Exception { }
283                     *                });
284                     *     }
285                     * }
286                     */
287                source = new String( source +
288                    "// " + src.description + "\n" +
289                    "class " + testname + "<T extends Object> {\n" +
290                    "    public T data = null;\n" +
291                    "    T getData() { return data;}\n" +
292                    "    String mtest( " + testname + "<String> t){ return t.getData(); }\n" +
293                    "    public void test() {\n" +
294                    "        mtest( new " + testname + "<String>() {\n" +
295                    "                 void m1(List<_As_ _Bs_ ? extends _As_ _Bs_  Object> lst) {}\n" +
296                    "                 void m2() throws_As_ _Bs_ Exception { }\n" +
297                    "               });\n" +
298                    "    }\n" +
299                    "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
300                    "\n";
301                    hasInnerClass=true;
302                    innerClassname="$1";
303            break;
304            case src4: // (repeating)annotations on type parameters, bounds and  type arguments on class decl.
305                    /*
306                     * @A @B @D
307                     * class Test2<@A @B @C @D T extends @A @B Object> {
308                     *     Map<List<String>, Integer> map =
309                     *         new HashMap<List< String>, Integer>();
310                     *     Map<List<String>,Integer> map2 = new HashMap<>();
311                     *     String test(Test2<T> this) { return null;}
312                     *     <T> String genericMethod(T t) { return null; }
313                     * }
314                     */
315                source = new String( source +
316                    "// " + src.description + "\n" +
317                    "_As_ _Bs_ _Ds_\n" +  //8004829: A and B on type parameter below.
318                    "class " + testname + "<_As_ _Bs_ @C _Ds_ T extends _As_ _Bs_ Object> {\n" +
319                    "    Map<List<String>, Integer> map =\n" +
320                    "        new HashMap<List< String>, Integer>();\n" +
321                    "    Map<List<String>,Integer> map2 = new HashMap<>();\n" +
322                    "    String test(" + testname + "<T> this) { return null;}\n" +
323                    "    <T> String genericMethod(T t) { return null; }\n" +
324                    "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
325                    "\n";
326                break;
327            case src5: // (repeating) annotations on type parameters, bounds and  type arguments on method.
328                    /*
329                     * class Test14<T extends Object> {
330                     *     Map<List<String>, Integer> map =
331                     *         new HashMap<List<String>, Integer>();
332                     *     Map<List<String>, Integer> map2 = new HashMap<>();
333                     *     String test(@A @B Test14<@D T> this) { return null;}
334                     *     <@C @D T> @A @B String genericMethod(@A @B @D T t) { return null; }
335                     * }
336                     */
337                source = new String( source +
338                    "// " + src.description + "\n" +
339                    "class " + testname + "<T extends Object> {\n" +
340                    "    Map<List<String>, Integer> map =\n" +
341                    "        new HashMap<List<String>, Integer>();\n" +
342                    "    Map<List<String>, Integer> map2 = new HashMap<>();\n" +
343                    "    String test(_As_ _Bs_ " + testname + "<_Ds_ T> this) { return null;}\n" +
344                    "    <@C _Ds_ T> _As_ _Bs_ String genericMethod(_As_ _Bs_ _Ds_ T t) { return null; }\n" +
345                    "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
346                    "\n";
347                break;
348            case src6: // repeating annotations on type parameters, bounds and  type arguments in method.
349                    /*
350                     * class Test7{
351                     *     <E extends Comparable> Map<List<E>, E > foo(E e) {
352                     *         class maptest <@A @B @D E> {
353                     *             Map<List<@A @B @D E>,@A @B @D E> getMap() {
354                     *                 return new HashMap<List<E>,E>();
355                     *             }
356                     *         }
357                     *         return new maptest<E>().getMap();
358                     *    }
359                     *    Map<List<String>,String> shm = foo(new String("hello"));
360                     * }
361                     */
362                source = new String( source +
363                    "// " + src.description + "\n" +
364                    "class "+ testname + "{\n" +
365                    "    <E extends Comparable> Map<List<E>, E > foo(E e) {\n" +
366                    "        class maptest <_As_ _Bs_ _Ds_ E> {\n" +                  // inner class $1maptest
367                    "            Map<List<_As_ _Bs_ _Ds_ E>,_As_ _Bs_ _Ds_ E> getMap() { \n" +
368                    "                return new HashMap<List<E>,E>();\n" +
369                    "            }\n" +
370                    "        }\n" +
371                    "        return new maptest<E>().getMap();\n" +
372                    "   }\n" +
373                    "   Map<List<String>,String> shm = foo(new String(\"hello\"));\n" +
374                    "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
375                    "\n";
376                    hasInnerClass=true;
377                    innerClassname="$1maptest";
378                break;
379        }
380        return imports + source;
381    }
382}
383