11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/* 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2008 The Guava Authors 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License. 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License. 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect.testing; 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.Collections.disjoint; 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.logging.Level.FINER; 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.testing.features.ConflictingRequirementsException; 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.testing.features.Feature; 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.testing.features.FeatureUtil; 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.testing.features.TesterRequirements; 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.Test; 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase; 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestSuite; 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.Method; 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.ArrayList; 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Arrays; 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collection; 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections; 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Enumeration; 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.HashMap; 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.HashSet; 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List; 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map; 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set; 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.logging.Logger; 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Creates, based on your criteria, a JUnit test suite that exhaustively tests 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the object generated by a G, selecting appropriate tests by matching them 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * against specified features. 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <B> The concrete type of this builder (the 'self-type'). All the 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Builder methods of this class (such as {@link #named}) return this type, so 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * that Builder methods of more derived classes can be chained onto them without 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * casting. 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @param <G> The type of the generator to be passed to testers in the 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * generated test suite. An instance of G should somehow provide an 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * instance of the class under test, plus any other information required 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * to parameterize the test. 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author George van den Driessche 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic abstract class FeatureSpecificTestSuiteBuilder< 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert B extends FeatureSpecificTestSuiteBuilder<B, G>, G> { 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected B self() { 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (B) this; 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Test Data 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private G subjectGenerator; 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Gets run before every test. 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Runnable setUp; 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Gets run at the conclusion of every test. 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Runnable tearDown; 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected B usingGenerator(G subjectGenerator) { 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.subjectGenerator = subjectGenerator; 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return self(); 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected G getSubjectGenerator() { 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return subjectGenerator; 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public B withSetUp(Runnable setUp) { 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.setUp = setUp; 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return self(); 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Runnable getSetUp() { 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return setUp; 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public B withTearDown(Runnable tearDown) { 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.tearDown = tearDown; 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return self(); 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Runnable getTearDown() { 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return tearDown; 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Features 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Set<Feature<?>> features; 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Configures this builder to produce tests appropriate for the given 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * features. 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public B withFeatures(Feature<?>... features) { 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return withFeatures(Arrays.asList(features)); 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public B withFeatures(Iterable<? extends Feature<?>> features) { 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.features = Helpers.copyToSet(features); 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return self(); 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Set<Feature<?>> getFeatures() { 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Collections.unmodifiableSet(features); 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Name 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private String name; 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** Configures this builder produce a TestSuite with the given name. */ 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public B named(String name) { 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (name.contains("(")) { 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new IllegalArgumentException("Eclipse hides all characters after " 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert + "'('; please use '[]' or other characters instead of parentheses"); 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert this.name = name; 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return self(); 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected String getName() { 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return name; 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Test suppression 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private Set<Method> suppressedTests = new HashSet<Method>(); 1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Prevents the given methods from being run as part of the test suite. 1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <em>Note:</em> in principle this should never need to be used, but it 1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * might be useful if the semantics of an implementation disagree in 1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * unforeseen ways with the semantics expected by a test, or to keep dependent 1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * builds clean in spite of an erroneous test. 1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public B suppressing(Method... methods) { 1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return suppressing(Arrays.asList(methods)); 1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public B suppressing(Collection<Method> methods) { 1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert suppressedTests.addAll(methods); 1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return self(); 1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected Set<Method> getSuppressedTests() { 1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return suppressedTests; 1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final Logger logger = Logger.getLogger( 1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert FeatureSpecificTestSuiteBuilder.class.getName()); 1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Creates a runnable JUnit test suite based on the criteria already given. 1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /* 1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Class parameters must be raw. This annotation should go on testerClass in 1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the for loop, but the 1.5 javac crashes on annotations in for loops: 1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6294589> 1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert public TestSuite createTestSuite() { 1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert checkCanCreate(); 1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert logger.fine(" Testing: " + name); 1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert logger.fine("Features: " + formatFeatureSet(features)); 1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert FeatureUtil.addImpliedFeatures(features); 1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert logger.fine("Expanded: " + formatFeatureSet(features)); 1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Class parameters must be raw. 1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<Class<? extends AbstractTester>> testers = getTesters(); 1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestSuite suite = new TestSuite(name); 1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Class<? extends AbstractTester> testerClass : testers) { 1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final TestSuite testerSuite = makeSuiteForTesterClass( 1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert (Class<? extends AbstractTester<?>>) testerClass); 1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (testerSuite.countTestCases() > 0) { 1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert suite.addTest(testerSuite); 1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return suite; 2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert /** 2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Throw {@link IllegalStateException} if {@link #createTestSuite()} can't 2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * be called yet. 2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected void checkCanCreate() { 2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (subjectGenerator == null) { 2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new IllegalStateException("Call using() before createTestSuite()."); 2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (name == null) { 2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new IllegalStateException("Call named() before createTestSuite()."); 2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (features == null) { 2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new IllegalStateException( 2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "Call withFeatures() before createTestSuite()."); 2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Class parameters must be raw. 2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected abstract List<Class<? extends AbstractTester>> 2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert getTesters(); 2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private boolean matches(Test test) { 2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Method method; 2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert method = extractMethod(test); 2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (IllegalArgumentException e) { 2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert logger.finer(Platform.format( 2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "%s: including by default: %s", test, e.getMessage())); 2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (suppressedTests.contains(method)) { 2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert logger.finer(Platform.format( 2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "%s: excluding because it was explicitly suppressed.", test)); 2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final TesterRequirements requirements; 2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert try { 2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert requirements = FeatureUtil.getTesterRequirements(method); 2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } catch (ConflictingRequirementsException e) { 2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new RuntimeException(e); 2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!features.containsAll(requirements.getPresentFeatures())) { 2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (logger.isLoggable(FINER)) { 2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<Feature<?>> missingFeatures = 2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Helpers.copyToSet(requirements.getPresentFeatures()); 2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert missingFeatures.removeAll(features); 2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert logger.finer(Platform.format( 2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "%s: skipping because these features are absent: %s", 2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert method, missingFeatures)); 2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (intersect(features, requirements.getAbsentFeatures())) { 2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (logger.isLoggable(FINER)) { 2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Set<Feature<?>> unwantedFeatures = 2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Helpers.copyToSet(requirements.getAbsentFeatures()); 2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert unwantedFeatures.retainAll(features); 2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert logger.finer(Platform.format( 2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "%s: skipping because these features are present: %s", 2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert method, unwantedFeatures)); 2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return true; 2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static boolean intersect(Set<?> a, Set<?> b) { 2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return !disjoint(a, b); 2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static Method extractMethod(Test test) { 2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (test instanceof AbstractTester) { 2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AbstractTester<?> tester = (AbstractTester<?>) test; 2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Platform.getMethod(tester.getClass(), tester.getTestMethodName()); 2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } else if (test instanceof TestCase) { 2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestCase testCase = (TestCase) test; 2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return Platform.getMethod(testCase.getClass(), testCase.getName()); 2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } else { 2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert throw new IllegalArgumentException( 2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert "unable to extract method from test: not a TestCase."); 2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected TestSuite makeSuiteForTesterClass( 2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Class<? extends AbstractTester<?>> testerClass) { 2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final TestSuite candidateTests = getTemplateSuite(testerClass); 2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final TestSuite suite = filterSuite(candidateTests); 2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Enumeration<?> allTests = suite.tests(); 2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (allTests.hasMoreElements()) { 2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object test = allTests.nextElement(); 2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (test instanceof AbstractTester) { 2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert @SuppressWarnings("unchecked") 2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert AbstractTester<? super G> tester = (AbstractTester<? super G>) test; 2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert tester.init(subjectGenerator, name, setUp, tearDown); 2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return suite; 3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static final Map<Class<? extends AbstractTester<?>>, TestSuite> 3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert templateSuiteForClass = 3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert new HashMap<Class<? extends AbstractTester<?>>, TestSuite>(); 3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private static TestSuite getTemplateSuite( 3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Class<? extends AbstractTester<?>> testerClass) { 3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert synchronized (templateSuiteForClass) { 3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestSuite suite = templateSuiteForClass.get(testerClass); 3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (suite == null) { 3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert suite = new TestSuite(testerClass); 3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert templateSuiteForClass.put(testerClass, suite); 3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return suite; 3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert private TestSuite filterSuite(TestSuite suite) { 3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert TestSuite filtered = new TestSuite(suite.getName()); 3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert final Enumeration<?> tests = suite.tests(); 3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert while (tests.hasMoreElements()) { 3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Test test = (Test) tests.nextElement(); 3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (matches(test)) { 3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert filtered.addTest(test); 3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return filtered; 3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert protected static String formatFeatureSet(Set<? extends Feature<?>> features) { 3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert List<String> temp = new ArrayList<String>(); 3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert for (Feature<?> feature : features) { 3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Object featureAsObject = feature; // to work around bogus JDK warning 3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (featureAsObject instanceof Enum) { 3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert Enum<?> f = (Enum<?>) featureAsObject; 3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert temp.add(Platform.classGetSimpleName( 3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert f.getDeclaringClass()) + "." + feature); 3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } else { 3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert temp.add(feature.toString()); 3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return temp.toString(); 3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 346