Wed, 27 Apr 2016 01:34:52 +0800
Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17
1 /*
2 * Copyright (c) 2013, 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 */
24 /*
25 * @test
26 * @bug 8005085 8005681 8008769 8010015
27 * @summary Check (repeating)type annotations on lambda usage.
28 * @run main CombinationsTargetTest3
29 */
31 import com.sun.tools.classfile.*;
32 import java.io.File;
33 import java.util.Vector;
35 public class CombinationsTargetTest3 extends ClassfileTestHelper {
37 // Helps identify test case in event of failure.
38 int testcount = 0;
40 // Known failure cases due to open bugs.
41 Vector<String> skippedTests = new Vector<>();
42 void printSkips() {
43 if(!skippedTests.isEmpty()) {
44 println(skippedTests.size() + " tests were skipped:");
45 for(String t : skippedTests)
46 println(" " + t);
47 }
48 }
50 // Test case descriptions and expected annotation counts.
51 enum srce {
52 src1("type annotations on lambda expression as method arg.",4,0),
53 src2("type annotations on new in single line lambda expression",2,0),
54 src3("type annotations in lambda expression code block",4,0),
55 src4("type annotations in code block with recursion,cast",2,0),
56 src5("type annotations in lambda expression code block",4,0),
57 src6("type annotations on type parm in method reference",4,0),
58 src7("type annotations on inner class field of lambda expression",2,2),
59 src8("type annotations in inner class of lambda expression",4,2),
60 src9("type annotations on static method of interface",4,2);
62 String description;
63 // Expected annotation counts are same for Vis or Invis, but which one
64 // depends on retention type.
65 Integer[] exp = { 0, 0 };
67 // If class to test is inner class, this may be set in SourceString()
68 String innerClassname = null ;
70 // If class to test is not main or inner class; set in sourceString()
71 String altClassName = null;
73 srce(String desc, int e1, int e2) {
74 description = this + ": " +desc;
75 exp[0]=e1;
76 exp[1]=e2;
77 }
78 }
80 // Check for RuntimeInvisible or RuntimeVisible annotations.
81 String[] RType={"CLASS", "RUNTIME"};
83 // This can be a compile only test.
84 static boolean compileonly=false;
86 // Collect failure for end of test report()
87 Vector<String> vFailures = new Vector<>();
89 // pass/fail determined after all tests have run.
90 void report() {
91 if(vFailures.isEmpty()) {
92 printSkips();
93 println("PASS");
94 } else {
95 System.err.println("FAILED: There were failures:");
96 for(String f : vFailures)
97 System.err.println(f);
98 throw new RuntimeException("There were failures. See test log.");
99 }
100 }
102 public static void main(String[] args) throws Exception {
103 if(args.length>0 && args[0].compareTo("compileonly")==0)
104 compileonly=true;
105 new CombinationsTargetTest3().run();
106 }
108 void run() throws Exception {
109 // Determines which repeat and order in source(ABMix).
110 Boolean As= false, BDs=true, ABMix=false;
111 int testrun=0;
112 // A repeats and/or B/D repeats, ABMix for order of As and Bs.
113 Boolean [][] bRepeat = new Boolean[][]{{false,false,false}, //no repeats
114 {true,false,false}, //repeat @A
115 {false,true,false}, //repeat @B
116 {true,true,false}, //repeat both
117 {false,false,true} //repeat mix
118 };
119 // Added ElementType's. All set; not permuted (so far) for this test
120 String et = "TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE";
122 // test loop
123 for(Boolean[] bCombo : bRepeat) {
124 As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2];
125 for(srce src : srce.values())
126 for( String rtype : RType ) {
127 switch( rtype ) {
128 case "RUNTIME":
129 test(0,src.exp[0],0,src.exp[1],As, BDs, ABMix,
130 "RUNTIME", et, ++testrun, src);
131 break;
132 case "CLASS":
133 test(src.exp[0],0,src.exp[1],0,As, BDs, ABMix,
134 "CLASS", et, ++testrun, src);
135 break;
136 }
137 }
138 }
139 report();
140 }
142 // Filter out skipped cases, compile, pass class file to test method,
143 // count annotations and asses results.
144 public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats,
145 Boolean BDrepeats, Boolean ABmix, String rtn, String et2,
146 Integer N, srce source) throws Exception {
147 ++testcount;
148 expected_tvisibles = tvis;
149 expected_tinvisibles = tinv;
150 expected_visibles = vis;
151 expected_invisibles = inv;
152 File testFile = null;
153 String tname="Test" + N.toString();
154 String testDef = "Test " + testcount + " parameters: tinv=" + tinv +
155 ", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis +
156 ", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats +
157 ", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " +
158 et2 + ", src=" + source;
160 // Skip failing cases with bug ID's
161 if ((source.equals(srce.src2) || source.equals(srce.src4) ||
162 source.equals(srce.src5)) &&
163 (ABmix || (Arepeats && BDrepeats))) {
164 skippedTests.add(testDef +
165 "\n--8005681 repeated type-annotations on new/cast/array in" +
166 " inner class in lambda expression.");
167 return;
168 }//8008769 Repeated type-annotations on type parm of local variable
169 else if (source.equals(srce.src6) &&
170 (ABmix || (Arepeats && BDrepeats))) {
171 skippedTests.add(testDef + "\n--8008769 Repeated " +
172 "type-annotations on type parm of local variable");
173 return;
174 }
176 println(testDef);
177 // Create test source and File.
178 String sourceString = sourceString(tname, rtn, et2, Arepeats,
179 BDrepeats, ABmix, source);
180 testFile = writeTestFile(tname+".java", sourceString);
181 // Compile test source and read classfile.
182 File classFile = null;
183 try {
184 classFile = compile(testFile);
185 System.out.println("pass compile: " + tname + ".java");
186 } catch (Error err) {
187 System.err.println("fail compile. Source:\n" + sourceString);
188 throw err;
189 }
190 if(!compileonly) {
191 //check if innerClassname is set
192 String classdir = classFile.getAbsolutePath();
193 if(source.innerClassname != null) {
194 StringBuffer sb = new StringBuffer(classdir);
195 classFile=new File(sb.insert(sb.lastIndexOf(".class"),
196 source.innerClassname).toString());
197 source.innerClassname=null;
198 } else if (source.altClassName != null) {
199 classdir = classdir.substring(0,classdir.lastIndexOf("Test"));
200 classFile=new File(classdir.concat(source.altClassName));
201 source.innerClassname=null;
202 }
203 ClassFile cf = ClassFile.read(classFile);
205 println("Testing classfile: " + cf.getName());
206 //Test class,fields and method counts.
207 test(cf);
209 for (Field f : cf.fields) {
210 test(cf, f);
211 test(cf, f, true);
212 }
213 for (Method m: cf.methods) {
214 test(cf, m);
215 test(cf, m, true);
216 }
218 countAnnotations(); // sets errors=0 before counting.
219 if (errors > 0) {
220 System.err.println( testDef );
221 System.err.println( "Source:\n" + sourceString );
222 vFailures.add(testDef);
223 }
224 }
225 if(errors==0) println("Pass"); println("");
226 }
228 /*
229 * Source definitions for test cases.
230 * To add a test:
231 * Add enum to srce(near top of file) with expected annotation counts.
232 * Add source defintion below.
233 */
234 String sourceString(String testname, String retentn, String annot2,
235 Boolean Arepeats, Boolean BDrepeats, Boolean ABmix,
236 srce src) {
238 String As = "@A", Bs = "@B", Ds = "@D";
239 if(Arepeats) As = "@A @A";
240 if(BDrepeats) {
241 Bs = "@B @B";
242 Ds = "@D @D";
243 }
244 if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; }
246 // Source to check for TYPE_USE and TYPE_PARAMETER annotations.
247 // Source base (annotations) is same for all test cases.
248 String source = new String();
249 String imports = new String("import java.lang.annotation.*; \n" +
250 "import static java.lang.annotation.RetentionPolicy.*; \n" +
251 "import static java.lang.annotation.ElementType.*; \n" +
252 "import java.util.List; \n" +
253 "import java.util.ArrayList;\n\n");
255 String sourceBase = new String(
256 "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @Repeatable( AC.class ) @interface A { }\n" +
257 "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @interface AC { A[] value(); } \n" +
258 "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @Repeatable( BC.class ) @interface B { }\n" +
259 "@Retention("+retentn+") @Target({TYPE_USE,_OTHER_}) @interface BC { B[] value(); } \n" +
260 "@Retention("+retentn+") @Target({TYPE_USE,TYPE_PARAMETER,_OTHER_}) @Repeatable(DC.class) @interface D { }\n" +
261 "@Retention("+retentn+") @Target({TYPE_USE,TYPE_PARAMETER,_OTHER_}) @interface DC { D[] value(); }");
263 // Test case sources with sample generated source
264 switch(src) {
265 case src1: //(repeating) type annotations on lambda expressions.
266 /*
267 * class Test1 {
268 * Test1(){}
269 * interface MapFun<T,R> { R m( T n); }
270 * void meth( MapFun<String,Integer> mf ) {
271 * assert( mf.m("four") == 4);
272 * }
273 * void test(Integer i) {
274 * // lambda expression as method arg
275 * meth( (@A @B String s) -> { @A @B Integer len = s.length(); return len; } );
276 * }}
277 */
278 source = new String( source +
279 "// " + src.description + "\n" +
280 "class " + testname + " {\n" +
281 " " + testname +"(){} \n" +
282 " interface MapFun<T,R> { R m( T n); }\n\n" +
283 " void meth( MapFun<String,Integer> mf ) {\n" +
284 " assert( mf.m(\"four\") == 4);\n" +
285 " }\n\n" +
286 " void test(Integer i) {\n" +
287 " // lambda expression as method arg\n" +
288 " meth( (_As_ _Bs_ String s) -> { _As_ _Bs_ Integer len = s.length(); return len; } );\n" +
289 "}}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
290 "\n";
291 break;
292 case src2: //(repeating) type annotations on new in single line lambda expression.
293 /*
294 * //case2: (repeating) type annotations on new in single lambda expressions.
295 * class Test2{
296 * interface MapFun<T, R> { R m( T n); }
297 * MapFun<Integer, String> its;
298 * void test(Integer i) {
299 * its = a -> "~"+new @A @B Integer(a).toString()+"~";
300 * System.out.println("in: " + i + " out: " + its.m(i));
301 * }}
302 */
303 source = new String( source +
304 "// " + src.description + "\n" +
305 "class " + testname + "{\n" +
306 " interface MapFun<T, R> { R m( T n); }\n" +
307 " MapFun<Integer, String> its;\n" +
308 " void test(Integer i) {\n" +
309 " its = a -> \"~\"+new _As_ _Bs_ Integer(a).toString()+\"~\";\n" +
310 " System.out.println(\"in: \" + i + \" out: \" + its.m(i));\n" +
311 " }\n" +
312 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
313 "\n";
314 break;
315 case src3: //(repeating) type annotations in lambda expression code block.
316 /*
317 * class Test183{
318 * interface MapFun<T, R> { R m( T n); }
319 * MapFun<List<Integer>, String> iLs;
320 * void testm(Integer i) {
321 * iLs = l -> { @A @B @A @B String ret = new String();
322 * for( @A @B @A @B Integer i2 : l)
323 * ret=ret.concat(i2.toString() + " ");
324 * return ret; };
325 * List<Integer> li = new ArrayList<>();
326 * for(int j=0; j<i; j++) li.add(j);
327 * System.out.println(iLs.m(li) );
328 * }}
329 */
330 source = new String( source +
331 "// " + src.description + "\n" +
332 "class "+ testname + "{\n" +
333 " interface MapFun<T, R> { R m( T n); }\n" +
334 " MapFun<List<Integer>, String> iLs;\n" +
335 " void testm(Integer i) {\n" +
336 " iLs = l -> { _As_ _Bs_ String ret = new String();\n" +
337 " for( _As_ _Bs_ Integer i2 : l)\n" +
338 " ret=ret.concat(i2.toString() + \" \");\n" +
339 " return ret; };\n" +
340 " List<Integer> li = new ArrayList<>();\n" +
341 " for(int j=0; j<i; j++) li.add(j);\n" +
342 " System.out.println(iLs.m(li) );\n" +
343 "}\n" +
344 "\n" +
345 " public static void main(String... args) {new " + testname + "().testm(5); }\n" +
346 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
347 "\n";
348 break;
349 case src4: //(repeating) type annotations in code block with recursion,cast
350 /*
351 * class Test194{
352 * interface MapFun<T, R> { R m( T n); }
353 * MapFun<Integer, Double> nf;
354 * void testm(Integer i) {
355 * nf = j -> { return j == 1 ? 1.0 : (@A @B @A @B Double)(nf.m(j-1) * j); };
356 * System.out.println( "nf.m(" + i + "): " + nf.m(i));
357 * }
358 * }
359 */
360 source = new String( source +
361 "// " + src.description + "\n" +
362 "class "+ testname + "{\n" +
363 " interface MapFun<T, R> { R m( T n); }\n" +
364 " MapFun<Integer, Double> nf;\n" +
365 " void testm(Integer i) {\n" +
366 " nf = j -> { return j == 1 ? 1.0 : (_As_ _Bs_ Double)(nf.m(j-1) * j); };\n" +
367 " System.out.println( \"nf.m(\" + i + \"): \" + nf.m(i));\n" +
368 " }\n" +
369 " public static void main(String... args) {new " + testname + "().testm(5); }\n" +
370 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
371 "\n";
372 break;
373 case src5: //(repeating) type annotations in lambda expression code block.
374 /*
375 * class Test180 {
376 * interface MapFun<T, R> { R m( T n); }
377 * MapFun<Integer,List<Integer>> iLi;
378 * void test(Integer i) {
379 * // type parameter use.
380 * iLi = n -> { List<@A @B @A @B Integer> LI = new ArrayList<@A @B @A @B Integer>(n);
381 * for(int nn = n; nn >=0; nn--) LI.add(nn);
382 * return LI; };
383 * List<Integer> li = iLi.m(i);
384 * for(Integer k : li) System.out.print(k);
385 * }
386 * }
387 */
388 source = new String( source +
389 "// " + src.description + "\n" +
390 "class "+ testname + "{\n" +
391 " interface MapFun<T, R> { R m( T n); }\n" +
392 " MapFun<Integer,List<Integer>> iLi;\n" +
393 " void test(Integer i) {\n" +
394 " // type parameter use.\n" +
395 " iLi = n -> { List<_As_ _Bs_ Integer> LI = new ArrayList<_As_ _Bs_ Integer>(n);\n" +
396 " for(int nn = n; nn >=0; nn--) LI.add(nn);\n" +
397 " return LI; };\n" +
398 " List<Integer> li = iLi.m(i);\n" +
399 " for(Integer k : li) System.out.print(k);\n" +
400 "}\n" +
401 " public static void main(String... args) {new " + testname + "().test(5); }\n" +
402 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
403 "\n";
404 break;
405 case src6: //(repeating) type annotations on type parm in method reference.
406 /*
407 * class Test240{
408 * interface PrintString { void print(String s); }
409 * public void printArray(Object[] oa, PrintString ps) {
410 * for(Object o : oa ) ps.print(o.toString());
411 * }
412 * public void test() {
413 * Integer[] intarray = {1,2,3,4,5};
414 * printArray(intarray, @A @B @A @B TPrint::<@A @B @A @B String>print);
415 * }
416 * }
417 * class TPrint {
418 * public static <T> void print(T t) { System.out.println( t.toString()); }
419 * }
420 */
421 source = new String( source +
422 "// " + src.description + "\n" +
423 "class "+ testname + "{\n" +
424 " interface PrintString { void print(String s); }\n" +
425 " public void printArray(Object[] oa, PrintString ps) {\n" +
426 " for(Object o : oa ) ps.print(o.toString());\n" +
427 " }\n" +
428 " public void test() {\n" +
429 " Integer[] intarray = {1,2,3,4,5};\n" +
430 " printArray(intarray, _As_ _Bs_ TPrint::<_As_ _Bs_ String>print);\n" +
431 " }\n" +
432 " public static void main(String... args) {new " + testname + "().test(); }\n" +
433 "}\n\n" +
434 "class TPrint {\n" +
435 " public static <T> void print(T t) { System.out.println( t.toString()); }\n" +
436 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
437 "\n";
438 break;
439 case src7: //(repeating)type annotations in inner class of lambda expression.
440 /*
441 * class Test2{
442 * interface MapFun<T, R> { R m( T n); }
443 * MapFun<Class<?>,String> cs;
444 * void test() {
445 * cs = c -> {
446 * class innerClass {
447 * @A @B Class<?> icc = null;
448 * String getString() { return icc.toString(); }
449 * }
450 * return new innerClass().getString();
451 * };
452 * System.out.println("cs.m : " + cs.m(Integer.class));
453 * }
454 * }
455 */
456 source = new String( source +
457 "// " + src.description + "\n" +
458 "class "+ testname + "{\n" +
459 " interface MapFun<T, R> { R m( T n); }\n" +
460 " MapFun<Class<?>,String> cs;\n" +
461 " void test() {\n" +
462 " cs = c -> {\n" +
463 " class innerClass {\n" +
464 " _As_ _Bs_ Class<?> icc = null;\n" +
465 " innerClass(Class<?> _c) { icc = _c; }\n" +
466 " String getString() { return icc.toString(); }\n" +
467 " }\n" +
468 " return new innerClass(c).getString();\n" +
469 " };\n" +
470 " System.out.println(\"cs.m : \" + cs.m(Integer.class));\n" +
471 " }\n" +
472 "\n" +
473 " public static void main(String... args) {new " + testname + "().test(); }\n" +
474 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
475 "\n";
476 src.innerClassname="$1innerClass";
477 break;
478 case src8: //(repeating)type annotations in inner class of lambda expression.
479 /*
480 * class Test2{
481 * interface MapFun<T, R> { R m( T n); }
482 * MapFun<Class<?>,String> cs;
483 * void test() {
484 * cs = c -> {
485 * class innerClass {
486 * Class<?> icc;
487 * innerClass(@A @B Class<?> _c) { icc = _c; }
488 * @A @B String getString() { return icc.toString(); }
489 * }
490 * return new innerClass(c).getString();
491 * };
492 * System.out.println("cs.m : " + cs.m(Integer.class));
493 * }
494 * }
495 */
496 source = new String( source +
497 "// " + src.description + "\n" +
498 "class "+ testname + "{\n" +
499 " interface MapFun<T, R> { R m( T n); }\n" +
500 " MapFun<Class<?>,String> cs;\n" +
501 " void test() {\n" +
502 " cs = c -> {\n" +
503 " class innerClass {\n" +
504 " Class<?> icc;\n" +
505 " innerClass(_As_ _Bs_ Class<?> _c) { icc = _c; }\n" +
506 " _As_ _Bs_ String getString() { return icc.toString(); }\n" +
507 " }\n" +
508 " return new innerClass(c).getString();\n" +
509 " };\n" +
510 " System.out.println(\"cs.m : \" + cs.m(Integer.class));\n" +
511 " }\n" +
512 "\n" +
513 " public static void main(String... args) {new " + testname + "().test(); }\n" +
514 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
515 "\n";
516 src.innerClassname="$1innerClass";
517 break;
518 case src9: //(repeating)type annotations on static method of interface
519 /*
520 * class Test90{
521 * interface I {
522 * static @A @B @A @B String m() { @A @B @A @B String ret = "I.m"; return ret; }
523 * }
524 * }
525 */
526 source = new String( source +
527 "// " + src.description + "\n" +
528 "class "+ testname + "{\n" +
529 " interface I { \n" +
530 " static _As_ _Bs_ String m() { _As_ _Bs_ String ret = \"I.m\"; return ret; }\n" +
531 " }\n" +
532 "}\n\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
533 "\n";
534 src.innerClassname="$I";
535 break;
536 }
537 return imports + source;
538 }
539 }