test/tools/javac/annotations/typeAnnotations/classfile/CombinationsTargetTest2.java

Tue, 14 May 2013 15:04:06 -0700

author
jjg
date
Tue, 14 May 2013 15:04:06 -0700
changeset 1755
ddb4a2bfcd82
parent 1721
abd153854f16
child 1969
7de231613e4a
permissions
-rw-r--r--

8013852: update reference impl for type-annotations
Reviewed-by: jjg
Contributed-by: wdietl@gmail.com, steve.sides@oracle.com, joel.franck@oracle.com, alex.buckley@oracle.com

jjg@1521 1 /*
darcy@1534 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
jjg@1521 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jjg@1521 4 *
jjg@1521 5 * This code is free software; you can redistribute it and/or modify it
jjg@1521 6 * under the terms of the GNU General Public License version 2 only, as
jjg@1521 7 * published by the Free Software Foundation.
jjg@1521 8 *
jjg@1521 9 * This code is distributed in the hope that it will be useful, but WITHOUT
jjg@1521 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jjg@1521 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jjg@1521 12 * version 2 for more details (a copy is included in the LICENSE file that
jjg@1521 13 * accompanied this code).
jjg@1521 14 *
jjg@1521 15 * You should have received a copy of the GNU General Public License version
jjg@1521 16 * 2 along with this work; if not, write to the Free Software Foundation,
jjg@1521 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jjg@1521 18 *
jjg@1521 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jjg@1521 20 * or visit www.oracle.com if you need additional information or have any
jjg@1521 21 * questions.
jjg@1521 22 */
jjg@1521 23
jjg@1521 24 /*
jjg@1521 25 * @test
jjg@1755 26 * @bug 8005085 8005877 8004829 8005681 8006734 8006775 8006507
jjg@1521 27 * @summary Combinations of Target ElementTypes on (repeated)type annotations.
jjg@1521 28 */
jjg@1521 29
jjg@1521 30 import com.sun.tools.classfile.*;
jjg@1521 31 import java.io.File;
jjg@1521 32
jjg@1521 33 public class CombinationsTargetTest2 extends ClassfileTestHelper {
jjg@1755 34
jjg@1755 35 // Test count helps identify test case in event of failure.
jjg@1521 36 int testcount = 0;
jjg@1755 37
jjg@1755 38 // Base test case template descriptions
jjg@1755 39 enum srce {
jjg@1755 40 src1("(repeating) type annotations on on field in method body",true),
jjg@1755 41 src2("(repeating) type annotations on type parameters, bounds and type arguments", true),
jjg@1755 42 src3("(repeating) type annotations on type parameters of class, method return value in method", true),
jjg@1755 43 src4("(repeating) type annotations on field in anonymous class", false),
jjg@1755 44 src5("(repeating) type annotations on field in anonymous class", false);
jjg@1755 45
jjg@1755 46 String description;
jjg@1755 47 Boolean local;
jjg@1755 48
jjg@1755 49 srce(String desc, Boolean b) {
jjg@1755 50 this.description = this + ": " +desc;
jjg@1755 51 this.local = b;
jjg@1755 52 }
jjg@1755 53 }
jjg@1755 54
jjg@1521 55
jjg@1521 56 String[] ETypes={"TYPE", "FIELD", "METHOD", "PARAMETER", "CONSTRUCTOR",
jjg@1521 57 "LOCAL_VARIABLE", "ANNOTATION_TYPE", "PACKAGE"};
jjg@1521 58
jjg@1521 59 // local class tests will have an inner class.
jjg@1521 60 Boolean hasInnerClass=false;
jjg@1521 61 String innerClassname="";
jjg@1521 62
jjg@1521 63 public static void main(String[] args) throws Exception {
jjg@1521 64 new CombinationsTargetTest2().run();
jjg@1521 65 }
jjg@1521 66
jjg@1521 67 void run() throws Exception {
jjg@1521 68 // Determines which repeat and order in source(ABMix).
jjg@1521 69 Boolean As= false, BDs=true, ABMix=false;
jjg@1521 70 int testrun=0;
jjg@1521 71 Boolean [][] bRepeat = new Boolean[][]{{false,false,false},//no repeats
jjg@1521 72 {true,false,false}, //repeat @A
jjg@1521 73 {false,true,false}, //repeat @B
jjg@1521 74 {true,true,false}, //repeat both
jjg@1521 75 {false,false,true} //repeat mix
jjg@1521 76 };
jjg@1755 77
jjg@1521 78 for(Boolean[] bCombo : bRepeat) {
jjg@1521 79 As=bCombo[0]; BDs=bCombo[1]; ABMix=bCombo[2];
jjg@1521 80 for(String et : ETypes) {
jjg@1521 81 switch(et) {
jjg@1521 82 case "METHOD":
jjg@1755 83 test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src1);
jjg@1755 84 test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
jjg@1755 85 test( 2, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src5);
jjg@1755 86 test( 0, 2, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src5);
jjg@1521 87 break;
jjg@1521 88 case "FIELD":
jjg@1755 89 test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src1);
jjg@1755 90 test( 8, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src2);
jjg@1755 91 test( 6, 0, 0, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src3);
jjg@1755 92 test( 2, 0, 2, 0, As, BDs, ABMix, "CLASS", et, ++testrun, srce.src4);
jjg@1755 93 test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src1);
jjg@1755 94 test( 0, 8, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src2);
jjg@1755 95 test( 0, 6, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src3);
jjg@1755 96 test( 0, 2, 0, 2, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src4);
jjg@1521 97 break;
jjg@1521 98 default:/*TYPE,PARAMETER,LOCAL_VARIABLE,ANNOTATION_TYPE,PACKAGE*/
jjg@1755 99 test( 0, 2, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src4);
jjg@1755 100 test( 0, 2, 0, 0, As, BDs, ABMix, "RUNTIME", et, ++testrun, srce.src5);
jjg@1521 101 break;
jjg@1521 102 }
jjg@1521 103 }
jjg@1521 104 }
jjg@1521 105 }
jjg@1521 106
jjg@1521 107 public void test(int tinv, int tvis, int inv, int vis, Boolean Arepeats,
jjg@1521 108 Boolean BDrepeats, Boolean ABmix, String rtn, String et2,
jjg@1755 109 Integer N, srce source) throws Exception {
jjg@1521 110 ++testcount;
jjg@1521 111 expected_tvisibles = tvis;
jjg@1521 112 expected_tinvisibles = tinv;
jjg@1521 113 expected_visibles = vis;
jjg@1521 114 expected_invisibles = inv;
jjg@1521 115 File testFile = null;
jjg@1521 116 String tname="Test" + N.toString();
jjg@1521 117 hasInnerClass=false;
jjg@1521 118 String testDef = "Test " + testcount + " parameters: tinv=" + tinv +
jjg@1521 119 ", tvis=" + tvis + ", inv=" + inv + ", vis=" + vis +
jjg@1521 120 ", Arepeats=" + Arepeats + ", BDrepeats=" + BDrepeats +
jjg@1521 121 ", ABmix=" + ABmix + ", retention: " + rtn + ", anno2: " +
jjg@1755 122 et2 + ", src=" + source + "\n " + source.description;
jjg@1521 123
jjg@1755 124 if(
jjg@1755 125 // 8005681 - src1,2,3 - skip cases with repeated annotations on new, array, cast.
jjg@1755 126 (( source.equals(srce.src1) || source.equals(srce.src2) ||
jjg@1755 127 source.equals(srce.src3)) && (ABmix || (Arepeats && BDrepeats)))
jjg@1755 128 // 8008928 - src4,5 - this change cause crash with t-a on anon class)
jjg@1755 129 || (source.equals(srce.src4) || source.equals(srce.src5))
jjg@1755 130 ) {
jjg@1755 131 System.out.println(testDef +
jjg@1755 132 "\n 8005681-skip repeated annotations on new,array,cast");
jjg@1755 133 return;
jjg@1755 134 }
jjg@1521 135
jjg@1521 136 println(testDef);
jjg@1521 137 // Create test source and File.
jjg@1521 138 String sourceString = sourceString(tname, rtn, et2, Arepeats,
jjg@1521 139 BDrepeats, ABmix, source);
jjg@1521 140 testFile = writeTestFile(tname+".java", sourceString);
jjg@1521 141 // Compile test source and read classfile.
jjg@1521 142 File classFile = null;
jjg@1521 143 try {
jjg@1521 144 classFile = compile(testFile);
jjg@1521 145 } catch (Error err) {
jjg@1521 146 System.err.println("Failed compile. Source:\n" + sourceString);
jjg@1521 147 throw err;
jjg@1521 148 }
jjg@1521 149 //if sourcString() set hasInnerClass it also set innerClassname.
jjg@1521 150 if(hasInnerClass) {
jjg@1521 151 StringBuffer sb = new StringBuffer(classFile.getAbsolutePath());
jjg@1521 152 classFile=new File(sb.insert(sb.lastIndexOf(".class"),innerClassname).toString());
jjg@1755 153 println("classfile: " + classFile.getAbsolutePath());
jjg@1521 154 }
jjg@1521 155 ClassFile cf = ClassFile.read(classFile);
jjg@1521 156
jjg@1521 157 //Test class,fields and method counts.
jjg@1521 158 test(cf);
jjg@1521 159
jjg@1521 160 for (Field f : cf.fields) {
jjg@1755 161 if(source.local)
jjg@1755 162 test(cf, f, true);
jjg@1755 163 else
jjg@1755 164 test(cf,f);
jjg@1521 165 }
jjg@1521 166 for (Method m: cf.methods) {
jjg@1755 167 if(source.local)
jjg@1755 168 test(cf, m, true);
jjg@1755 169 else
jjg@1755 170 test(cf, m);
jjg@1521 171 }
jjg@1521 172 countAnnotations();
jjg@1521 173 if (errors > 0) {
jjg@1521 174 System.err.println( testDef );
jjg@1521 175 System.err.println( "Source:\n" + sourceString );
jjg@1521 176 throw new Exception( errors + " errors found" );
jjg@1521 177 }
jjg@1521 178 println("Pass");
jjg@1521 179 }
jjg@1521 180
jjg@1521 181 //
jjg@1521 182 // Source for test cases
jjg@1521 183 //
jjg@1521 184 String sourceString(String testname, String retentn, String annot2,
jjg@1521 185 Boolean Arepeats, Boolean BDrepeats, Boolean ABmix,
jjg@1755 186 srce src) {
jjg@1521 187
jjg@1521 188 String As = "@A", Bs = "@B", Ds = "@D";
jjg@1521 189 if(Arepeats) As = "@A @A";
jjg@1521 190 if(BDrepeats) {
jjg@1521 191 Bs = "@B @B";
jjg@1521 192 Ds = "@D @D";
jjg@1521 193 }
jjg@1521 194 if(ABmix) { As = "@A @B"; Bs = "@A @B"; Ds = "@D @D"; }
jjg@1521 195
jjg@1521 196 // Source to check for TYPE_USE and TYPE_PARAMETER annotations.
jjg@1521 197 // Source base (annotations) is same for all test cases.
jjg@1521 198 String source = new String();
jjg@1521 199 String imports = new String("import java.lang.annotation.*; \n" +
jjg@1521 200 "import static java.lang.annotation.RetentionPolicy.*; \n" +
jjg@1521 201 "import static java.lang.annotation.ElementType.*; \n" +
jjg@1521 202 "import java.util.List; \n" +
jjg@1521 203 "import java.util.HashMap; \n" +
jjg@1521 204 "import java.util.Map; \n\n");
jjg@1521 205
jjg@1521 206 String sourceBase = new String("@Retention("+retentn+")\n" +
jjg@1521 207 "@Target({TYPE_USE,_OTHER_})\n" +
darcy@1531 208 "@Repeatable( AC.class )\n" +
jjg@1521 209 "@interface A { }\n\n" +
jjg@1521 210
jjg@1521 211 "@Retention("+retentn+")\n" +
jjg@1521 212 "@Target({TYPE_USE,_OTHER_})\n" +
jjg@1521 213 "@interface AC { A[] value(); }\n\n" +
jjg@1521 214
jjg@1521 215 "@Retention("+retentn+")\n" +
jjg@1521 216 "@Target({TYPE_USE,_OTHER_})\n" +
darcy@1531 217 "@Repeatable( BC.class )\n" +
jjg@1521 218 "@interface B { }\n\n" +
jjg@1521 219
jjg@1521 220 "@Retention("+retentn+")\n" +
jjg@1521 221 "@Target({TYPE_USE,_OTHER_})\n" +
jjg@1521 222 "@interface BC { B[] value(); } \n\n" +
jjg@1521 223
jjg@1521 224 "@Retention("+retentn+")\n" +
jjg@1521 225 "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" +
darcy@1531 226 "@Repeatable(DC.class)\n" +
jjg@1521 227 "@interface D { }\n\n" +
jjg@1521 228
jjg@1521 229 "@Retention("+retentn+")\n" +
jjg@1521 230 "@Target({TYPE_USE,TYPE_PARAMETER,_OTHER_})\n" +
jjg@1521 231 "@interface DC { D[] value(); }\n\n");
jjg@1521 232
jjg@1521 233 // Test case sources with sample generated source
jjg@1521 234 switch(src) {
jjg@1755 235 case src1: // (repeating) type annotations on field in method body
jjg@1521 236 /*
jjg@1521 237 * class Test1 {
jjg@1521 238 * Test1(){}
jjg@1521 239 * // type usage in method body
jjg@1521 240 * String test(Test1 this, String param, String ... vararg) {
jjg@1521 241 * @A @B
jjg@1521 242 * Object o = new @A @B String @A @B [3];
jjg@1521 243 * return (@A @B String) null;
jjg@1521 244 * }}
jjg@1521 245 */
jjg@1521 246 source = new String(
jjg@1755 247 "// " + src.description + "\n" +
jjg@1755 248 "class " + testname + " {\n" +
jjg@1755 249 "" + testname +"(){} \n" +
jjg@1755 250 "// type usage in method body \n" +
jjg@1755 251 "String test("+testname+" this, " +
jjg@1755 252 "String param, String ... vararg) { \n" +
jjg@1755 253 " _As_ _Bs_\n Object o = new _As_ _Bs_ String _As_ _Bs_ [3]; \n" +
jjg@1755 254 " return (_As_ _Bs_ String) null; \n" +
jjg@1755 255 "} \n" +
jjg@1755 256 "} \n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
jjg@1755 257 "\n\n";
jjg@1755 258 break;
jjg@1755 259 case src2: // (repeating) annotations on type parameters, bounds and type arguments in new statement.
jjg@1521 260 /*
jjg@1521 261 * class Test2<T extends Object> {
jjg@1521 262 * Map<List<String>, Integer> map =
jjg@1521 263 * new HashMap<@A @B List<@A @B String>, @A @B Integer>();
jjg@1521 264 * Map<List<String>, Integer> map2 = new @A @B HashMap<>();
jjg@1521 265 * String test(Test2<T> this) { return null;}
jjg@1521 266 * <T> String genericMethod(T t) { return null; }
jjg@1521 267 * }
jjg@1521 268 */
jjg@1521 269 source = new String( source +
jjg@1755 270 "// " + src.description + "\n" +
jjg@1755 271 "class " + testname + "<T extends Object> {\n" +
jjg@1755 272 " Map<List<String>, Integer> map =\n" +
jjg@1755 273 " new HashMap<_As_ _Bs_ List<_As_ _Bs_ String>, _As_ _Bs_ Integer>();\n" +
jjg@1755 274 " Map<List<String>, Integer> map2 = new _As_ _Bs_ HashMap<>();\n" +
jjg@1755 275 " String test(" + testname + "<T> this) { return null;}\n" +
jjg@1755 276 " <T> String genericMethod(T t) { return null; }\n" +
jjg@1755 277 "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
jjg@1755 278 "\n\n";
jjg@1755 279 break;
jjg@1755 280 case src3: // (repeating)annotations on type parameters of class, method return value in method.
jjg@1521 281 /*
jjg@1521 282 * class Test3{
jjg@1521 283 * <E extends Comparable> Map<List<E>, E > foo(E e) {
jjg@1521 284 * class maptest <E> {
jjg@1521 285 * Map<List<E>,E> getMap() {
jjg@1521 286 * Map<List<E>,E> Em = new HashMap<List<@A @B @D E>,@A @B @D E>();
jjg@1521 287 * return Em;
jjg@1521 288 * }
jjg@1521 289 * }
jjg@1521 290 * return new maptest<E>().getMap();
jjg@1521 291 * }
jjg@1521 292 * Map<List<String>,String> shm = foo(new String("hello"));
jjg@1521 293 * }
jjg@1521 294 */
jjg@1521 295 source = new String( source +
jjg@1755 296 "// " + src.description + "\n" +
jjg@1755 297 "class "+ testname + "{\n" +
jjg@1755 298 " <E extends Comparable> Map<List<E>, E > foo(E e) {\n" +
jjg@1755 299 " class maptest <E> {\n" + // inner class $1maptest
jjg@1755 300 " Map<List<E>,E> getMap() { \n" +
jjg@1755 301 " Map<List<E>,E> Em = new HashMap<List<_As_ _Bs_ _Ds_ E>,_As_ _Bs_ _Ds_ E>();\n" +
jjg@1755 302 " return Em;\n" +
jjg@1755 303 " }\n" +
jjg@1755 304 " }\n" +
jjg@1755 305 " return new maptest<E>().getMap();\n" +
jjg@1755 306 " }\n" +
jjg@1755 307 " Map<List<String>,String> shm = foo(new String(\"hello\"));\n" +
jjg@1755 308 "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs).replace("_Ds_",Ds) +
jjg@1755 309 "\n\n";
jjg@1755 310 hasInnerClass=true;
jjg@1755 311 innerClassname="$1maptest";
jjg@1755 312 break;
jjg@1755 313 case src4: // (repeating)annotations on field in anonymous class
jjg@1755 314 /*
jjg@1755 315 * class Test95{
jjg@1755 316 * void mtest( Test95 t){ }
jjg@1755 317 * public void test() {
jjg@1755 318 * mtest( new Test95() {
jjg@1755 319 * @A @A @B @B String data2 = "test";
jjg@1755 320 * });
jjg@1755 321 * }
jjg@1755 322 * }
jjg@1755 323 */
jjg@1755 324 source = new String( source +
jjg@1755 325 "// " + src.description + "\n" +
jjg@1755 326 "class "+ testname + "{\n" +
jjg@1755 327 " void mtest( "+ testname + " t){ }\n" +
jjg@1755 328 " public void test() {\n" +
jjg@1755 329 " mtest( new "+ testname + "() {\n" +
jjg@1755 330 " _As_ _Bs_ String data2 = \"test\";\n" +
jjg@1755 331 " });\n" +
jjg@1755 332 " }\n" +
jjg@1755 333 "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
jjg@1755 334 "\n\n";
jjg@1755 335 hasInnerClass=true;
jjg@1755 336 innerClassname="$1";
jjg@1755 337 break;
jjg@1755 338 case src5: // (repeating)annotations on method in anonymous class
jjg@1755 339 /*
jjg@1755 340 * class Test120{
jjg@1755 341 * void mtest( Test120 t){ }
jjg@1755 342 * public void test() {
jjg@1755 343 * mtest( new Test120() {
jjg@1755 344 * @A @B @A @B String m2(){return null;};
jjg@1755 345 * });
jjg@1755 346 * }
jjg@1755 347 */
jjg@1755 348 source = new String( source +
jjg@1755 349 "// " + src.description + "\n" +
jjg@1755 350 "class "+ testname + "{\n" +
jjg@1755 351 " void mtest( "+ testname + " t){ }\n" +
jjg@1755 352 " public void test() {\n" +
jjg@1755 353 " mtest( new "+ testname + "() {\n" +
jjg@1755 354 " _As_ _Bs_ String m2(){return null;};\n" +
jjg@1755 355 " });\n" +
jjg@1755 356 " }\n" +
jjg@1755 357 "}\n").concat(sourceBase).replace("_OTHER_", annot2).replace("_As_",As).replace("_Bs_",Bs) +
jjg@1755 358 "\n\n";
jjg@1755 359 hasInnerClass=true;
jjg@1755 360 innerClassname="$1";
jjg@1755 361 break;
jjg@1521 362 }
jjg@1521 363 return imports + source;
jjg@1521 364 }
jjg@1521 365 }

mercurial