diff -r fa24eba012bd -r 195b71850b56 test/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java --- a/test/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java Fri Mar 15 09:02:26 2013 +0000 +++ b/test/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java Fri Mar 15 13:39:04 2013 +0100 @@ -21,245 +21,404 @@ * questions. */ -/** +/* * @test - * @bug 7195131 - * @author sogoel - * @summary Combo test for all possible combinations for Target values - * @ignore 8008339 Test TargetAnnoCombo.java is broken + * @bug 7151010 8006547 8007766 + * @summary Default test cases for running combinations for Target values * @build Helper - * @compile TargetAnnoCombo.java TestCaseGenerator.java * @run main TargetAnnoCombo */ +import java.util.Set; +import java.util.List; import java.io.IOException; +import java.lang.annotation.ElementType; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; +import java.util.EnumSet; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaFileObject; -/* - * TargetAnnoCombo gets a list of test case numbers using TestCaseGenerator. - * For each of the test case number, @Target sets for base and container annotations - * are determined, source files are generated, compiled, and the result is verified - * based on if the @Target set for base and container is a positive or negative combination. - * - * @Target sets for base and container annotations are determined using a bit mapping of - * 10 ElementType enum constants defined in JDK8. - * - * Bit Target value - * 0 "ElementType.ANNOTATION_TYPE" - * 1 "ElementType.CONSTRUCTOR" - * 2 "ElementType.FIELD" - * 3 "ElementType.LOCAL_VARIABLE" - * 4 "ElementType.METHOD" - * 5 "ElementType.TYPE" - * 6 "ElementType.PARAMETER" - * 7 "ElementType.PACKAGE" - * 8 "ElementType.TYPE_USE" - * 9 "ElementType.TYPE_PARAMETER" - * - * Group 1: - * 20 bits mapping, representing a test case number, is used for all target set - * combinations ( 0 to 1048575 ) including empty @Target sets => @Target({}). - * From this 20 bits, 10 bits are for base followed by 10 bits for container - * where each bit maps to an ElementType enum constant defined in JDK8. - * - * Examples: - * Test case number: 4, binary: 100 => container=100, base=[], container=["ElementType.FIELD"] - * Test case number: 1003575, binary: 11110101000000110111 => base=1111010100, container=0000110111; - * base=["ElementType.PARAMETER", "ElementType.TYPE_USE", "ElementType.METHOD", "ElementType.FIELD", "ElementType.PACKAGE", "ElementType.TYPE_PARAMETER"], - * container=["ElementType.TYPE", "ElementType.METHOD", "ElementType.ANNOTATION_TYPE", "ElementType.CONSTRUCTOR", "ElementType.FIELD"] - * - * In the following groups, no @Target set is represented by null. - * Group 2: - * @Target is not defined on base. - * Target sets for container are determined using the 10-bit binary number - * resulting in 1024 test cases, mapping them to test case numbers from - * 1048576 to (1048576 + 1023) => 1048576 to 1049599. - * - * Example: - * Test case number: 1048587 => 1048587 - 1048576 = test case 11 in Group 2, binary: 1011 => - * base = null, - * container = ["ElementType.ANNOTATION_TYPE","ElementType.CONSTRUCTOR","ElementType.LOCAL_VARIABLE"] - * - * Group 3: - * @Target is not defined on container - * Target sets for base are determined using the 10-bit binary number - * resulting in 1024 test cases, mapping them to test case numbers from - * 1049600 to (1049600 + 1023) => 1049600 to 1050623. - * - * Example: - * Test case number: 1049708 => 1049708 - 1049600 = test case 108 in Group 3, binary: 1101100 => - * base = ["ElementType.FIELD", "ElementType.LOCAL_VARIABLE", "ElementType.TYPE", "ElementType.PARAMETER"], - * container = null - * - * For the above group, test case number: 1049855 gives compiler error, JDK-8006547 filed - * - * Group 4: - * @Target not defined for both base and container annotations. - * - * This is the last test and corresponds to test case number 1050624. base=null, container=null - * - * Examples to run this test: - * 1. Run a specific test case number: - * ${JTREG} -DTestCaseNum=10782 -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java - * 2. Run specific number of tests: - * ${JTREG} -DNumberOfTests=4 -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java - * 3. Run specific number of tests with a seed: - * ${JTREG} -DNumberOfTests=4 -DTestSeed=-972894659 -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java - * 4. Run tests in default mode (number of tests = 1000): - * ${JTREG} -DTestMode=DEFAULT -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java - * 5. Run all tests (FULL mode): - * ${JTREG} -DTestMode=FULL -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java - * - */ +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.ElementType.PACKAGE; +import static java.lang.annotation.ElementType.LOCAL_VARIABLE; +import static java.lang.annotation.ElementType.TYPE_USE; +import static java.lang.annotation.ElementType.TYPE_PARAMETER; public class TargetAnnoCombo { - int errors = 0; + static final String TESTPKG = "testpkg"; - /* - * Set it to true to get more debug information including base and - * container target sets for a given test case number - */ + + // Set it to true to get more debug information including base and container + // target sets for a given test case. static final boolean DEBUG = false; - // JDK 5/6/7/8 Targets - static final String[] targetVals = {"ElementType.ANNOTATION_TYPE", - "ElementType.CONSTRUCTOR", "ElementType.FIELD", - "ElementType.LOCAL_VARIABLE", "ElementType.METHOD", - "ElementType.TYPE", "ElementType.PARAMETER", - "ElementType.PACKAGE", "ElementType.TYPE_USE", - "ElementType.TYPE_PARAMETER"}; + // Define constant target sets to be used for the combination of the target values. + final static Set noSet = null; + final static Set empty = EnumSet.noneOf(ElementType.class); - // TYPE_USE and TYPE_PARAMETER (added in JDK8) are not part of default Target set - static final int DEFAULT_TARGET_CNT = 8; + // [TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, + // PACKAGE, TYPE_PARAMETER, TYPE_USE] + final static Set allTargets = EnumSet.allOf(ElementType.class); + + // [TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, + // PACKAGE] + final static Set jdk7 = EnumSet.range(TYPE, PACKAGE); + + // [TYPE_USE, TYPE_PARAMETER] + final static Set jdk8 = EnumSet.range(TYPE_PARAMETER, TYPE_USE); + + // List of test cases to run. This list is created in generate(). + // To run a specific test cases add case number in @run main line. + List testCases = new ArrayList(); + + int errors = 0; + + // Identify test cases that fail. + enum IgnoreKind { + RUN, + IGNORE + }; + + private class TestCase { + + private Set baseAnnotations; + private Set containerAnnotations; + private IgnoreKind ignore; + + public TestCase(Set baseAnnotations, Set containerAnnotations) { + this(baseAnnotations, containerAnnotations, IgnoreKind.RUN); + } + + public TestCase(Set baseAnnotations, Set containerAnnotations, + IgnoreKind ignoreKind) { + this.baseAnnotations = baseAnnotations; + this.containerAnnotations = containerAnnotations; + this.ignore = ignoreKind; + } + + public Set getBaseAnnotations() { + return baseAnnotations; + } + + public Set getContainerAnnotations() { + return containerAnnotations; + } + + public boolean isIgnored() { + return ignore == IgnoreKind.IGNORE; + } + + // Determine if a testCase should compile or not. + private boolean isValidSubSet() { + /* + * RULE 1: conAnnoTarget should be a subset of baseAnnoTarget + * RULE 2: For empty @Target ({}) - annotation cannot be applied anywhere + * - Empty sets for both is valid + * - Empty baseTarget set is invalid with non-empty conTarget set + * - Non-empty baseTarget set is valid with empty conTarget set + * RULE 3: For no @Target specified - annotation can be applied to any JDK 7 targets + * - No @Target for both is valid + * - No @Target for baseTarget set with @Target conTarget set is valid + * - @Target for baseTarget set with no @Target for conTarget is invalid + */ + + + /* If baseAnno has no @Target, Foo can be either applied to @Target specified + * for container annotation else will be applicable for all default targets + * if no @Target is present for container annotation. + * In both cases, the set will be a valid set with no @Target for base annotation + */ + if (baseAnnotations == null) { + if (containerAnnotations == null) { + return true; + } + return !(containerAnnotations.contains(TYPE_USE) || + containerAnnotations.contains(TYPE_PARAMETER)); + } + + Set tempBaseSet = EnumSet.noneOf(ElementType.class); + tempBaseSet.addAll(baseAnnotations); + // If BaseAnno has TYPE, then ANNOTATION_TYPE is allowed by default. + if (baseAnnotations.contains(TYPE)) { + tempBaseSet.add(ANNOTATION_TYPE); + } + + // If containerAnno has no @Target, only valid case if baseAnnoTarget has + // all targets defined else invalid set. + if (containerAnnotations == null) { + return tempBaseSet.containsAll(jdk7); + } + + // At this point, neither conAnnoTarget or baseAnnoTarget are null. + if (containerAnnotations.isEmpty()) { + return true; + } + + // At this point, conAnnoTarget is non-empty. + if (baseAnnotations.isEmpty()) { + return false; + } + + // At this point, neither conAnnoTarget or baseAnnoTarget are empty. + return tempBaseSet.containsAll(containerAnnotations); + } + } public static void main(String args[]) throws Exception { - - /* maxTestNum = (base and container combinations of targetVals elems [0 - 1048575 combos]) - * + (combinations where base or container has no Target [1024 combos]) - * + (no -1 even though 1st test is number 0 as last test is where both - * base and container have no target) - */ - - int maxTestNum = (int)Math.pow(2, 2*targetVals.length) + 2*(int)Math.pow(2, targetVals.length); - TestCaseGenerator tcg = new TestCaseGenerator(maxTestNum); TargetAnnoCombo tac = new TargetAnnoCombo(); - - int testCtr = 0; - int testCase = -1; - while ( (testCase=tcg.getNextTestCase()) != -1 ) { - tac.executeTestCase(testCase, maxTestNum); - testCtr++; + // Generates all test cases to be run. + tac.generate(); + List cases = new ArrayList(); + for (int i = 0; i < args.length; i++) { + cases.add(Integer.parseInt(args[i])); } - - System.out.println("Total tests run: " + testCtr); - if (tac.errors > 0) - throw new Exception(tac.errors + " errors found"); + if (cases.isEmpty()) { + tac.run(); + } else { + for (int index : cases) { + tac.executeTestCase(tac.testCases.get(index), index); + } + } } - /* - * For given testCase, determine the base and container annotation Target sets, - * get if testCase should compile, get test source file(s), get compilation result and verify. - * - */ - private void executeTestCase(int testCase, int maxTestNum) { + private void generate() { + // Adding test cases to run. + testCases.addAll(Arrays.asList( + // No base target against no container target. + new TestCase(noSet, noSet), + // No base target against empty container target. + new TestCase(noSet, empty), + // No base target against TYPE_USE only container target. + new TestCase(noSet, less(jdk8, TYPE_PARAMETER)), + // No base target against TYPE_PARAMETER only container target. + new TestCase(noSet, less(jdk8, TYPE_USE)), + // No base target against TYPE_USE + TYPE_PARAMETER only container target. + new TestCase(noSet, jdk8), + // No base target against TYPE_USE + some selection of jdk7 targets. + new TestCase(noSet, + plus(EnumSet.range(TYPE, LOCAL_VARIABLE), TYPE_USE)), + // No base target against TYPE_PARAMETER + some selection of jdk7 targets. + new TestCase(noSet, + plus(EnumSet.range(TYPE, LOCAL_VARIABLE), TYPE_PARAMETER)), + // No base target against each jdk7 target alone as container target. + new TestCase(noSet, plus(empty, TYPE)), + new TestCase(noSet, plus(empty, PARAMETER)), + new TestCase(noSet, plus(empty, PACKAGE)), + new TestCase(noSet, plus(empty, METHOD)), + new TestCase(noSet, plus(empty, LOCAL_VARIABLE)), + new TestCase(noSet, plus(empty, FIELD)), + new TestCase(noSet, plus(empty, CONSTRUCTOR)), + new TestCase(noSet, plus(empty, ANNOTATION_TYPE)), + // Empty base target against no container target. + new TestCase(empty, noSet), + // Empty base target against empty container target. + new TestCase(empty, empty), + // Empty base target against any lone container target. + new TestCase(empty, plus(empty, TYPE)), + new TestCase(empty, plus(empty, PARAMETER)), + new TestCase(empty, plus(empty, PACKAGE)), + new TestCase(empty, plus(empty, METHOD)), + new TestCase(empty, plus(empty, LOCAL_VARIABLE)), + new TestCase(empty, plus(empty, FIELD)), + new TestCase(empty, plus(empty, CONSTRUCTOR)), + new TestCase(empty, plus(empty, ANNOTATION_TYPE)), + new TestCase(empty, less(jdk8, TYPE_USE)), + new TestCase(empty, less(jdk8, TYPE_PARAMETER)), + // No container target against all all-but one jdk7 targets. + new TestCase(less(jdk7, TYPE), noSet), + new TestCase(less(jdk7, PARAMETER), noSet), + new TestCase(less(jdk7, PACKAGE), noSet), + new TestCase(less(jdk7, METHOD), noSet), + new TestCase(less(jdk7, LOCAL_VARIABLE), noSet), + new TestCase(less(jdk7, FIELD), noSet), + new TestCase(less(jdk7, CONSTRUCTOR), noSet), + new TestCase(less(jdk7, ANNOTATION_TYPE), noSet), + // No container against all but TYPE and ANNOTATION_TYPE + new TestCase(less(jdk7, TYPE, ANNOTATION_TYPE), noSet), + // No container against jdk7 targets. + new TestCase(jdk7, noSet), + // No container against jdk7 targets plus one or both of TYPE_USE, TYPE_PARAMETER + new TestCase(plus(jdk7, TYPE_USE), noSet), + new TestCase(plus(jdk7, TYPE_PARAMETER), noSet), + new TestCase(allTargets, noSet), + // Empty container target against any lone target. + new TestCase(plus(empty, TYPE), empty), + new TestCase(plus(empty, PARAMETER), empty), + new TestCase(plus(empty, PACKAGE), empty), + new TestCase(plus(empty, METHOD), empty), + new TestCase(plus(empty, LOCAL_VARIABLE), empty), + new TestCase(plus(empty, FIELD), empty), + new TestCase(plus(empty, CONSTRUCTOR), empty), + new TestCase(plus(empty, ANNOTATION_TYPE), empty), + new TestCase(plus(empty, TYPE_USE), empty), + new TestCase(plus(empty, TYPE_PARAMETER), empty), + // All base targets against all container targets. + new TestCase(allTargets, allTargets), + // All base targets against all but one container targets. + new TestCase(allTargets, less(allTargets, TYPE)), + new TestCase(allTargets, less(allTargets, PARAMETER)), + new TestCase(allTargets, less(allTargets, PACKAGE)), + new TestCase(allTargets, less(allTargets, METHOD)), + new TestCase(allTargets, less(allTargets, LOCAL_VARIABLE)), + new TestCase(allTargets, less(allTargets, FIELD)), + new TestCase(allTargets, less(allTargets, CONSTRUCTOR)), + new TestCase(allTargets, less(allTargets, ANNOTATION_TYPE)), + new TestCase(allTargets, less(allTargets, TYPE_USE)), + new TestCase(allTargets, less(allTargets, TYPE_PARAMETER)), + // All container targets against all but one base targets. + new TestCase(less(allTargets, TYPE), allTargets), + new TestCase(less(allTargets, PARAMETER), allTargets), + new TestCase(less(allTargets, PACKAGE), allTargets), + new TestCase(less(allTargets, METHOD), allTargets), + new TestCase(less(allTargets, LOCAL_VARIABLE), allTargets), + new TestCase(less(allTargets, FIELD), allTargets), + new TestCase(less(allTargets, CONSTRUCTOR), allTargets), + new TestCase(less(allTargets, ANNOTATION_TYPE), allTargets), + new TestCase(less(allTargets, TYPE_USE), allTargets), + new TestCase(less(allTargets, TYPE_PARAMETER), allTargets))); + // Generates 100 test cases for any lone base target contained in Set + // allTargets against any lone container target. + for (ElementType b : allTargets) { + for (ElementType c : allTargets) { + testCases.add(new TestCase(plus(empty, b), plus(empty, c))); + } + } + } - // Determine base and container annotation Target sets for the testCase - Set baseAnnoTarget = null; - Set conAnnoTarget = null; + void run() throws Exception { + int testCtr = 0; + for (TestCase tc : testCases) { + if (!tc.isIgnored()) { + executeTestCase(tc, testCases.indexOf(tc)); + testCtr++; + } + } + System.out.println("Total tests run: " + testCtr); + if (errors > 0) { + throw new Exception(errors + " errors found"); + } + } - //Number of base and container combinations [0 - 1048575 combos] - int baseContCombos = (int)Math.pow(2, 2*targetVals.length); - //Number of either base or container combinations when one of them has no @Target [1024 combos] - int targetValsCombos = (int)Math.pow(2, targetVals.length); + private void executeTestCase(TestCase testCase, int index) { + debugPrint("Test case number = " + index); + debugPrint(" => baseAnnoTarget = " + testCase.getBaseAnnotations()); + debugPrint(" => containerAnnoTarget = " + testCase.getContainerAnnotations()); - if (testCase >= baseContCombos) { - //Base annotation do not have @Target - if (testCase < baseContCombos + targetValsCombos) { - baseAnnoTarget = null; - conAnnoTarget = getSetFromBitVec(Integer.toBinaryString(testCase - baseContCombos)); - } else if (testCase < baseContCombos + 2*targetValsCombos) { - //Container annotation do not have @Target - baseAnnoTarget = getSetFromBitVec(Integer.toBinaryString(testCase - baseContCombos - targetValsCombos)); - conAnnoTarget = null; - } else { - //Both Base and Container annotation do not have @Target - baseAnnoTarget = null; - conAnnoTarget = null; - } - } else { - //TestCase number is represented as 10-bits for base followed by container bits - String bin = Integer.toBinaryString(testCase); - String base="", cont=bin; - if (bin.length() > targetVals.length){ - base = bin.substring(0, bin.length() - targetVals.length); - cont = bin.substring(bin.length() - targetVals.length,bin.length()); - } - baseAnnoTarget = getSetFromBitVec(base); - conAnnoTarget = getSetFromBitVec(cont); - } - - debugPrint("Test case number = " + testCase + " => binary = " + Integer.toBinaryString(testCase)); - debugPrint(" => baseAnnoTarget = " + baseAnnoTarget); - debugPrint(" => containerAnnoTarget = " + conAnnoTarget); - - // Determine if a testCase should compile or not - String className = "TC" + testCase; - boolean shouldCompile = isValidSubSet(baseAnnoTarget, conAnnoTarget); - - // Get test source file(s) - Iterable files = getFileList(className, baseAnnoTarget, - conAnnoTarget, shouldCompile); - - // Get result of compiling test src file(s) + String className = "TC" + index; + boolean shouldCompile = testCase.isValidSubSet(); + Iterable files = getFileList(className, testCase, shouldCompile); + // Get result of compiling test src file(s). boolean result = getCompileResult(className, shouldCompile, files); - - // List test src code if test fails - if(!result) { - System.out.println("FAIL: Test " + testCase); + // List test src code if test fails. + if (!result) { + System.out.println("FAIL: Test " + index); try { - for (JavaFileObject f: files) { + for (JavaFileObject f : files) { System.out.println("File: " + f.getName() + "\n" + f.getCharContent(true)); } } catch (IOException ioe) { System.out.println("Exception: " + ioe); } } else { - debugPrint("PASS: Test " + testCase); + debugPrint("PASS: Test " + index); } + } - // Get a Set based on bits that are set to 1 - public Set getSetFromBitVec(String bitVec) { - Set ret = new HashSet<>(); - char[] bit = bitVec.toCharArray(); - for (int i=bit.length-1, j=0; i>=0; i--, j++){ - if (bit[i] == '1') { - ret.add(targetVals[j]); + // Create src code and corresponding JavaFileObjects. + private Iterable getFileList(String className, + TestCase testCase, boolean shouldCompile) { + Set baseAnnoTarget = testCase.getBaseAnnotations(); + Set conAnnoTarget = testCase.getContainerAnnotations(); + String srcContent = ""; + String pkgInfoContent = ""; + String template = Helper.template; + String baseTarget = "", conTarget = ""; + + String target = Helper.ContentVars.TARGET.getVal(); + if (baseAnnoTarget != null) { + String tmp = target.replace("#VAL", convertToString(baseAnnoTarget).toString()); + baseTarget = tmp.replace("[", "{").replace("]", "}"); + } + if (conAnnoTarget != null) { + String tmp = target.replace("#VAL", convertToString(conAnnoTarget).toString()); + conTarget = tmp.replace("[", "{").replace("]", "}"); + } + + String annoData = Helper.ContentVars.IMPORTSTMTS.getVal() + + conTarget + + Helper.ContentVars.CONTAINER.getVal() + + baseTarget + + Helper.ContentVars.REPEATABLE.getVal() + + Helper.ContentVars.BASE.getVal(); + + JavaFileObject pkgInfoFile = null; + + // If shouldCompile = true and no @Target is specified for container annotation, + // then all 8 ElementType enum constants are applicable as targets for + // container annotation. + if (shouldCompile && conAnnoTarget == null) { + Set copySet = EnumSet.noneOf(ElementType.class); + copySet.addAll(jdk7); + conAnnoTarget = copySet; + } + + if (shouldCompile) { + boolean isPkgCasePresent = conAnnoTarget.contains(PACKAGE); + String repeatableAnno = Helper.ContentVars.BASEANNO.getVal() + + " " + Helper.ContentVars.BASEANNO.getVal(); + for (ElementType s : conAnnoTarget) { + String replaceStr = "/*" + s.name() + "*/"; + if (s.name().equalsIgnoreCase("PACKAGE")) { + //Create packageInfo file. + String pkgInfoName = TESTPKG + "." + "package-info"; + pkgInfoContent = repeatableAnno + "\npackage " + TESTPKG + ";" + annoData; + pkgInfoFile = Helper.getFile(pkgInfoName, pkgInfoContent); + } else { + template = template.replace(replaceStr, repeatableAnno); + if (!isPkgCasePresent) { + srcContent = template.replace( + "/*ANNODATA*/", annoData).replace("#ClassName", className); + } else { + replaceStr = "/*PACKAGE*/"; + String tmp = template.replace(replaceStr, "package " + TESTPKG + ";"); + srcContent = tmp.replace("#ClassName", className); + } + } } + } else { + // For invalid cases, compilation should fail at declaration site. + template = "class #ClassName {}"; + srcContent = annoData + template.replace("#ClassName", className); } - return ret; + JavaFileObject srcFile = Helper.getFile(className, srcContent); + Iterable files = null; + if (pkgInfoFile != null) { + files = Arrays.asList(pkgInfoFile, srcFile); + } else { + files = Arrays.asList(srcFile); + } + return files; } - // Compile the test source file(s) and return test result + // Compile the test source file(s) and return test result. private boolean getCompileResult(String className, boolean shouldCompile, Iterable files) { DiagnosticCollector diagnostics = new DiagnosticCollector(); Helper.compileCode(diagnostics, files); - - // Test case pass or fail + // Test case pass or fail. boolean ok = false; - String errMesg = ""; int numDiags = diagnostics.getDiagnostics().size(); - if (numDiags == 0) { if (shouldCompile) { debugPrint("Test passed, compiled as expected."); @@ -270,201 +429,80 @@ } } else { if (shouldCompile) { - // did not compile + // did not compile. errMesg = "Test failed, did not compile."; ok = false; } else { - // Error in compilation as expected - String expectedErrKey = "compiler.err.invalid.repeatable." + - "annotation.incompatible.target"; + // Error in compilation as expected. + String expectedErrKey = "compiler.err.invalid.repeatable." + + "annotation.incompatible.target"; for (Diagnostic d : diagnostics.getDiagnostics()) { - if((d.getKind() == Diagnostic.Kind.ERROR) && - d.getCode().contains(expectedErrKey)) { - // Error message as expected + if ((d.getKind() == Diagnostic.Kind.ERROR) + && d.getCode().contains(expectedErrKey)) { + // Error message as expected. debugPrint("Error message as expected."); ok = true; break; } else { - // error message is incorrect + // error message is incorrect. ok = false; } } if (!ok) { - errMesg = "Incorrect error received when compiling " + - className + ", expected: " + expectedErrKey; + errMesg = "Incorrect error received when compiling " + + className + ", expected: " + expectedErrKey; } } } - if(!ok) { + if (!ok) { error(errMesg); - for (Diagnostic d : diagnostics.getDiagnostics()) + for (Diagnostic d : diagnostics.getDiagnostics()) { System.out.println(" Diags: " + d); + } } return ok; } - private void debugPrint(String string) { - if(DEBUG) - System.out.println(string); + private Set less(Set base, ElementType... sub) { + Set res = EnumSet.noneOf(ElementType.class); + res.addAll(base); + for (ElementType t : sub) { + res.remove(t); + } + return res; } - // Create src code and corresponding JavaFileObjects - private Iterable getFileList(String className, - Set baseAnnoTarget, Set conAnnoTarget, - boolean shouldCompile) { - - String srcContent = ""; - String pkgInfoContent = ""; - String template = Helper.template; - String baseTarget = "", conTarget = ""; - - String target = Helper.ContentVars.TARGET.getVal(); - if(baseAnnoTarget != null) { - baseTarget = target.replace("#VAL", baseAnnoTarget.toString()) - .replace("[", "{").replace("]", "}"); + private Set plus(Set base, ElementType... add) { + Set res = EnumSet.noneOf(ElementType.class); + res.addAll(base); + for (ElementType t : add) { + res.add(t); } - if(conAnnoTarget != null) { - conTarget = target.replace("#VAL", conAnnoTarget.toString()) - .replace("[", "{").replace("]", "}"); - } - - String annoData = Helper.ContentVars.IMPORTSTMTS.getVal() + - conTarget + - Helper.ContentVars.CONTAINER.getVal() + - baseTarget + - Helper.ContentVars.REPEATABLE.getVal() + - Helper.ContentVars.BASE.getVal(); - - JavaFileObject pkgInfoFile = null; - - /* - * If shouldCompile = true and no @Target is specified for container annotation, - * then all 8 ElementType enum constants are applicable as targets for - * container annotation. - */ - if(shouldCompile && conAnnoTarget == null) { - //conAnnoTarget = new HashSet(Arrays.asList(targetVals)); - conAnnoTarget = getDefaultTargetSet(); - } - - if(shouldCompile) { - boolean isPkgCasePresent = new ArrayList(conAnnoTarget).contains("ElementType.PACKAGE"); - String repeatableAnno = Helper.ContentVars.BASEANNO.getVal() + " " + Helper.ContentVars.BASEANNO.getVal(); - for(String s: conAnnoTarget) { - s = s.replace("ElementType.",""); - String replaceStr = "/*"+s+"*/"; - if(s.equalsIgnoreCase("PACKAGE")) { - //Create packageInfo file - String pkgInfoName = TESTPKG + "." + "package-info"; - pkgInfoContent = repeatableAnno + "\npackage " + TESTPKG + ";" + annoData; - pkgInfoFile = Helper.getFile(pkgInfoName, pkgInfoContent); - } else { - template = template.replace(replaceStr, repeatableAnno); - //srcContent = template.replace("#ClassName",className); - if(!isPkgCasePresent) { - srcContent = template.replace("/*ANNODATA*/", annoData).replace("#ClassName",className); - } else { - replaceStr = "/*PACKAGE*/"; - srcContent = template.replace(replaceStr, "package " + TESTPKG + ";") - .replace("#ClassName", className); - } - } - } - } else { - // For invalid cases, compilation should fail at declaration site - template = "class #ClassName {}"; - srcContent = annoData + template.replace("#ClassName",className); - } - JavaFileObject srcFile = Helper.getFile(className, srcContent); - Iterable files = null; - if(pkgInfoFile != null) - files = Arrays.asList(pkgInfoFile,srcFile); - else - files = Arrays.asList(srcFile); - return files; + return res; } - private Set getDefaultTargetSet() { - Set defaultSet = new HashSet<>(); - int ctr = 0; - for(String s : targetVals) { - if(ctr++ < DEFAULT_TARGET_CNT) { - defaultSet.add(s); - } + // Iterate target set and add "ElementType." in front of every target type. + private List convertToString(Set annoTarget) { + if (annoTarget == null) { + return null; } - return defaultSet; + List annoTargets = new ArrayList(); + for (ElementType e : annoTarget) { + annoTargets.add("ElementType." + e.name()); + } + return annoTargets; } - private boolean isValidSubSet(Set baseAnnoTarget, Set conAnnoTarget) { - /* - * RULE 1: conAnnoTarget should be a subset of baseAnnoTarget - * RULE 2: For empty @Target ({}) - annotation cannot be applied anywhere - * - Empty sets for both is valid - * - Empty baseTarget set is invalid with non-empty conTarget set - * - Non-empty baseTarget set is valid with empty conTarget set - * RULE 3: For no @Target specified - annotation can be applied to any JDK 7 targets - * - No @Target for both is valid - * - No @Target for baseTarget set with @Target conTarget set is valid - * - @Target for baseTarget set with no @Target for conTarget is invalid - */ - - - /* If baseAnno has no @Target, Foo can be either applied to @Target specified for container annotation - * else will be applicable for all default targets if no @Target is present for container annotation. - * In both cases, the set will be a valid set with no @Target for base annotation - */ - if(baseAnnoTarget == null) { - if(conAnnoTarget == null) return true; - return !(conAnnoTarget.contains("ElementType.TYPE_USE") || conAnnoTarget.contains("ElementType.TYPE_PARAMETER")); + private void debugPrint(String string) { + if (DEBUG) { + System.out.println(string); } - - Set tempBaseSet = new HashSet<>(baseAnnoTarget); - // If BaseAnno has TYPE, then ANNOTATION_TYPE is allowed by default - if(baseAnnoTarget.contains("ElementType.TYPE")) { - tempBaseSet.add("ElementType.ANNOTATION_TYPE"); - } - - /* - * If containerAnno has no @Target, only valid case if baseAnnoTarget has all targets defined - * else invalid set - */ - if(conAnnoTarget == null) { - return (tempBaseSet.containsAll(getDefaultTargetSet())); - } - - // At this point, neither conAnnoTarget or baseAnnoTarget are null - if(conAnnoTarget.size() == 0) return true; - - // At this point, conAnnoTarget is non-empty - if (baseAnnoTarget.size() == 0) return false; - - // At this point, neither conAnnoTarget or baseAnnoTarget are empty - return tempBaseSet.containsAll(conAnnoTarget); } - void error(String msg) { + private void error(String msg) { System.out.println("ERROR: " + msg); errors++; } +} - // Lists the start and end range for the given set of target vals - void showGroups() { - //Group 1: All target set combinations ( 0 to 1048575 ) including empty @Target sets => @Target({}) - int grpEnd1 = (int)Math.pow(2, 2*targetVals.length) - 1; - System.out.println("[Group 1]: 0 - " + grpEnd1); - - //Group 2: @Target not defined for base annotation ( 1048576 - 1049599 ). - System.out.print("[Group 2]: " + (grpEnd1 + 1) + " - "); - int grpEnd2 = grpEnd1 + 1 + (int)Math.pow(2, targetVals.length) - 1; - System.out.println(grpEnd2); - - //Group 3: @Target not defined for container annotation ( 1049600 - 1050623 ). - System.out.print("[Group 3]: " + (grpEnd2 + 1) + " - "); - int grpEnd3 = grpEnd2 + 1 + (int)Math.pow(2, targetVals.length) - 1; - System.out.println(grpEnd3); - - //Group 4: @Target not defined for both base and container annotations ( 1050624 ). - System.out.println("[Group 4]: " + (grpEnd3 + 1)); - } -}