| /* |
| * Copyright 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.junit.tools; |
| |
| import com.google.gwt.junit.client.GWTTestCase; |
| |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.TreeMap; |
| |
| /** |
| * A utility class to optimize the order in which GWTTestCases are run by |
| * minimizing the number of times the test framework switches modules. |
| */ |
| public class GWTTestSuite extends TestSuite { |
| private final Map<String, TestSuite> moduleSuites = new TreeMap<String, TestSuite>(); |
| |
| private TestSuite nonGWTTestSuite; |
| |
| public GWTTestSuite() { |
| } |
| |
| public GWTTestSuite(String name) { |
| super(name); |
| } |
| |
| @Override |
| public void addTest(Test test) { |
| if (test instanceof TestSuite) { |
| doAddTest((TestSuite) test); |
| } else { |
| doAddTest(test); |
| } |
| } |
| |
| private void doAddTest(Test test) { |
| TestSuite moduleSuite = getModuleSuiteFor(test); |
| moduleSuite.addTest(test); |
| } |
| |
| private void doAddTest(TestSuite suite) { |
| Test[] homogenized = homogenize(suite); |
| for (Test test : homogenized) { |
| doAddTest(test); |
| } |
| } |
| |
| /** |
| * Returns the "module" suite this test should be placed in; only accurate for |
| * suites that are homogeneous. |
| */ |
| private TestSuite getModuleSuiteFor(Test test) { |
| if (test instanceof TestSuite) { |
| TestSuite suite = (TestSuite) test; |
| if (suite.countTestCases() == 0) { |
| return getNonGWTTestSuite(); |
| } else { |
| return getModuleSuiteFor(suite.testAt(0)); |
| } |
| } |
| |
| if (test instanceof GWTTestCase) { |
| GWTTestCase gwtTest = (GWTTestCase) test; |
| String moduleName = gwtTest.getSyntheticModuleName(); |
| if (moduleName != null) { |
| TestSuite suite = moduleSuites.get(moduleName); |
| if (suite == null) { |
| suite = new TestSuite(moduleName + ".gwt.xml"); |
| moduleSuites.put(moduleName, suite); |
| super.addTest(suite); |
| } |
| return suite; |
| } else { |
| // Fall-through to group with non-GWT tests. |
| } |
| } |
| |
| return getNonGWTTestSuite(); |
| } |
| |
| private TestSuite getNonGWTTestSuite() { |
| if (nonGWTTestSuite == null) { |
| nonGWTTestSuite = new TestSuite("Non-GWT"); |
| super.addTest(nonGWTTestSuite); |
| } |
| return nonGWTTestSuite; |
| } |
| |
| /** |
| * Breaks non-homogeneous suites into two or more homogeneous suites. A |
| * homogeneous suite is one in which all tests run within a single module. |
| */ |
| private TestSuite[] homogenize(TestSuite suite) { |
| String suiteName = suite.getName(); |
| |
| // Each sub-test is placed into a "bucket" corresponding to its module. |
| List<TestSuite> buckets = new ArrayList<TestSuite>(); |
| Map<TestSuite, TestSuite> moduleToBucket = new HashMap<TestSuite, TestSuite>(); |
| |
| // Sort the sub-tests into buckets by module. |
| for (Enumeration<Test> enumeration = suite.tests(); enumeration.hasMoreElements();) { |
| Test test = enumeration.nextElement(); |
| if (test instanceof TestSuite) { |
| // Recursively homogenize any sub-suites. |
| TestSuite[] subSuites = homogenize((TestSuite) test); |
| for (TestSuite subSuite : subSuites) { |
| sortIntoBucket(subSuite, buckets, moduleToBucket, suiteName); |
| } |
| } else { |
| sortIntoBucket(test, buckets, moduleToBucket, suiteName); |
| } |
| } |
| |
| // Return myself if there's only one bucket; otherwise return the buckets. |
| int numBuckets = buckets.size(); |
| if (numBuckets == 1) { |
| return new TestSuite[] {suite}; |
| } else { |
| return buckets.toArray(new TestSuite[numBuckets]); |
| } |
| } |
| |
| private void sortIntoBucket(Test test, List<TestSuite> buckets, |
| Map<TestSuite, TestSuite> moduleToBucket, String newBucketName) { |
| TestSuite module = getModuleSuiteFor(test); |
| TestSuite bucket = moduleToBucket.get(module); |
| if (bucket == null) { |
| bucket = new TestSuite(newBucketName); |
| buckets.add(bucket); |
| moduleToBucket.put(module, bucket); |
| } |
| bucket.addTest(test); |
| } |
| } |