test/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java

changeset 1641
195b71850b56
parent 1589
87884cd0fea3
child 2250
66570bfdbdd7
equal deleted inserted replaced
1640:fa24eba012bd 1641:195b71850b56
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 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 20 * or visit www.oracle.com if you need additional information or have any
21 * questions. 21 * questions.
22 */ 22 */
23 23
24 /** 24 /*
25 * @test 25 * @test
26 * @bug 7195131 26 * @bug 7151010 8006547 8007766
27 * @author sogoel 27 * @summary Default test cases for running combinations for Target values
28 * @summary Combo test for all possible combinations for Target values
29 * @ignore 8008339 Test TargetAnnoCombo.java is broken
30 * @build Helper 28 * @build Helper
31 * @compile TargetAnnoCombo.java TestCaseGenerator.java
32 * @run main TargetAnnoCombo 29 * @run main TargetAnnoCombo
33 */ 30 */
34 31
32 import java.util.Set;
33 import java.util.List;
35 import java.io.IOException; 34 import java.io.IOException;
35 import java.lang.annotation.ElementType;
36 import java.util.ArrayList; 36 import java.util.ArrayList;
37 import java.util.Arrays; 37 import java.util.Arrays;
38 import java.util.HashSet; 38 import java.util.EnumSet;
39 import java.util.Set;
40 import javax.tools.Diagnostic; 39 import javax.tools.Diagnostic;
41 import javax.tools.DiagnosticCollector; 40 import javax.tools.DiagnosticCollector;
42 import javax.tools.JavaFileObject; 41 import javax.tools.JavaFileObject;
43 42
44 /* 43 import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
45 * TargetAnnoCombo gets a list of test case numbers using TestCaseGenerator. 44 import static java.lang.annotation.ElementType.CONSTRUCTOR;
46 * For each of the test case number, @Target sets for base and container annotations 45 import static java.lang.annotation.ElementType.FIELD;
47 * are determined, source files are generated, compiled, and the result is verified 46 import static java.lang.annotation.ElementType.METHOD;
48 * based on if the @Target set for base and container is a positive or negative combination. 47 import static java.lang.annotation.ElementType.PARAMETER;
49 * 48 import static java.lang.annotation.ElementType.TYPE;
50 * @Target sets for base and container annotations are determined using a bit mapping of 49 import static java.lang.annotation.ElementType.PACKAGE;
51 * 10 ElementType enum constants defined in JDK8. 50 import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
52 * 51 import static java.lang.annotation.ElementType.TYPE_USE;
53 * Bit Target value 52 import static java.lang.annotation.ElementType.TYPE_PARAMETER;
54 * 0 "ElementType.ANNOTATION_TYPE"
55 * 1 "ElementType.CONSTRUCTOR"
56 * 2 "ElementType.FIELD"
57 * 3 "ElementType.LOCAL_VARIABLE"
58 * 4 "ElementType.METHOD"
59 * 5 "ElementType.TYPE"
60 * 6 "ElementType.PARAMETER"
61 * 7 "ElementType.PACKAGE"
62 * 8 "ElementType.TYPE_USE"
63 * 9 "ElementType.TYPE_PARAMETER"
64 *
65 * Group 1:
66 * 20 bits mapping, representing a test case number, is used for all target set
67 * combinations ( 0 to 1048575 ) including empty @Target sets => @Target({}).
68 * From this 20 bits, 10 bits are for base followed by 10 bits for container
69 * where each bit maps to an ElementType enum constant defined in JDK8.
70 *
71 * Examples:
72 * Test case number: 4, binary: 100 => container=100, base=[], container=["ElementType.FIELD"]
73 * Test case number: 1003575, binary: 11110101000000110111 => base=1111010100, container=0000110111;
74 * base=["ElementType.PARAMETER", "ElementType.TYPE_USE", "ElementType.METHOD", "ElementType.FIELD", "ElementType.PACKAGE", "ElementType.TYPE_PARAMETER"],
75 * container=["ElementType.TYPE", "ElementType.METHOD", "ElementType.ANNOTATION_TYPE", "ElementType.CONSTRUCTOR", "ElementType.FIELD"]
76 *
77 * In the following groups, no @Target set is represented by null.
78 * Group 2:
79 * @Target is not defined on base.
80 * Target sets for container are determined using the 10-bit binary number
81 * resulting in 1024 test cases, mapping them to test case numbers from
82 * 1048576 to (1048576 + 1023) => 1048576 to 1049599.
83 *
84 * Example:
85 * Test case number: 1048587 => 1048587 - 1048576 = test case 11 in Group 2, binary: 1011 =>
86 * base = null,
87 * container = ["ElementType.ANNOTATION_TYPE","ElementType.CONSTRUCTOR","ElementType.LOCAL_VARIABLE"]
88 *
89 * Group 3:
90 * @Target is not defined on container
91 * Target sets for base are determined using the 10-bit binary number
92 * resulting in 1024 test cases, mapping them to test case numbers from
93 * 1049600 to (1049600 + 1023) => 1049600 to 1050623.
94 *
95 * Example:
96 * Test case number: 1049708 => 1049708 - 1049600 = test case 108 in Group 3, binary: 1101100 =>
97 * base = ["ElementType.FIELD", "ElementType.LOCAL_VARIABLE", "ElementType.TYPE", "ElementType.PARAMETER"],
98 * container = null
99 *
100 * For the above group, test case number: 1049855 gives compiler error, JDK-8006547 filed
101 *
102 * Group 4:
103 * @Target not defined for both base and container annotations.
104 *
105 * This is the last test and corresponds to test case number 1050624. base=null, container=null
106 *
107 * Examples to run this test:
108 * 1. Run a specific test case number:
109 * ${JTREG} -DTestCaseNum=10782 -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
110 * 2. Run specific number of tests:
111 * ${JTREG} -DNumberOfTests=4 -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
112 * 3. Run specific number of tests with a seed:
113 * ${JTREG} -DNumberOfTests=4 -DTestSeed=-972894659 -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
114 * 4. Run tests in default mode (number of tests = 1000):
115 * ${JTREG} -DTestMode=DEFAULT -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
116 * 5. Run all tests (FULL mode):
117 * ${JTREG} -DTestMode=FULL -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
118 *
119 */
120 53
121 public class TargetAnnoCombo { 54 public class TargetAnnoCombo {
55
56 static final String TESTPKG = "testpkg";
57
58 // Set it to true to get more debug information including base and container
59 // target sets for a given test case.
60 static final boolean DEBUG = false;
61
62 // Define constant target sets to be used for the combination of the target values.
63 final static Set<ElementType> noSet = null;
64 final static Set<ElementType> empty = EnumSet.noneOf(ElementType.class);
65
66 // [TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE,
67 // PACKAGE, TYPE_PARAMETER, TYPE_USE]
68 final static Set<ElementType> allTargets = EnumSet.allOf(ElementType.class);
69
70 // [TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE,
71 // PACKAGE]
72 final static Set<ElementType> jdk7 = EnumSet.range(TYPE, PACKAGE);
73
74 // [TYPE_USE, TYPE_PARAMETER]
75 final static Set<ElementType> jdk8 = EnumSet.range(TYPE_PARAMETER, TYPE_USE);
76
77 // List of test cases to run. This list is created in generate().
78 // To run a specific test cases add case number in @run main line.
79 List<TestCase> testCases = new ArrayList<TestCase>();
80
122 int errors = 0; 81 int errors = 0;
123 static final String TESTPKG = "testpkg"; 82
124 /* 83 // Identify test cases that fail.
125 * Set it to true to get more debug information including base and 84 enum IgnoreKind {
126 * container target sets for a given test case number 85 RUN,
127 */ 86 IGNORE
128 static final boolean DEBUG = false; 87 };
129 88
130 // JDK 5/6/7/8 Targets 89 private class TestCase {
131 static final String[] targetVals = {"ElementType.ANNOTATION_TYPE", 90
132 "ElementType.CONSTRUCTOR", "ElementType.FIELD", 91 private Set<ElementType> baseAnnotations;
133 "ElementType.LOCAL_VARIABLE", "ElementType.METHOD", 92 private Set<ElementType> containerAnnotations;
134 "ElementType.TYPE", "ElementType.PARAMETER", 93 private IgnoreKind ignore;
135 "ElementType.PACKAGE", "ElementType.TYPE_USE", 94
136 "ElementType.TYPE_PARAMETER"}; 95 public TestCase(Set<ElementType> baseAnnotations, Set<ElementType> containerAnnotations) {
137 96 this(baseAnnotations, containerAnnotations, IgnoreKind.RUN);
138 // TYPE_USE and TYPE_PARAMETER (added in JDK8) are not part of default Target set 97 }
139 static final int DEFAULT_TARGET_CNT = 8; 98
99 public TestCase(Set<ElementType> baseAnnotations, Set<ElementType> containerAnnotations,
100 IgnoreKind ignoreKind) {
101 this.baseAnnotations = baseAnnotations;
102 this.containerAnnotations = containerAnnotations;
103 this.ignore = ignoreKind;
104 }
105
106 public Set getBaseAnnotations() {
107 return baseAnnotations;
108 }
109
110 public Set getContainerAnnotations() {
111 return containerAnnotations;
112 }
113
114 public boolean isIgnored() {
115 return ignore == IgnoreKind.IGNORE;
116 }
117
118 // Determine if a testCase should compile or not.
119 private boolean isValidSubSet() {
120 /*
121 * RULE 1: conAnnoTarget should be a subset of baseAnnoTarget
122 * RULE 2: For empty @Target ({}) - annotation cannot be applied anywhere
123 * - Empty sets for both is valid
124 * - Empty baseTarget set is invalid with non-empty conTarget set
125 * - Non-empty baseTarget set is valid with empty conTarget set
126 * RULE 3: For no @Target specified - annotation can be applied to any JDK 7 targets
127 * - No @Target for both is valid
128 * - No @Target for baseTarget set with @Target conTarget set is valid
129 * - @Target for baseTarget set with no @Target for conTarget is invalid
130 */
131
132
133 /* If baseAnno has no @Target, Foo can be either applied to @Target specified
134 * for container annotation else will be applicable for all default targets
135 * if no @Target is present for container annotation.
136 * In both cases, the set will be a valid set with no @Target for base annotation
137 */
138 if (baseAnnotations == null) {
139 if (containerAnnotations == null) {
140 return true;
141 }
142 return !(containerAnnotations.contains(TYPE_USE) ||
143 containerAnnotations.contains(TYPE_PARAMETER));
144 }
145
146 Set<ElementType> tempBaseSet = EnumSet.noneOf(ElementType.class);
147 tempBaseSet.addAll(baseAnnotations);
148 // If BaseAnno has TYPE, then ANNOTATION_TYPE is allowed by default.
149 if (baseAnnotations.contains(TYPE)) {
150 tempBaseSet.add(ANNOTATION_TYPE);
151 }
152
153 // If containerAnno has no @Target, only valid case if baseAnnoTarget has
154 // all targets defined else invalid set.
155 if (containerAnnotations == null) {
156 return tempBaseSet.containsAll(jdk7);
157 }
158
159 // At this point, neither conAnnoTarget or baseAnnoTarget are null.
160 if (containerAnnotations.isEmpty()) {
161 return true;
162 }
163
164 // At this point, conAnnoTarget is non-empty.
165 if (baseAnnotations.isEmpty()) {
166 return false;
167 }
168
169 // At this point, neither conAnnoTarget or baseAnnoTarget are empty.
170 return tempBaseSet.containsAll(containerAnnotations);
171 }
172 }
140 173
141 public static void main(String args[]) throws Exception { 174 public static void main(String args[]) throws Exception {
142
143 /* maxTestNum = (base and container combinations of targetVals elems [0 - 1048575 combos])
144 * + (combinations where base or container has no Target [1024 combos])
145 * + (no -1 even though 1st test is number 0 as last test is where both
146 * base and container have no target)
147 */
148
149 int maxTestNum = (int)Math.pow(2, 2*targetVals.length) + 2*(int)Math.pow(2, targetVals.length);
150 TestCaseGenerator tcg = new TestCaseGenerator(maxTestNum);
151 TargetAnnoCombo tac = new TargetAnnoCombo(); 175 TargetAnnoCombo tac = new TargetAnnoCombo();
152 176 // Generates all test cases to be run.
177 tac.generate();
178 List<Integer> cases = new ArrayList<Integer>();
179 for (int i = 0; i < args.length; i++) {
180 cases.add(Integer.parseInt(args[i]));
181 }
182 if (cases.isEmpty()) {
183 tac.run();
184 } else {
185 for (int index : cases) {
186 tac.executeTestCase(tac.testCases.get(index), index);
187 }
188 }
189 }
190
191 private void generate() {
192 // Adding test cases to run.
193 testCases.addAll(Arrays.asList(
194 // No base target against no container target.
195 new TestCase(noSet, noSet),
196 // No base target against empty container target.
197 new TestCase(noSet, empty),
198 // No base target against TYPE_USE only container target.
199 new TestCase(noSet, less(jdk8, TYPE_PARAMETER)),
200 // No base target against TYPE_PARAMETER only container target.
201 new TestCase(noSet, less(jdk8, TYPE_USE)),
202 // No base target against TYPE_USE + TYPE_PARAMETER only container target.
203 new TestCase(noSet, jdk8),
204 // No base target against TYPE_USE + some selection of jdk7 targets.
205 new TestCase(noSet,
206 plus(EnumSet.range(TYPE, LOCAL_VARIABLE), TYPE_USE)),
207 // No base target against TYPE_PARAMETER + some selection of jdk7 targets.
208 new TestCase(noSet,
209 plus(EnumSet.range(TYPE, LOCAL_VARIABLE), TYPE_PARAMETER)),
210 // No base target against each jdk7 target alone as container target.
211 new TestCase(noSet, plus(empty, TYPE)),
212 new TestCase(noSet, plus(empty, PARAMETER)),
213 new TestCase(noSet, plus(empty, PACKAGE)),
214 new TestCase(noSet, plus(empty, METHOD)),
215 new TestCase(noSet, plus(empty, LOCAL_VARIABLE)),
216 new TestCase(noSet, plus(empty, FIELD)),
217 new TestCase(noSet, plus(empty, CONSTRUCTOR)),
218 new TestCase(noSet, plus(empty, ANNOTATION_TYPE)),
219 // Empty base target against no container target.
220 new TestCase(empty, noSet),
221 // Empty base target against empty container target.
222 new TestCase(empty, empty),
223 // Empty base target against any lone container target.
224 new TestCase(empty, plus(empty, TYPE)),
225 new TestCase(empty, plus(empty, PARAMETER)),
226 new TestCase(empty, plus(empty, PACKAGE)),
227 new TestCase(empty, plus(empty, METHOD)),
228 new TestCase(empty, plus(empty, LOCAL_VARIABLE)),
229 new TestCase(empty, plus(empty, FIELD)),
230 new TestCase(empty, plus(empty, CONSTRUCTOR)),
231 new TestCase(empty, plus(empty, ANNOTATION_TYPE)),
232 new TestCase(empty, less(jdk8, TYPE_USE)),
233 new TestCase(empty, less(jdk8, TYPE_PARAMETER)),
234 // No container target against all all-but one jdk7 targets.
235 new TestCase(less(jdk7, TYPE), noSet),
236 new TestCase(less(jdk7, PARAMETER), noSet),
237 new TestCase(less(jdk7, PACKAGE), noSet),
238 new TestCase(less(jdk7, METHOD), noSet),
239 new TestCase(less(jdk7, LOCAL_VARIABLE), noSet),
240 new TestCase(less(jdk7, FIELD), noSet),
241 new TestCase(less(jdk7, CONSTRUCTOR), noSet),
242 new TestCase(less(jdk7, ANNOTATION_TYPE), noSet),
243 // No container against all but TYPE and ANNOTATION_TYPE
244 new TestCase(less(jdk7, TYPE, ANNOTATION_TYPE), noSet),
245 // No container against jdk7 targets.
246 new TestCase(jdk7, noSet),
247 // No container against jdk7 targets plus one or both of TYPE_USE, TYPE_PARAMETER
248 new TestCase(plus(jdk7, TYPE_USE), noSet),
249 new TestCase(plus(jdk7, TYPE_PARAMETER), noSet),
250 new TestCase(allTargets, noSet),
251 // Empty container target against any lone target.
252 new TestCase(plus(empty, TYPE), empty),
253 new TestCase(plus(empty, PARAMETER), empty),
254 new TestCase(plus(empty, PACKAGE), empty),
255 new TestCase(plus(empty, METHOD), empty),
256 new TestCase(plus(empty, LOCAL_VARIABLE), empty),
257 new TestCase(plus(empty, FIELD), empty),
258 new TestCase(plus(empty, CONSTRUCTOR), empty),
259 new TestCase(plus(empty, ANNOTATION_TYPE), empty),
260 new TestCase(plus(empty, TYPE_USE), empty),
261 new TestCase(plus(empty, TYPE_PARAMETER), empty),
262 // All base targets against all container targets.
263 new TestCase(allTargets, allTargets),
264 // All base targets against all but one container targets.
265 new TestCase(allTargets, less(allTargets, TYPE)),
266 new TestCase(allTargets, less(allTargets, PARAMETER)),
267 new TestCase(allTargets, less(allTargets, PACKAGE)),
268 new TestCase(allTargets, less(allTargets, METHOD)),
269 new TestCase(allTargets, less(allTargets, LOCAL_VARIABLE)),
270 new TestCase(allTargets, less(allTargets, FIELD)),
271 new TestCase(allTargets, less(allTargets, CONSTRUCTOR)),
272 new TestCase(allTargets, less(allTargets, ANNOTATION_TYPE)),
273 new TestCase(allTargets, less(allTargets, TYPE_USE)),
274 new TestCase(allTargets, less(allTargets, TYPE_PARAMETER)),
275 // All container targets against all but one base targets.
276 new TestCase(less(allTargets, TYPE), allTargets),
277 new TestCase(less(allTargets, PARAMETER), allTargets),
278 new TestCase(less(allTargets, PACKAGE), allTargets),
279 new TestCase(less(allTargets, METHOD), allTargets),
280 new TestCase(less(allTargets, LOCAL_VARIABLE), allTargets),
281 new TestCase(less(allTargets, FIELD), allTargets),
282 new TestCase(less(allTargets, CONSTRUCTOR), allTargets),
283 new TestCase(less(allTargets, ANNOTATION_TYPE), allTargets),
284 new TestCase(less(allTargets, TYPE_USE), allTargets),
285 new TestCase(less(allTargets, TYPE_PARAMETER), allTargets)));
286 // Generates 100 test cases for any lone base target contained in Set
287 // allTargets against any lone container target.
288 for (ElementType b : allTargets) {
289 for (ElementType c : allTargets) {
290 testCases.add(new TestCase(plus(empty, b), plus(empty, c)));
291 }
292 }
293 }
294
295 void run() throws Exception {
153 int testCtr = 0; 296 int testCtr = 0;
154 int testCase = -1; 297 for (TestCase tc : testCases) {
155 while ( (testCase=tcg.getNextTestCase()) != -1 ) { 298 if (!tc.isIgnored()) {
156 tac.executeTestCase(testCase, maxTestNum); 299 executeTestCase(tc, testCases.indexOf(tc));
157 testCtr++; 300 testCtr++;
158 } 301 }
159 302 }
160 System.out.println("Total tests run: " + testCtr); 303 System.out.println("Total tests run: " + testCtr);
161 if (tac.errors > 0) 304 if (errors > 0) {
162 throw new Exception(tac.errors + " errors found"); 305 throw new Exception(errors + " errors found");
163 } 306 }
164 307 }
165 /* 308
166 * For given testCase, determine the base and container annotation Target sets, 309 private void executeTestCase(TestCase testCase, int index) {
167 * get if testCase should compile, get test source file(s), get compilation result and verify. 310 debugPrint("Test case number = " + index);
168 * 311 debugPrint(" => baseAnnoTarget = " + testCase.getBaseAnnotations());
169 */ 312 debugPrint(" => containerAnnoTarget = " + testCase.getContainerAnnotations());
170 private void executeTestCase(int testCase, int maxTestNum) { 313
171 314 String className = "TC" + index;
172 // Determine base and container annotation Target sets for the testCase 315 boolean shouldCompile = testCase.isValidSubSet();
173 Set<String> baseAnnoTarget = null; 316 Iterable<? extends JavaFileObject> files = getFileList(className, testCase, shouldCompile);
174 Set<String> conAnnoTarget = null; 317 // Get result of compiling test src file(s).
175
176 //Number of base and container combinations [0 - 1048575 combos]
177 int baseContCombos = (int)Math.pow(2, 2*targetVals.length);
178 //Number of either base or container combinations when one of them has no @Target [1024 combos]
179 int targetValsCombos = (int)Math.pow(2, targetVals.length);
180
181 if (testCase >= baseContCombos) {
182 //Base annotation do not have @Target
183 if (testCase < baseContCombos + targetValsCombos) {
184 baseAnnoTarget = null;
185 conAnnoTarget = getSetFromBitVec(Integer.toBinaryString(testCase - baseContCombos));
186 } else if (testCase < baseContCombos + 2*targetValsCombos) {
187 //Container annotation do not have @Target
188 baseAnnoTarget = getSetFromBitVec(Integer.toBinaryString(testCase - baseContCombos - targetValsCombos));
189 conAnnoTarget = null;
190 } else {
191 //Both Base and Container annotation do not have @Target
192 baseAnnoTarget = null;
193 conAnnoTarget = null;
194 }
195 } else {
196 //TestCase number is represented as 10-bits for base followed by container bits
197 String bin = Integer.toBinaryString(testCase);
198 String base="", cont=bin;
199 if (bin.length() > targetVals.length){
200 base = bin.substring(0, bin.length() - targetVals.length);
201 cont = bin.substring(bin.length() - targetVals.length,bin.length());
202 }
203 baseAnnoTarget = getSetFromBitVec(base);
204 conAnnoTarget = getSetFromBitVec(cont);
205 }
206
207 debugPrint("Test case number = " + testCase + " => binary = " + Integer.toBinaryString(testCase));
208 debugPrint(" => baseAnnoTarget = " + baseAnnoTarget);
209 debugPrint(" => containerAnnoTarget = " + conAnnoTarget);
210
211 // Determine if a testCase should compile or not
212 String className = "TC" + testCase;
213 boolean shouldCompile = isValidSubSet(baseAnnoTarget, conAnnoTarget);
214
215 // Get test source file(s)
216 Iterable<? extends JavaFileObject> files = getFileList(className, baseAnnoTarget,
217 conAnnoTarget, shouldCompile);
218
219 // Get result of compiling test src file(s)
220 boolean result = getCompileResult(className, shouldCompile, files); 318 boolean result = getCompileResult(className, shouldCompile, files);
221 319 // List test src code if test fails.
222 // List test src code if test fails 320 if (!result) {
223 if(!result) { 321 System.out.println("FAIL: Test " + index);
224 System.out.println("FAIL: Test " + testCase);
225 try { 322 try {
226 for (JavaFileObject f: files) { 323 for (JavaFileObject f : files) {
227 System.out.println("File: " + f.getName() + "\n" + f.getCharContent(true)); 324 System.out.println("File: " + f.getName() + "\n" + f.getCharContent(true));
228 } 325 }
229 } catch (IOException ioe) { 326 } catch (IOException ioe) {
230 System.out.println("Exception: " + ioe); 327 System.out.println("Exception: " + ioe);
231 } 328 }
232 } else { 329 } else {
233 debugPrint("PASS: Test " + testCase); 330 debugPrint("PASS: Test " + index);
234 } 331 }
235 } 332
236 333 }
237 // Get a Set<String> based on bits that are set to 1 334
238 public Set<String> getSetFromBitVec(String bitVec) { 335 // Create src code and corresponding JavaFileObjects.
239 Set<String> ret = new HashSet<>(); 336 private Iterable<? extends JavaFileObject> getFileList(String className,
240 char[] bit = bitVec.toCharArray(); 337 TestCase testCase, boolean shouldCompile) {
241 for (int i=bit.length-1, j=0; i>=0; i--, j++){ 338 Set<ElementType> baseAnnoTarget = testCase.getBaseAnnotations();
242 if (bit[i] == '1') { 339 Set<ElementType> conAnnoTarget = testCase.getContainerAnnotations();
243 ret.add(targetVals[j]); 340 String srcContent = "";
244 } 341 String pkgInfoContent = "";
245 } 342 String template = Helper.template;
246 return ret; 343 String baseTarget = "", conTarget = "";
247 } 344
248 345 String target = Helper.ContentVars.TARGET.getVal();
249 // Compile the test source file(s) and return test result 346 if (baseAnnoTarget != null) {
347 String tmp = target.replace("#VAL", convertToString(baseAnnoTarget).toString());
348 baseTarget = tmp.replace("[", "{").replace("]", "}");
349 }
350 if (conAnnoTarget != null) {
351 String tmp = target.replace("#VAL", convertToString(conAnnoTarget).toString());
352 conTarget = tmp.replace("[", "{").replace("]", "}");
353 }
354
355 String annoData = Helper.ContentVars.IMPORTSTMTS.getVal()
356 + conTarget
357 + Helper.ContentVars.CONTAINER.getVal()
358 + baseTarget
359 + Helper.ContentVars.REPEATABLE.getVal()
360 + Helper.ContentVars.BASE.getVal();
361
362 JavaFileObject pkgInfoFile = null;
363
364 // If shouldCompile = true and no @Target is specified for container annotation,
365 // then all 8 ElementType enum constants are applicable as targets for
366 // container annotation.
367 if (shouldCompile && conAnnoTarget == null) {
368 Set<ElementType> copySet = EnumSet.noneOf(ElementType.class);
369 copySet.addAll(jdk7);
370 conAnnoTarget = copySet;
371 }
372
373 if (shouldCompile) {
374 boolean isPkgCasePresent = conAnnoTarget.contains(PACKAGE);
375 String repeatableAnno = Helper.ContentVars.BASEANNO.getVal()
376 + " " + Helper.ContentVars.BASEANNO.getVal();
377 for (ElementType s : conAnnoTarget) {
378 String replaceStr = "/*" + s.name() + "*/";
379 if (s.name().equalsIgnoreCase("PACKAGE")) {
380 //Create packageInfo file.
381 String pkgInfoName = TESTPKG + "." + "package-info";
382 pkgInfoContent = repeatableAnno + "\npackage " + TESTPKG + ";" + annoData;
383 pkgInfoFile = Helper.getFile(pkgInfoName, pkgInfoContent);
384 } else {
385 template = template.replace(replaceStr, repeatableAnno);
386 if (!isPkgCasePresent) {
387 srcContent = template.replace(
388 "/*ANNODATA*/", annoData).replace("#ClassName", className);
389 } else {
390 replaceStr = "/*PACKAGE*/";
391 String tmp = template.replace(replaceStr, "package " + TESTPKG + ";");
392 srcContent = tmp.replace("#ClassName", className);
393 }
394 }
395 }
396 } else {
397 // For invalid cases, compilation should fail at declaration site.
398 template = "class #ClassName {}";
399 srcContent = annoData + template.replace("#ClassName", className);
400 }
401 JavaFileObject srcFile = Helper.getFile(className, srcContent);
402 Iterable<? extends JavaFileObject> files = null;
403 if (pkgInfoFile != null) {
404 files = Arrays.asList(pkgInfoFile, srcFile);
405 } else {
406 files = Arrays.asList(srcFile);
407 }
408 return files;
409 }
410
411 // Compile the test source file(s) and return test result.
250 private boolean getCompileResult(String className, boolean shouldCompile, 412 private boolean getCompileResult(String className, boolean shouldCompile,
251 Iterable<? extends JavaFileObject> files) { 413 Iterable<? extends JavaFileObject> files) {
252 414
253 DiagnosticCollector<JavaFileObject> diagnostics = 415 DiagnosticCollector<JavaFileObject> diagnostics =
254 new DiagnosticCollector<JavaFileObject>(); 416 new DiagnosticCollector<JavaFileObject>();
255 Helper.compileCode(diagnostics, files); 417 Helper.compileCode(diagnostics, files);
256 418 // Test case pass or fail.
257 // Test case pass or fail
258 boolean ok = false; 419 boolean ok = false;
259
260 String errMesg = ""; 420 String errMesg = "";
261 int numDiags = diagnostics.getDiagnostics().size(); 421 int numDiags = diagnostics.getDiagnostics().size();
262
263 if (numDiags == 0) { 422 if (numDiags == 0) {
264 if (shouldCompile) { 423 if (shouldCompile) {
265 debugPrint("Test passed, compiled as expected."); 424 debugPrint("Test passed, compiled as expected.");
266 ok = true; 425 ok = true;
267 } else { 426 } else {
268 errMesg = "Test failed, compiled unexpectedly."; 427 errMesg = "Test failed, compiled unexpectedly.";
269 ok = false; 428 ok = false;
270 } 429 }
271 } else { 430 } else {
272 if (shouldCompile) { 431 if (shouldCompile) {
273 // did not compile 432 // did not compile.
274 errMesg = "Test failed, did not compile."; 433 errMesg = "Test failed, did not compile.";
275 ok = false; 434 ok = false;
276 } else { 435 } else {
277 // Error in compilation as expected 436 // Error in compilation as expected.
278 String expectedErrKey = "compiler.err.invalid.repeatable." + 437 String expectedErrKey = "compiler.err.invalid.repeatable."
279 "annotation.incompatible.target"; 438 + "annotation.incompatible.target";
280 for (Diagnostic<?> d : diagnostics.getDiagnostics()) { 439 for (Diagnostic<?> d : diagnostics.getDiagnostics()) {
281 if((d.getKind() == Diagnostic.Kind.ERROR) && 440 if ((d.getKind() == Diagnostic.Kind.ERROR)
282 d.getCode().contains(expectedErrKey)) { 441 && d.getCode().contains(expectedErrKey)) {
283 // Error message as expected 442 // Error message as expected.
284 debugPrint("Error message as expected."); 443 debugPrint("Error message as expected.");
285 ok = true; 444 ok = true;
286 break; 445 break;
287 } else { 446 } else {
288 // error message is incorrect 447 // error message is incorrect.
289 ok = false; 448 ok = false;
290 } 449 }
291 } 450 }
292 if (!ok) { 451 if (!ok) {
293 errMesg = "Incorrect error received when compiling " + 452 errMesg = "Incorrect error received when compiling "
294 className + ", expected: " + expectedErrKey; 453 + className + ", expected: " + expectedErrKey;
295 } 454 }
296 } 455 }
297 } 456 }
298 457
299 if(!ok) { 458 if (!ok) {
300 error(errMesg); 459 error(errMesg);
301 for (Diagnostic<?> d : diagnostics.getDiagnostics()) 460 for (Diagnostic<?> d : diagnostics.getDiagnostics()) {
302 System.out.println(" Diags: " + d); 461 System.out.println(" Diags: " + d);
462 }
303 } 463 }
304 return ok; 464 return ok;
305 } 465 }
306 466
467 private Set<ElementType> less(Set<ElementType> base, ElementType... sub) {
468 Set<ElementType> res = EnumSet.noneOf(ElementType.class);
469 res.addAll(base);
470 for (ElementType t : sub) {
471 res.remove(t);
472 }
473 return res;
474 }
475
476 private Set<ElementType> plus(Set<ElementType> base, ElementType... add) {
477 Set<ElementType> res = EnumSet.noneOf(ElementType.class);
478 res.addAll(base);
479 for (ElementType t : add) {
480 res.add(t);
481 }
482 return res;
483 }
484
485 // Iterate target set and add "ElementType." in front of every target type.
486 private List<String> convertToString(Set<ElementType> annoTarget) {
487 if (annoTarget == null) {
488 return null;
489 }
490 List<String> annoTargets = new ArrayList<String>();
491 for (ElementType e : annoTarget) {
492 annoTargets.add("ElementType." + e.name());
493 }
494 return annoTargets;
495 }
496
307 private void debugPrint(String string) { 497 private void debugPrint(String string) {
308 if(DEBUG) 498 if (DEBUG) {
309 System.out.println(string); 499 System.out.println(string);
310 } 500 }
311 501 }
312 // Create src code and corresponding JavaFileObjects 502
313 private Iterable<? extends JavaFileObject> getFileList(String className, 503 private void error(String msg) {
314 Set<String> baseAnnoTarget, Set<String> conAnnoTarget,
315 boolean shouldCompile) {
316
317 String srcContent = "";
318 String pkgInfoContent = "";
319 String template = Helper.template;
320 String baseTarget = "", conTarget = "";
321
322 String target = Helper.ContentVars.TARGET.getVal();
323 if(baseAnnoTarget != null) {
324 baseTarget = target.replace("#VAL", baseAnnoTarget.toString())
325 .replace("[", "{").replace("]", "}");
326 }
327 if(conAnnoTarget != null) {
328 conTarget = target.replace("#VAL", conAnnoTarget.toString())
329 .replace("[", "{").replace("]", "}");
330 }
331
332 String annoData = Helper.ContentVars.IMPORTSTMTS.getVal() +
333 conTarget +
334 Helper.ContentVars.CONTAINER.getVal() +
335 baseTarget +
336 Helper.ContentVars.REPEATABLE.getVal() +
337 Helper.ContentVars.BASE.getVal();
338
339 JavaFileObject pkgInfoFile = null;
340
341 /*
342 * If shouldCompile = true and no @Target is specified for container annotation,
343 * then all 8 ElementType enum constants are applicable as targets for
344 * container annotation.
345 */
346 if(shouldCompile && conAnnoTarget == null) {
347 //conAnnoTarget = new HashSet<String>(Arrays.asList(targetVals));
348 conAnnoTarget = getDefaultTargetSet();
349 }
350
351 if(shouldCompile) {
352 boolean isPkgCasePresent = new ArrayList<String>(conAnnoTarget).contains("ElementType.PACKAGE");
353 String repeatableAnno = Helper.ContentVars.BASEANNO.getVal() + " " + Helper.ContentVars.BASEANNO.getVal();
354 for(String s: conAnnoTarget) {
355 s = s.replace("ElementType.","");
356 String replaceStr = "/*"+s+"*/";
357 if(s.equalsIgnoreCase("PACKAGE")) {
358 //Create packageInfo file
359 String pkgInfoName = TESTPKG + "." + "package-info";
360 pkgInfoContent = repeatableAnno + "\npackage " + TESTPKG + ";" + annoData;
361 pkgInfoFile = Helper.getFile(pkgInfoName, pkgInfoContent);
362 } else {
363 template = template.replace(replaceStr, repeatableAnno);
364 //srcContent = template.replace("#ClassName",className);
365 if(!isPkgCasePresent) {
366 srcContent = template.replace("/*ANNODATA*/", annoData).replace("#ClassName",className);
367 } else {
368 replaceStr = "/*PACKAGE*/";
369 srcContent = template.replace(replaceStr, "package " + TESTPKG + ";")
370 .replace("#ClassName", className);
371 }
372 }
373 }
374 } else {
375 // For invalid cases, compilation should fail at declaration site
376 template = "class #ClassName {}";
377 srcContent = annoData + template.replace("#ClassName",className);
378 }
379 JavaFileObject srcFile = Helper.getFile(className, srcContent);
380 Iterable<? extends JavaFileObject> files = null;
381 if(pkgInfoFile != null)
382 files = Arrays.asList(pkgInfoFile,srcFile);
383 else
384 files = Arrays.asList(srcFile);
385 return files;
386 }
387
388 private Set<String> getDefaultTargetSet() {
389 Set<String> defaultSet = new HashSet<>();
390 int ctr = 0;
391 for(String s : targetVals) {
392 if(ctr++ < DEFAULT_TARGET_CNT) {
393 defaultSet.add(s);
394 }
395 }
396 return defaultSet;
397 }
398
399 private boolean isValidSubSet(Set<String> baseAnnoTarget, Set<String> conAnnoTarget) {
400 /*
401 * RULE 1: conAnnoTarget should be a subset of baseAnnoTarget
402 * RULE 2: For empty @Target ({}) - annotation cannot be applied anywhere
403 * - Empty sets for both is valid
404 * - Empty baseTarget set is invalid with non-empty conTarget set
405 * - Non-empty baseTarget set is valid with empty conTarget set
406 * RULE 3: For no @Target specified - annotation can be applied to any JDK 7 targets
407 * - No @Target for both is valid
408 * - No @Target for baseTarget set with @Target conTarget set is valid
409 * - @Target for baseTarget set with no @Target for conTarget is invalid
410 */
411
412
413 /* If baseAnno has no @Target, Foo can be either applied to @Target specified for container annotation
414 * else will be applicable for all default targets if no @Target is present for container annotation.
415 * In both cases, the set will be a valid set with no @Target for base annotation
416 */
417 if(baseAnnoTarget == null) {
418 if(conAnnoTarget == null) return true;
419 return !(conAnnoTarget.contains("ElementType.TYPE_USE") || conAnnoTarget.contains("ElementType.TYPE_PARAMETER"));
420 }
421
422 Set<String> tempBaseSet = new HashSet<>(baseAnnoTarget);
423 // If BaseAnno has TYPE, then ANNOTATION_TYPE is allowed by default
424 if(baseAnnoTarget.contains("ElementType.TYPE")) {
425 tempBaseSet.add("ElementType.ANNOTATION_TYPE");
426 }
427
428 /*
429 * If containerAnno has no @Target, only valid case if baseAnnoTarget has all targets defined
430 * else invalid set
431 */
432 if(conAnnoTarget == null) {
433 return (tempBaseSet.containsAll(getDefaultTargetSet()));
434 }
435
436 // At this point, neither conAnnoTarget or baseAnnoTarget are null
437 if(conAnnoTarget.size() == 0) return true;
438
439 // At this point, conAnnoTarget is non-empty
440 if (baseAnnoTarget.size() == 0) return false;
441
442 // At this point, neither conAnnoTarget or baseAnnoTarget are empty
443 return tempBaseSet.containsAll(conAnnoTarget);
444 }
445
446 void error(String msg) {
447 System.out.println("ERROR: " + msg); 504 System.out.println("ERROR: " + msg);
448 errors++; 505 errors++;
449 } 506 }
450
451 // Lists the start and end range for the given set of target vals
452 void showGroups() {
453 //Group 1: All target set combinations ( 0 to 1048575 ) including empty @Target sets => @Target({})
454 int grpEnd1 = (int)Math.pow(2, 2*targetVals.length) - 1;
455 System.out.println("[Group 1]: 0 - " + grpEnd1);
456
457 //Group 2: @Target not defined for base annotation ( 1048576 - 1049599 ).
458 System.out.print("[Group 2]: " + (grpEnd1 + 1) + " - ");
459 int grpEnd2 = grpEnd1 + 1 + (int)Math.pow(2, targetVals.length) - 1;
460 System.out.println(grpEnd2);
461
462 //Group 3: @Target not defined for container annotation ( 1049600 - 1050623 ).
463 System.out.print("[Group 3]: " + (grpEnd2 + 1) + " - ");
464 int grpEnd3 = grpEnd2 + 1 + (int)Math.pow(2, targetVals.length) - 1;
465 System.out.println(grpEnd3);
466
467 //Group 4: @Target not defined for both base and container annotations ( 1050624 ).
468 System.out.println("[Group 4]: " + (grpEnd3 + 1));
469 }
470 } 507 }
508

mercurial