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

changeset 1641
195b71850b56
parent 1589
87884cd0fea3
child 2250
66570bfdbdd7
     1.1 --- a/test/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java	Fri Mar 15 09:02:26 2013 +0000
     1.2 +++ b/test/tools/javac/annotations/repeatingAnnotations/combo/TargetAnnoCombo.java	Fri Mar 15 13:39:04 2013 +0100
     1.3 @@ -21,245 +21,404 @@
     1.4   * questions.
     1.5   */
     1.6  
     1.7 -/**
     1.8 +/*
     1.9   * @test
    1.10 - * @bug      7195131
    1.11 - * @author   sogoel
    1.12 - * @summary  Combo test for all possible combinations for Target values
    1.13 - * @ignore   8008339 Test TargetAnnoCombo.java is broken
    1.14 + * @bug      7151010 8006547 8007766
    1.15 + * @summary  Default test cases for running combinations for Target values
    1.16   * @build    Helper
    1.17 - * @compile  TargetAnnoCombo.java TestCaseGenerator.java
    1.18   * @run main TargetAnnoCombo
    1.19   */
    1.20  
    1.21 +import java.util.Set;
    1.22 +import java.util.List;
    1.23  import java.io.IOException;
    1.24 +import java.lang.annotation.ElementType;
    1.25  import java.util.ArrayList;
    1.26  import java.util.Arrays;
    1.27 -import java.util.HashSet;
    1.28 -import java.util.Set;
    1.29 +import java.util.EnumSet;
    1.30  import javax.tools.Diagnostic;
    1.31  import javax.tools.DiagnosticCollector;
    1.32  import javax.tools.JavaFileObject;
    1.33  
    1.34 -/*
    1.35 - * TargetAnnoCombo gets a list of test case numbers using TestCaseGenerator.
    1.36 - * For each of the test case number, @Target sets for base and container annotations
    1.37 - * are determined, source files are generated, compiled, and the result is verified
    1.38 - * based on if the @Target set for base and container is a positive or negative combination.
    1.39 - *
    1.40 - * @Target sets for base and container annotations are determined using a bit mapping of
    1.41 - * 10 ElementType enum constants defined in JDK8.
    1.42 - *
    1.43 - * Bit      Target value
    1.44 - *  0  "ElementType.ANNOTATION_TYPE"
    1.45 - *  1  "ElementType.CONSTRUCTOR"
    1.46 - *  2  "ElementType.FIELD"
    1.47 - *  3  "ElementType.LOCAL_VARIABLE"
    1.48 - *  4  "ElementType.METHOD"
    1.49 - *  5  "ElementType.TYPE"
    1.50 - *  6  "ElementType.PARAMETER"
    1.51 - *  7  "ElementType.PACKAGE"
    1.52 - *  8  "ElementType.TYPE_USE"
    1.53 - *  9  "ElementType.TYPE_PARAMETER"
    1.54 - *
    1.55 - * Group 1:
    1.56 - * 20 bits mapping, representing a test case number, is used for all target set
    1.57 - * combinations ( 0 to 1048575 ) including empty @Target sets => @Target({}).
    1.58 - * From this 20 bits, 10 bits are for base followed by 10 bits for container
    1.59 - * where each bit maps to an ElementType enum constant defined in JDK8.
    1.60 - *
    1.61 - * Examples:
    1.62 - * Test case number: 4, binary: 100 => container=100, base=[], container=["ElementType.FIELD"]
    1.63 - * Test case number: 1003575, binary: 11110101000000110111 => base=1111010100, container=0000110111;
    1.64 - *                   base=["ElementType.PARAMETER", "ElementType.TYPE_USE", "ElementType.METHOD", "ElementType.FIELD", "ElementType.PACKAGE", "ElementType.TYPE_PARAMETER"],
    1.65 - *                   container=["ElementType.TYPE", "ElementType.METHOD", "ElementType.ANNOTATION_TYPE", "ElementType.CONSTRUCTOR", "ElementType.FIELD"]
    1.66 - *
    1.67 - * In the following groups, no @Target set is represented by null.
    1.68 - * Group 2:
    1.69 - * @Target is not defined on base.
    1.70 - * Target sets for container are determined using the 10-bit binary number
    1.71 - * resulting in 1024 test cases, mapping them to test case numbers from
    1.72 - * 1048576 to (1048576 + 1023) => 1048576 to 1049599.
    1.73 - *
    1.74 - * Example:
    1.75 - * Test case number: 1048587 => 1048587 - 1048576 = test case 11 in Group 2, binary: 1011 =>
    1.76 - *                   base = null,
    1.77 - *                   container = ["ElementType.ANNOTATION_TYPE","ElementType.CONSTRUCTOR","ElementType.LOCAL_VARIABLE"]
    1.78 - *
    1.79 - * Group 3:
    1.80 - * @Target is not defined on container
    1.81 - * Target sets for base are determined using the 10-bit binary number
    1.82 - * resulting in 1024 test cases, mapping them to test case numbers from
    1.83 - * 1049600 to (1049600 + 1023) => 1049600 to 1050623.
    1.84 - *
    1.85 - * Example:
    1.86 - * Test case number: 1049708 => 1049708 - 1049600 = test case 108 in Group 3, binary: 1101100 =>
    1.87 - *                   base = ["ElementType.FIELD", "ElementType.LOCAL_VARIABLE", "ElementType.TYPE", "ElementType.PARAMETER"],
    1.88 - *                   container = null
    1.89 - *
    1.90 - * For the above group, test case number: 1049855 gives compiler error, JDK-8006547 filed
    1.91 - *
    1.92 - * Group 4:
    1.93 - * @Target not defined for both base and container annotations.
    1.94 - *
    1.95 - * This is the last test and corresponds to test case number 1050624. base=null, container=null
    1.96 - *
    1.97 - * Examples to run this test:
    1.98 - * 1. Run a specific test case number:
    1.99 - *    ${JTREG} -DTestCaseNum=10782 -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
   1.100 - * 2. Run specific number of tests:
   1.101 - *    ${JTREG} -DNumberOfTests=4 -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
   1.102 - * 3. Run specific number of tests with a seed:
   1.103 - *    ${JTREG} -DNumberOfTests=4 -DTestSeed=-972894659 -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
   1.104 - * 4. Run tests in default mode (number of tests = 1000):
   1.105 - *    ${JTREG} -DTestMode=DEFAULT -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
   1.106 - * 5. Run all tests (FULL mode):
   1.107 - *    ${JTREG} -DTestMode=FULL -samevm -jdk:${JAVA_TEST} -reportDir ${REPORT} -workDir ${WORK} TargetAnnoCombo.java
   1.108 - *
   1.109 - */
   1.110 +import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
   1.111 +import static java.lang.annotation.ElementType.CONSTRUCTOR;
   1.112 +import static java.lang.annotation.ElementType.FIELD;
   1.113 +import static java.lang.annotation.ElementType.METHOD;
   1.114 +import static java.lang.annotation.ElementType.PARAMETER;
   1.115 +import static java.lang.annotation.ElementType.TYPE;
   1.116 +import static java.lang.annotation.ElementType.PACKAGE;
   1.117 +import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
   1.118 +import static java.lang.annotation.ElementType.TYPE_USE;
   1.119 +import static java.lang.annotation.ElementType.TYPE_PARAMETER;
   1.120  
   1.121  public class TargetAnnoCombo {
   1.122 -    int errors = 0;
   1.123 +
   1.124      static final String TESTPKG = "testpkg";
   1.125 -    /*
   1.126 -     *  Set it to true to get more debug information including base and
   1.127 -     *  container target sets for a given test case number
   1.128 -     */
   1.129 +
   1.130 +    // Set it to true to get more debug information including base and container
   1.131 +    // target sets for a given test case.
   1.132      static final boolean DEBUG = false;
   1.133  
   1.134 -    // JDK 5/6/7/8 Targets
   1.135 -    static final String[] targetVals = {"ElementType.ANNOTATION_TYPE",
   1.136 -      "ElementType.CONSTRUCTOR", "ElementType.FIELD",
   1.137 -      "ElementType.LOCAL_VARIABLE", "ElementType.METHOD",
   1.138 -      "ElementType.TYPE", "ElementType.PARAMETER",
   1.139 -      "ElementType.PACKAGE", "ElementType.TYPE_USE",
   1.140 -      "ElementType.TYPE_PARAMETER"};
   1.141 +    // Define constant target sets to be used for the combination of the target values.
   1.142 +    final static Set<ElementType> noSet = null;
   1.143 +    final static Set<ElementType> empty = EnumSet.noneOf(ElementType.class);
   1.144  
   1.145 -    // TYPE_USE and TYPE_PARAMETER (added in JDK8) are not part of default Target set
   1.146 -    static final int DEFAULT_TARGET_CNT = 8;
   1.147 +    // [TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE,
   1.148 +    // PACKAGE, TYPE_PARAMETER, TYPE_USE]
   1.149 +    final static Set<ElementType> allTargets = EnumSet.allOf(ElementType.class);
   1.150 +
   1.151 +    // [TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE,
   1.152 +    // PACKAGE]
   1.153 +    final static Set<ElementType> jdk7 = EnumSet.range(TYPE, PACKAGE);
   1.154 +
   1.155 +    // [TYPE_USE, TYPE_PARAMETER]
   1.156 +    final static Set<ElementType> jdk8 = EnumSet.range(TYPE_PARAMETER, TYPE_USE);
   1.157 +
   1.158 +    // List of test cases to run. This list is created in generate().
   1.159 +    // To run a specific test cases add case number in @run main line.
   1.160 +    List<TestCase> testCases = new ArrayList<TestCase>();
   1.161 +
   1.162 +    int errors = 0;
   1.163 +
   1.164 +    // Identify test cases that fail.
   1.165 +    enum IgnoreKind {
   1.166 +        RUN,
   1.167 +        IGNORE
   1.168 +    };
   1.169 +
   1.170 +    private class TestCase {
   1.171 +
   1.172 +        private Set<ElementType> baseAnnotations;
   1.173 +        private Set<ElementType> containerAnnotations;
   1.174 +        private IgnoreKind ignore;
   1.175 +
   1.176 +        public TestCase(Set<ElementType> baseAnnotations, Set<ElementType> containerAnnotations) {
   1.177 +            this(baseAnnotations, containerAnnotations, IgnoreKind.RUN);
   1.178 +        }
   1.179 +
   1.180 +        public TestCase(Set<ElementType> baseAnnotations, Set<ElementType> containerAnnotations,
   1.181 +                        IgnoreKind ignoreKind) {
   1.182 +            this.baseAnnotations = baseAnnotations;
   1.183 +            this.containerAnnotations = containerAnnotations;
   1.184 +            this.ignore = ignoreKind;
   1.185 +        }
   1.186 +
   1.187 +        public Set getBaseAnnotations() {
   1.188 +            return baseAnnotations;
   1.189 +        }
   1.190 +
   1.191 +        public Set getContainerAnnotations() {
   1.192 +            return containerAnnotations;
   1.193 +        }
   1.194 +
   1.195 +        public boolean isIgnored() {
   1.196 +            return ignore == IgnoreKind.IGNORE;
   1.197 +        }
   1.198 +
   1.199 +        // Determine if a testCase should compile or not.
   1.200 +        private boolean isValidSubSet() {
   1.201 +            /*
   1.202 +             *  RULE 1: conAnnoTarget should be a subset of baseAnnoTarget
   1.203 +             *  RULE 2: For empty @Target ({}) - annotation cannot be applied anywhere
   1.204 +             *         - Empty sets for both is valid
   1.205 +             *         - Empty baseTarget set is invalid with non-empty conTarget set
   1.206 +             *         - Non-empty baseTarget set is valid with empty conTarget set
   1.207 +             *  RULE 3: For no @Target specified - annotation can be applied to any JDK 7 targets
   1.208 +             *         - No @Target for both is valid
   1.209 +             *         - No @Target for baseTarget set with @Target conTarget set is valid
   1.210 +             *         - @Target for baseTarget set with no @Target for conTarget is invalid
   1.211 +             */
   1.212 +
   1.213 +
   1.214 +            /* If baseAnno has no @Target, Foo can be either applied to @Target specified
   1.215 +             * for container annotation else will be applicable for all default targets
   1.216 +             * if no @Target is present for container annotation.
   1.217 +             * In both cases, the set will be a valid set with no @Target for base annotation
   1.218 +             */
   1.219 +            if (baseAnnotations == null) {
   1.220 +                if (containerAnnotations == null) {
   1.221 +                    return true;
   1.222 +                }
   1.223 +                return !(containerAnnotations.contains(TYPE_USE) ||
   1.224 +                         containerAnnotations.contains(TYPE_PARAMETER));
   1.225 +            }
   1.226 +
   1.227 +            Set<ElementType> tempBaseSet = EnumSet.noneOf(ElementType.class);
   1.228 +            tempBaseSet.addAll(baseAnnotations);
   1.229 +            // If BaseAnno has TYPE, then ANNOTATION_TYPE is allowed by default.
   1.230 +            if (baseAnnotations.contains(TYPE)) {
   1.231 +                tempBaseSet.add(ANNOTATION_TYPE);
   1.232 +            }
   1.233 +
   1.234 +            // If containerAnno has no @Target, only valid case if baseAnnoTarget has
   1.235 +            // all targets defined else invalid set.
   1.236 +            if (containerAnnotations == null) {
   1.237 +                return tempBaseSet.containsAll(jdk7);
   1.238 +            }
   1.239 +
   1.240 +            // At this point, neither conAnnoTarget or baseAnnoTarget are null.
   1.241 +            if (containerAnnotations.isEmpty()) {
   1.242 +                return true;
   1.243 +            }
   1.244 +
   1.245 +            // At this point, conAnnoTarget is non-empty.
   1.246 +            if (baseAnnotations.isEmpty()) {
   1.247 +                return false;
   1.248 +            }
   1.249 +
   1.250 +            // At this point, neither conAnnoTarget or baseAnnoTarget are empty.
   1.251 +            return tempBaseSet.containsAll(containerAnnotations);
   1.252 +        }
   1.253 +    }
   1.254  
   1.255      public static void main(String args[]) throws Exception {
   1.256 -
   1.257 -        /* maxTestNum = (base and container combinations of targetVals elems [0 - 1048575 combos])
   1.258 -         *              + (combinations where base or container has no Target [1024 combos])
   1.259 -         *              + (no -1 even though 1st test is number 0 as last test is where both
   1.260 -         *                 base and container have no target)
   1.261 -         */
   1.262 -
   1.263 -        int maxTestNum = (int)Math.pow(2, 2*targetVals.length) + 2*(int)Math.pow(2, targetVals.length);
   1.264 -        TestCaseGenerator tcg = new TestCaseGenerator(maxTestNum);
   1.265          TargetAnnoCombo tac = new TargetAnnoCombo();
   1.266 -
   1.267 -        int testCtr = 0;
   1.268 -        int testCase = -1;
   1.269 -        while ( (testCase=tcg.getNextTestCase()) != -1 ) {
   1.270 -            tac.executeTestCase(testCase, maxTestNum);
   1.271 -            testCtr++;
   1.272 +        // Generates all test cases to be run.
   1.273 +        tac.generate();
   1.274 +        List<Integer> cases = new ArrayList<Integer>();
   1.275 +        for (int i = 0; i < args.length; i++) {
   1.276 +            cases.add(Integer.parseInt(args[i]));
   1.277          }
   1.278 -
   1.279 -        System.out.println("Total tests run: " + testCtr);
   1.280 -        if (tac.errors > 0)
   1.281 -            throw new Exception(tac.errors + " errors found");
   1.282 +        if (cases.isEmpty()) {
   1.283 +            tac.run();
   1.284 +        } else {
   1.285 +            for (int index : cases) {
   1.286 +                tac.executeTestCase(tac.testCases.get(index), index);
   1.287 +            }
   1.288 +        }
   1.289      }
   1.290  
   1.291 -    /*
   1.292 -     * For given testCase, determine the base and container annotation Target sets,
   1.293 -     * get if testCase should compile, get test source file(s), get compilation result and verify.
   1.294 -     *
   1.295 -     */
   1.296 -    private void executeTestCase(int testCase, int maxTestNum) {
   1.297 +    private void generate() {
   1.298 +        // Adding test cases to run.
   1.299 +        testCases.addAll(Arrays.asList(
   1.300 +                // No base target against no container target.
   1.301 +                new TestCase(noSet, noSet),
   1.302 +                // No base target against empty container target.
   1.303 +                new TestCase(noSet, empty),
   1.304 +                // No base target against TYPE_USE only container target.
   1.305 +                new TestCase(noSet, less(jdk8, TYPE_PARAMETER)),
   1.306 +                // No base target against TYPE_PARAMETER only container target.
   1.307 +                new TestCase(noSet, less(jdk8, TYPE_USE)),
   1.308 +                // No base target against TYPE_USE + TYPE_PARAMETER only container target.
   1.309 +                new TestCase(noSet, jdk8),
   1.310 +                // No base target against TYPE_USE + some selection of jdk7 targets.
   1.311 +                new TestCase(noSet,
   1.312 +                plus(EnumSet.range(TYPE, LOCAL_VARIABLE), TYPE_USE)),
   1.313 +                // No base target against TYPE_PARAMETER + some selection of jdk7 targets.
   1.314 +                new TestCase(noSet,
   1.315 +                plus(EnumSet.range(TYPE, LOCAL_VARIABLE), TYPE_PARAMETER)),
   1.316 +                // No base target against each jdk7 target alone as container target.
   1.317 +                new TestCase(noSet, plus(empty, TYPE)),
   1.318 +                new TestCase(noSet, plus(empty, PARAMETER)),
   1.319 +                new TestCase(noSet, plus(empty, PACKAGE)),
   1.320 +                new TestCase(noSet, plus(empty, METHOD)),
   1.321 +                new TestCase(noSet, plus(empty, LOCAL_VARIABLE)),
   1.322 +                new TestCase(noSet, plus(empty, FIELD)),
   1.323 +                new TestCase(noSet, plus(empty, CONSTRUCTOR)),
   1.324 +                new TestCase(noSet, plus(empty, ANNOTATION_TYPE)),
   1.325 +                // Empty base target against no container target.
   1.326 +                new TestCase(empty, noSet),
   1.327 +                // Empty base target against empty container target.
   1.328 +                new TestCase(empty, empty),
   1.329 +                // Empty base target against any lone container target.
   1.330 +                new TestCase(empty, plus(empty, TYPE)),
   1.331 +                new TestCase(empty, plus(empty, PARAMETER)),
   1.332 +                new TestCase(empty, plus(empty, PACKAGE)),
   1.333 +                new TestCase(empty, plus(empty, METHOD)),
   1.334 +                new TestCase(empty, plus(empty, LOCAL_VARIABLE)),
   1.335 +                new TestCase(empty, plus(empty, FIELD)),
   1.336 +                new TestCase(empty, plus(empty, CONSTRUCTOR)),
   1.337 +                new TestCase(empty, plus(empty, ANNOTATION_TYPE)),
   1.338 +                new TestCase(empty, less(jdk8, TYPE_USE)),
   1.339 +                new TestCase(empty, less(jdk8, TYPE_PARAMETER)),
   1.340 +                // No container target against all all-but one jdk7 targets.
   1.341 +                new TestCase(less(jdk7, TYPE), noSet),
   1.342 +                new TestCase(less(jdk7, PARAMETER), noSet),
   1.343 +                new TestCase(less(jdk7, PACKAGE), noSet),
   1.344 +                new TestCase(less(jdk7, METHOD), noSet),
   1.345 +                new TestCase(less(jdk7, LOCAL_VARIABLE), noSet),
   1.346 +                new TestCase(less(jdk7, FIELD), noSet),
   1.347 +                new TestCase(less(jdk7, CONSTRUCTOR), noSet),
   1.348 +                new TestCase(less(jdk7, ANNOTATION_TYPE), noSet),
   1.349 +                // No container against all but TYPE and ANNOTATION_TYPE
   1.350 +                new TestCase(less(jdk7, TYPE, ANNOTATION_TYPE), noSet),
   1.351 +                // No container against jdk7 targets.
   1.352 +                new TestCase(jdk7, noSet),
   1.353 +                // No container against jdk7 targets plus one or both of TYPE_USE, TYPE_PARAMETER
   1.354 +                new TestCase(plus(jdk7, TYPE_USE), noSet),
   1.355 +                new TestCase(plus(jdk7, TYPE_PARAMETER), noSet),
   1.356 +                new TestCase(allTargets, noSet),
   1.357 +                // Empty container target against any lone target.
   1.358 +                new TestCase(plus(empty, TYPE), empty),
   1.359 +                new TestCase(plus(empty, PARAMETER), empty),
   1.360 +                new TestCase(plus(empty, PACKAGE), empty),
   1.361 +                new TestCase(plus(empty, METHOD), empty),
   1.362 +                new TestCase(plus(empty, LOCAL_VARIABLE), empty),
   1.363 +                new TestCase(plus(empty, FIELD), empty),
   1.364 +                new TestCase(plus(empty, CONSTRUCTOR), empty),
   1.365 +                new TestCase(plus(empty, ANNOTATION_TYPE), empty),
   1.366 +                new TestCase(plus(empty, TYPE_USE), empty),
   1.367 +                new TestCase(plus(empty, TYPE_PARAMETER), empty),
   1.368 +                // All base targets against all container targets.
   1.369 +                new TestCase(allTargets, allTargets),
   1.370 +                // All base targets against all but one container targets.
   1.371 +                new TestCase(allTargets, less(allTargets, TYPE)),
   1.372 +                new TestCase(allTargets, less(allTargets, PARAMETER)),
   1.373 +                new TestCase(allTargets, less(allTargets, PACKAGE)),
   1.374 +                new TestCase(allTargets, less(allTargets, METHOD)),
   1.375 +                new TestCase(allTargets, less(allTargets, LOCAL_VARIABLE)),
   1.376 +                new TestCase(allTargets, less(allTargets, FIELD)),
   1.377 +                new TestCase(allTargets, less(allTargets, CONSTRUCTOR)),
   1.378 +                new TestCase(allTargets, less(allTargets, ANNOTATION_TYPE)),
   1.379 +                new TestCase(allTargets, less(allTargets, TYPE_USE)),
   1.380 +                new TestCase(allTargets, less(allTargets, TYPE_PARAMETER)),
   1.381 +                // All container targets against all but one base targets.
   1.382 +                new TestCase(less(allTargets, TYPE), allTargets),
   1.383 +                new TestCase(less(allTargets, PARAMETER), allTargets),
   1.384 +                new TestCase(less(allTargets, PACKAGE), allTargets),
   1.385 +                new TestCase(less(allTargets, METHOD), allTargets),
   1.386 +                new TestCase(less(allTargets, LOCAL_VARIABLE), allTargets),
   1.387 +                new TestCase(less(allTargets, FIELD), allTargets),
   1.388 +                new TestCase(less(allTargets, CONSTRUCTOR), allTargets),
   1.389 +                new TestCase(less(allTargets, ANNOTATION_TYPE), allTargets),
   1.390 +                new TestCase(less(allTargets, TYPE_USE), allTargets),
   1.391 +                new TestCase(less(allTargets, TYPE_PARAMETER), allTargets)));
   1.392 +        // Generates 100 test cases for any lone base target contained in Set
   1.393 +        // allTargets against any lone container target.
   1.394 +        for (ElementType b : allTargets) {
   1.395 +            for (ElementType c : allTargets) {
   1.396 +                testCases.add(new TestCase(plus(empty, b), plus(empty, c)));
   1.397 +            }
   1.398 +        }
   1.399 +    }
   1.400  
   1.401 -        // Determine base and container annotation Target sets for the testCase
   1.402 -        Set<String> baseAnnoTarget = null;
   1.403 -        Set<String> conAnnoTarget = null;
   1.404 +    void run() throws Exception {
   1.405 +        int testCtr = 0;
   1.406 +        for (TestCase tc : testCases) {
   1.407 +            if (!tc.isIgnored()) {
   1.408 +                executeTestCase(tc, testCases.indexOf(tc));
   1.409 +                testCtr++;
   1.410 +            }
   1.411 +        }
   1.412 +        System.out.println("Total tests run: " + testCtr);
   1.413 +        if (errors > 0) {
   1.414 +            throw new Exception(errors + " errors found");
   1.415 +        }
   1.416 +    }
   1.417  
   1.418 -        //Number of base and container combinations [0 - 1048575 combos]
   1.419 -        int baseContCombos = (int)Math.pow(2, 2*targetVals.length);
   1.420 -        //Number of either base or container combinations when one of them has no @Target [1024 combos]
   1.421 -        int targetValsCombos = (int)Math.pow(2, targetVals.length);
   1.422 +    private void executeTestCase(TestCase testCase, int index) {
   1.423 +        debugPrint("Test case number = " + index);
   1.424 +        debugPrint(" => baseAnnoTarget = " + testCase.getBaseAnnotations());
   1.425 +        debugPrint(" => containerAnnoTarget = " + testCase.getContainerAnnotations());
   1.426  
   1.427 -        if (testCase >= baseContCombos) {
   1.428 -            //Base annotation do not have @Target
   1.429 -            if (testCase < baseContCombos + targetValsCombos) {
   1.430 -                baseAnnoTarget = null;
   1.431 -                conAnnoTarget = getSetFromBitVec(Integer.toBinaryString(testCase - baseContCombos));
   1.432 -            } else if (testCase < baseContCombos + 2*targetValsCombos) {
   1.433 -                //Container annotation do not have @Target
   1.434 -                baseAnnoTarget = getSetFromBitVec(Integer.toBinaryString(testCase - baseContCombos - targetValsCombos));
   1.435 -                conAnnoTarget = null;
   1.436 -            } else {
   1.437 -                //Both Base and Container annotation do not have @Target
   1.438 -                baseAnnoTarget = null;
   1.439 -                conAnnoTarget = null;
   1.440 -            }
   1.441 -        } else {
   1.442 -            //TestCase number is represented as 10-bits for base followed by container bits
   1.443 -            String bin = Integer.toBinaryString(testCase);
   1.444 -            String base="", cont=bin;
   1.445 -            if (bin.length() > targetVals.length){
   1.446 -                base = bin.substring(0, bin.length() - targetVals.length);
   1.447 -                cont = bin.substring(bin.length() - targetVals.length,bin.length());
   1.448 -            }
   1.449 -            baseAnnoTarget = getSetFromBitVec(base);
   1.450 -            conAnnoTarget = getSetFromBitVec(cont);
   1.451 -        }
   1.452 -
   1.453 -        debugPrint("Test case number = " + testCase + " => binary = " + Integer.toBinaryString(testCase));
   1.454 -        debugPrint(" => baseAnnoTarget = " + baseAnnoTarget);
   1.455 -        debugPrint(" => containerAnnoTarget = " + conAnnoTarget);
   1.456 -
   1.457 -        // Determine if a testCase should compile or not
   1.458 -        String className = "TC" + testCase;
   1.459 -        boolean shouldCompile = isValidSubSet(baseAnnoTarget, conAnnoTarget);
   1.460 -
   1.461 -        // Get test source file(s)
   1.462 -        Iterable<? extends JavaFileObject> files = getFileList(className, baseAnnoTarget,
   1.463 -                conAnnoTarget, shouldCompile);
   1.464 -
   1.465 -        // Get result of compiling test src file(s)
   1.466 +        String className = "TC" + index;
   1.467 +        boolean shouldCompile = testCase.isValidSubSet();
   1.468 +        Iterable<? extends JavaFileObject> files = getFileList(className, testCase, shouldCompile);
   1.469 +        // Get result of compiling test src file(s).
   1.470          boolean result = getCompileResult(className, shouldCompile, files);
   1.471 -
   1.472 -        // List test src code if test fails
   1.473 -        if(!result) {
   1.474 -            System.out.println("FAIL: Test " + testCase);
   1.475 +        // List test src code if test fails.
   1.476 +        if (!result) {
   1.477 +            System.out.println("FAIL: Test " + index);
   1.478              try {
   1.479 -                for (JavaFileObject f: files) {
   1.480 +                for (JavaFileObject f : files) {
   1.481                      System.out.println("File: " + f.getName() + "\n" + f.getCharContent(true));
   1.482                  }
   1.483              } catch (IOException ioe) {
   1.484                  System.out.println("Exception: " + ioe);
   1.485              }
   1.486          } else {
   1.487 -            debugPrint("PASS: Test " + testCase);
   1.488 +            debugPrint("PASS: Test " + index);
   1.489          }
   1.490 +
   1.491      }
   1.492  
   1.493 -    // Get a Set<String> based on bits that are set to 1
   1.494 -    public Set<String> getSetFromBitVec(String bitVec) {
   1.495 -        Set<String> ret = new HashSet<>();
   1.496 -        char[] bit = bitVec.toCharArray();
   1.497 -        for (int i=bit.length-1, j=0; i>=0; i--, j++){
   1.498 -            if (bit[i] == '1') {
   1.499 -                ret.add(targetVals[j]);
   1.500 +    // Create src code and corresponding JavaFileObjects.
   1.501 +    private Iterable<? extends JavaFileObject> getFileList(String className,
   1.502 +            TestCase testCase, boolean shouldCompile) {
   1.503 +        Set<ElementType> baseAnnoTarget = testCase.getBaseAnnotations();
   1.504 +        Set<ElementType> conAnnoTarget = testCase.getContainerAnnotations();
   1.505 +        String srcContent = "";
   1.506 +        String pkgInfoContent = "";
   1.507 +        String template = Helper.template;
   1.508 +        String baseTarget = "", conTarget = "";
   1.509 +
   1.510 +        String target = Helper.ContentVars.TARGET.getVal();
   1.511 +        if (baseAnnoTarget != null) {
   1.512 +            String tmp = target.replace("#VAL", convertToString(baseAnnoTarget).toString());
   1.513 +            baseTarget = tmp.replace("[", "{").replace("]", "}");
   1.514 +        }
   1.515 +        if (conAnnoTarget != null) {
   1.516 +            String tmp = target.replace("#VAL", convertToString(conAnnoTarget).toString());
   1.517 +            conTarget = tmp.replace("[", "{").replace("]", "}");
   1.518 +        }
   1.519 +
   1.520 +        String annoData = Helper.ContentVars.IMPORTSTMTS.getVal()
   1.521 +                + conTarget
   1.522 +                + Helper.ContentVars.CONTAINER.getVal()
   1.523 +                + baseTarget
   1.524 +                + Helper.ContentVars.REPEATABLE.getVal()
   1.525 +                + Helper.ContentVars.BASE.getVal();
   1.526 +
   1.527 +        JavaFileObject pkgInfoFile = null;
   1.528 +
   1.529 +        // If shouldCompile = true and no @Target is specified for container annotation,
   1.530 +        // then all 8 ElementType enum constants are applicable as targets for
   1.531 +        // container annotation.
   1.532 +        if (shouldCompile && conAnnoTarget == null) {
   1.533 +            Set<ElementType> copySet = EnumSet.noneOf(ElementType.class);
   1.534 +            copySet.addAll(jdk7);
   1.535 +            conAnnoTarget = copySet;
   1.536 +        }
   1.537 +
   1.538 +        if (shouldCompile) {
   1.539 +            boolean isPkgCasePresent = conAnnoTarget.contains(PACKAGE);
   1.540 +            String repeatableAnno = Helper.ContentVars.BASEANNO.getVal()
   1.541 +                    + " " + Helper.ContentVars.BASEANNO.getVal();
   1.542 +            for (ElementType s : conAnnoTarget) {
   1.543 +                String replaceStr = "/*" + s.name() + "*/";
   1.544 +                if (s.name().equalsIgnoreCase("PACKAGE")) {
   1.545 +                    //Create packageInfo file.
   1.546 +                    String pkgInfoName = TESTPKG + "." + "package-info";
   1.547 +                    pkgInfoContent = repeatableAnno + "\npackage " + TESTPKG + ";" + annoData;
   1.548 +                    pkgInfoFile = Helper.getFile(pkgInfoName, pkgInfoContent);
   1.549 +                } else {
   1.550 +                    template = template.replace(replaceStr, repeatableAnno);
   1.551 +                    if (!isPkgCasePresent) {
   1.552 +                        srcContent = template.replace(
   1.553 +                                "/*ANNODATA*/", annoData).replace("#ClassName", className);
   1.554 +                    } else {
   1.555 +                        replaceStr = "/*PACKAGE*/";
   1.556 +                        String tmp = template.replace(replaceStr, "package " + TESTPKG + ";");
   1.557 +                        srcContent = tmp.replace("#ClassName", className);
   1.558 +                    }
   1.559 +                }
   1.560              }
   1.561 +        } else {
   1.562 +            // For invalid cases, compilation should fail at declaration site.
   1.563 +            template = "class #ClassName {}";
   1.564 +            srcContent = annoData + template.replace("#ClassName", className);
   1.565          }
   1.566 -        return ret;
   1.567 +        JavaFileObject srcFile = Helper.getFile(className, srcContent);
   1.568 +        Iterable<? extends JavaFileObject> files = null;
   1.569 +        if (pkgInfoFile != null) {
   1.570 +            files = Arrays.asList(pkgInfoFile, srcFile);
   1.571 +        } else {
   1.572 +            files = Arrays.asList(srcFile);
   1.573 +        }
   1.574 +        return files;
   1.575      }
   1.576  
   1.577 -    // Compile the test source file(s) and return test result
   1.578 +    // Compile the test source file(s) and return test result.
   1.579      private boolean getCompileResult(String className, boolean shouldCompile,
   1.580              Iterable<? extends JavaFileObject> files) {
   1.581  
   1.582          DiagnosticCollector<JavaFileObject> diagnostics =
   1.583                  new DiagnosticCollector<JavaFileObject>();
   1.584          Helper.compileCode(diagnostics, files);
   1.585 -
   1.586 -        // Test case pass or fail
   1.587 +        // Test case pass or fail.
   1.588          boolean ok = false;
   1.589 -
   1.590          String errMesg = "";
   1.591          int numDiags = diagnostics.getDiagnostics().size();
   1.592 -
   1.593          if (numDiags == 0) {
   1.594              if (shouldCompile) {
   1.595                  debugPrint("Test passed, compiled as expected.");
   1.596 @@ -270,201 +429,80 @@
   1.597              }
   1.598          } else {
   1.599              if (shouldCompile) {
   1.600 -                // did not compile
   1.601 +                // did not compile.
   1.602                  errMesg = "Test failed, did not compile.";
   1.603                  ok = false;
   1.604              } else {
   1.605 -                // Error in compilation as expected
   1.606 -                String expectedErrKey = "compiler.err.invalid.repeatable." +
   1.607 -                        "annotation.incompatible.target";
   1.608 +                // Error in compilation as expected.
   1.609 +                String expectedErrKey = "compiler.err.invalid.repeatable."
   1.610 +                        + "annotation.incompatible.target";
   1.611                  for (Diagnostic<?> d : diagnostics.getDiagnostics()) {
   1.612 -                    if((d.getKind() == Diagnostic.Kind.ERROR) &&
   1.613 -                        d.getCode().contains(expectedErrKey)) {
   1.614 -                        // Error message as expected
   1.615 +                    if ((d.getKind() == Diagnostic.Kind.ERROR)
   1.616 +                            && d.getCode().contains(expectedErrKey)) {
   1.617 +                        // Error message as expected.
   1.618                          debugPrint("Error message as expected.");
   1.619                          ok = true;
   1.620                          break;
   1.621                      } else {
   1.622 -                        // error message is incorrect
   1.623 +                        // error message is incorrect.
   1.624                          ok = false;
   1.625                      }
   1.626                  }
   1.627                  if (!ok) {
   1.628 -                    errMesg = "Incorrect error received when compiling " +
   1.629 -                        className + ", expected: " + expectedErrKey;
   1.630 +                    errMesg = "Incorrect error received when compiling "
   1.631 +                            + className + ", expected: " + expectedErrKey;
   1.632                  }
   1.633              }
   1.634          }
   1.635  
   1.636 -        if(!ok) {
   1.637 +        if (!ok) {
   1.638              error(errMesg);
   1.639 -            for (Diagnostic<?> d : diagnostics.getDiagnostics())
   1.640 +            for (Diagnostic<?> d : diagnostics.getDiagnostics()) {
   1.641                  System.out.println(" Diags: " + d);
   1.642 +            }
   1.643          }
   1.644          return ok;
   1.645      }
   1.646  
   1.647 -    private void debugPrint(String string) {
   1.648 -        if(DEBUG)
   1.649 -            System.out.println(string);
   1.650 +    private Set<ElementType> less(Set<ElementType> base, ElementType... sub) {
   1.651 +        Set<ElementType> res = EnumSet.noneOf(ElementType.class);
   1.652 +        res.addAll(base);
   1.653 +        for (ElementType t : sub) {
   1.654 +            res.remove(t);
   1.655 +        }
   1.656 +        return res;
   1.657      }
   1.658  
   1.659 -    // Create src code and corresponding JavaFileObjects
   1.660 -    private Iterable<? extends JavaFileObject> getFileList(String className,
   1.661 -            Set<String> baseAnnoTarget, Set<String> conAnnoTarget,
   1.662 -            boolean shouldCompile) {
   1.663 -
   1.664 -        String srcContent = "";
   1.665 -        String pkgInfoContent = "";
   1.666 -        String template = Helper.template;
   1.667 -        String baseTarget = "", conTarget = "";
   1.668 -
   1.669 -        String target = Helper.ContentVars.TARGET.getVal();
   1.670 -        if(baseAnnoTarget != null) {
   1.671 -            baseTarget = target.replace("#VAL", baseAnnoTarget.toString())
   1.672 -                                  .replace("[", "{").replace("]", "}");
   1.673 +    private Set<ElementType> plus(Set<ElementType> base, ElementType... add) {
   1.674 +        Set<ElementType> res = EnumSet.noneOf(ElementType.class);
   1.675 +        res.addAll(base);
   1.676 +        for (ElementType t : add) {
   1.677 +            res.add(t);
   1.678          }
   1.679 -        if(conAnnoTarget != null) {
   1.680 -            conTarget = target.replace("#VAL", conAnnoTarget.toString())
   1.681 -                                 .replace("[", "{").replace("]", "}");
   1.682 -        }
   1.683 -
   1.684 -        String annoData = Helper.ContentVars.IMPORTSTMTS.getVal() +
   1.685 -                          conTarget +
   1.686 -                          Helper.ContentVars.CONTAINER.getVal() +
   1.687 -                          baseTarget +
   1.688 -                          Helper.ContentVars.REPEATABLE.getVal() +
   1.689 -                          Helper.ContentVars.BASE.getVal();
   1.690 -
   1.691 -        JavaFileObject pkgInfoFile = null;
   1.692 -
   1.693 -        /*
   1.694 -         *  If shouldCompile = true and no @Target is specified for container annotation,
   1.695 -         *  then all 8 ElementType enum constants are applicable as targets for
   1.696 -         *  container annotation.
   1.697 -         */
   1.698 -        if(shouldCompile && conAnnoTarget == null) {
   1.699 -            //conAnnoTarget = new HashSet<String>(Arrays.asList(targetVals));
   1.700 -            conAnnoTarget = getDefaultTargetSet();
   1.701 -        }
   1.702 -
   1.703 -        if(shouldCompile) {
   1.704 -            boolean isPkgCasePresent = new ArrayList<String>(conAnnoTarget).contains("ElementType.PACKAGE");
   1.705 -            String repeatableAnno = Helper.ContentVars.BASEANNO.getVal() + " " + Helper.ContentVars.BASEANNO.getVal();
   1.706 -            for(String s: conAnnoTarget) {
   1.707 -                s = s.replace("ElementType.","");
   1.708 -                String replaceStr = "/*"+s+"*/";
   1.709 -                if(s.equalsIgnoreCase("PACKAGE")) {
   1.710 -                    //Create packageInfo file
   1.711 -                    String pkgInfoName = TESTPKG + "." + "package-info";
   1.712 -                    pkgInfoContent = repeatableAnno + "\npackage " + TESTPKG + ";" + annoData;
   1.713 -                    pkgInfoFile = Helper.getFile(pkgInfoName, pkgInfoContent);
   1.714 -                } else {
   1.715 -                    template = template.replace(replaceStr, repeatableAnno);
   1.716 -                    //srcContent = template.replace("#ClassName",className);
   1.717 -                    if(!isPkgCasePresent) {
   1.718 -                        srcContent = template.replace("/*ANNODATA*/", annoData).replace("#ClassName",className);
   1.719 -                    } else {
   1.720 -                        replaceStr = "/*PACKAGE*/";
   1.721 -                        srcContent = template.replace(replaceStr, "package " + TESTPKG + ";")
   1.722 -                                     .replace("#ClassName", className);
   1.723 -                    }
   1.724 -                }
   1.725 -            }
   1.726 -        } else {
   1.727 -            // For invalid cases, compilation should fail at declaration site
   1.728 -            template = "class #ClassName {}";
   1.729 -            srcContent = annoData + template.replace("#ClassName",className);
   1.730 -        }
   1.731 -        JavaFileObject srcFile = Helper.getFile(className, srcContent);
   1.732 -        Iterable<? extends JavaFileObject> files = null;
   1.733 -        if(pkgInfoFile != null)
   1.734 -            files = Arrays.asList(pkgInfoFile,srcFile);
   1.735 -        else
   1.736 -            files = Arrays.asList(srcFile);
   1.737 -        return files;
   1.738 +        return res;
   1.739      }
   1.740  
   1.741 -    private Set<String> getDefaultTargetSet() {
   1.742 -        Set<String> defaultSet = new HashSet<>();
   1.743 -        int ctr = 0;
   1.744 -        for(String s : targetVals) {
   1.745 -            if(ctr++ < DEFAULT_TARGET_CNT) {
   1.746 -                defaultSet.add(s);
   1.747 -            }
   1.748 +    // Iterate target set and add "ElementType." in front of every target type.
   1.749 +    private List<String> convertToString(Set<ElementType> annoTarget) {
   1.750 +        if (annoTarget == null) {
   1.751 +            return null;
   1.752          }
   1.753 -        return defaultSet;
   1.754 +        List<String> annoTargets = new ArrayList<String>();
   1.755 +        for (ElementType e : annoTarget) {
   1.756 +            annoTargets.add("ElementType." + e.name());
   1.757 +        }
   1.758 +        return annoTargets;
   1.759      }
   1.760  
   1.761 -    private boolean isValidSubSet(Set<String> baseAnnoTarget, Set<String> conAnnoTarget) {
   1.762 -        /*
   1.763 -         *  RULE 1: conAnnoTarget should be a subset of baseAnnoTarget
   1.764 -         *  RULE 2: For empty @Target ({}) - annotation cannot be applied anywhere
   1.765 -         *         - Empty sets for both is valid
   1.766 -         *         - Empty baseTarget set is invalid with non-empty conTarget set
   1.767 -         *         - Non-empty baseTarget set is valid with empty conTarget set
   1.768 -         *  RULE 3: For no @Target specified - annotation can be applied to any JDK 7 targets
   1.769 -         *         - No @Target for both is valid
   1.770 -         *         - No @Target for baseTarget set with @Target conTarget set is valid
   1.771 -         *         - @Target for baseTarget set with no @Target for conTarget is invalid
   1.772 -         */
   1.773 -
   1.774 -
   1.775 -        /* If baseAnno has no @Target, Foo can be either applied to @Target specified for container annotation
   1.776 -         * else will be applicable for all default targets if no @Target is present for container annotation.
   1.777 -         * In both cases, the set will be a valid set with no @Target for base annotation
   1.778 -         */
   1.779 -        if(baseAnnoTarget == null) {
   1.780 -            if(conAnnoTarget == null) return true;
   1.781 -            return !(conAnnoTarget.contains("ElementType.TYPE_USE") || conAnnoTarget.contains("ElementType.TYPE_PARAMETER"));
   1.782 +    private void debugPrint(String string) {
   1.783 +        if (DEBUG) {
   1.784 +            System.out.println(string);
   1.785          }
   1.786 -
   1.787 -        Set<String> tempBaseSet = new HashSet<>(baseAnnoTarget);
   1.788 -        // If BaseAnno has TYPE, then ANNOTATION_TYPE is allowed by default
   1.789 -        if(baseAnnoTarget.contains("ElementType.TYPE")) {
   1.790 -            tempBaseSet.add("ElementType.ANNOTATION_TYPE");
   1.791 -        }
   1.792 -
   1.793 -        /*
   1.794 -         * If containerAnno has no @Target, only valid case if baseAnnoTarget has all targets defined
   1.795 -         * else invalid set
   1.796 -         */
   1.797 -        if(conAnnoTarget == null) {
   1.798 -            return (tempBaseSet.containsAll(getDefaultTargetSet()));
   1.799 -        }
   1.800 -
   1.801 -        // At this point, neither conAnnoTarget or baseAnnoTarget are null
   1.802 -        if(conAnnoTarget.size() == 0) return true;
   1.803 -
   1.804 -        // At this point, conAnnoTarget is non-empty
   1.805 -        if (baseAnnoTarget.size() == 0) return false;
   1.806 -
   1.807 -        // At this point, neither conAnnoTarget or baseAnnoTarget are empty
   1.808 -        return tempBaseSet.containsAll(conAnnoTarget);
   1.809      }
   1.810  
   1.811 -    void error(String msg) {
   1.812 +    private void error(String msg) {
   1.813          System.out.println("ERROR: " + msg);
   1.814          errors++;
   1.815      }
   1.816 +}
   1.817  
   1.818 -    // Lists the start and end range for the given set of target vals
   1.819 -    void showGroups() {
   1.820 -        //Group 1: All target set combinations ( 0 to 1048575 ) including empty @Target sets => @Target({})
   1.821 -        int grpEnd1 = (int)Math.pow(2, 2*targetVals.length) - 1;
   1.822 -        System.out.println("[Group 1]: 0 - " + grpEnd1);
   1.823 -
   1.824 -        //Group 2: @Target not defined for base annotation ( 1048576 - 1049599 ).
   1.825 -        System.out.print("[Group 2]: " + (grpEnd1 + 1) + " - ");
   1.826 -        int grpEnd2 = grpEnd1 + 1 + (int)Math.pow(2, targetVals.length) - 1;
   1.827 -        System.out.println(grpEnd2);
   1.828 -
   1.829 -        //Group 3: @Target not defined for container annotation ( 1049600 - 1050623 ).
   1.830 -        System.out.print("[Group 3]: " + (grpEnd2 + 1) + " - ");
   1.831 -        int grpEnd3 = grpEnd2 + 1 + (int)Math.pow(2, targetVals.length) - 1;
   1.832 -        System.out.println(grpEnd3);
   1.833 -
   1.834 -        //Group 4: @Target not defined for both base and container annotations ( 1050624 ).
   1.835 -        System.out.println("[Group 4]: " + (grpEnd3 + 1));
   1.836 -    }
   1.837 -}

mercurial