| /* |
| * Copyright (c) 2008, 2011-2013 Eike Stepper (Berlin, Germany) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.emf.cdo.tests.config.impl; |
| |
| import org.eclipse.emf.cdo.tests.config.IConstants; |
| import org.eclipse.emf.cdo.tests.config.IScenario; |
| import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Requires; |
| import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Skips; |
| |
| import org.eclipse.net4j.util.om.OMBundle; |
| |
| import java.lang.reflect.AnnotatedElement; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Modifier; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| |
| import junit.framework.Test; |
| import junit.framework.TestResult; |
| import junit.framework.TestSuite; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public abstract class ConfigTestSuite implements IConstants |
| { |
| public ConfigTestSuite() |
| { |
| } |
| |
| public Test getTestSuite() |
| { |
| return getTestSuite(getClass().getName()); |
| } |
| |
| public Test getTestSuite(String name) |
| { |
| TestSuite suite = new MainSuite(name); |
| initConfigSuites(suite); |
| return suite; |
| } |
| |
| public void addScenario(TestSuite parent, RepositoryConfig repositoryConfig, SessionConfig sessionConfig, |
| ModelConfig modelConfig) |
| { |
| IScenario scenario = new Scenario(); |
| scenario.setRepositoryConfig(repositoryConfig); |
| scenario.setSessionConfig(sessionConfig); |
| scenario.setModelConfig(modelConfig); |
| |
| if (scenario.isValid()) |
| { |
| TestSuite suite = new TestSuite(scenario.toString()); |
| |
| List<Class<? extends ConfigTest>> testClasses = new ArrayList<Class<? extends ConfigTest>>(); |
| initTestClasses(testClasses, scenario); |
| |
| for (Class<? extends ConfigTest> testClass : testClasses) |
| { |
| try |
| { |
| TestWrapper wrapper = new TestWrapper(testClass, scenario, this); |
| if (wrapper.testCount() != 0) |
| { |
| suite.addTest(wrapper); |
| } |
| } |
| catch (ConstraintsViolatedException ex) |
| { |
| //$FALL-THROUGH$ |
| } |
| } |
| |
| parent.addTest(suite); |
| } |
| } |
| |
| protected List<Class<? extends ConfigTest>> getTestClasses(OMBundle bundle, String packageName) |
| { |
| List<Class<? extends ConfigTest>> result = new ArrayList<Class<? extends ConfigTest>>(); |
| |
| for (Iterator<Class<?>> it = bundle.getClasses(); it.hasNext();) |
| { |
| Class<?> c = it.next(); |
| if (ConfigTest.class.isAssignableFrom(c) && c.getName().startsWith(packageName)) |
| { |
| @SuppressWarnings("unchecked") |
| Class<? extends ConfigTest> configTest = (Class<? extends ConfigTest>)c; |
| result.add(configTest); |
| } |
| } |
| |
| Collections.sort(result, new Comparator<Class<? extends ConfigTest>>() |
| { |
| public int compare(Class<? extends ConfigTest> c1, Class<? extends ConfigTest> c2) |
| { |
| return c1.getName().compareTo(c2.getName()); |
| } |
| }); |
| |
| return result; |
| } |
| |
| protected abstract void initConfigSuites(TestSuite parent); |
| |
| protected abstract void initTestClasses(List<Class<? extends ConfigTest>> testClasses, IScenario scenario); |
| |
| /** |
| * Can be overridden by subclasses. |
| */ |
| protected void prepareTest(ConfigTest configTest) |
| { |
| } |
| |
| /** |
| * Can be overridden by subclasses. |
| */ |
| protected void mainSuiteFinished() |
| { |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class MainSuite extends TestSuite |
| { |
| public MainSuite(String name) |
| { |
| super(name); |
| } |
| |
| @Override |
| public void run(TestResult result) |
| { |
| super.run(result); |
| mainSuiteFinished(); |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private static final class ConstraintsViolatedException extends Exception |
| { |
| private static final long serialVersionUID = 1L; |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private static final class TestWrapper extends TestSuite |
| { |
| private IScenario scenario; |
| |
| public TestWrapper(Class<? extends ConfigTest> testClass, IScenario scenario, ConfigTestSuite suite) |
| throws ConstraintsViolatedException |
| { |
| // super(testClass, testClass.getName()); // Important for the UI to set the *qualified* class name! |
| this.scenario = scenario; |
| addTestsFromTestCase(testClass, suite); |
| } |
| |
| @Override |
| public void runTest(Test test, TestResult result) |
| { |
| if (test instanceof ConfigTest) |
| { |
| scenario.save(); |
| |
| ConfigTest configTest = (ConfigTest)test; |
| configTest.setScenario(scenario); |
| |
| if (configTest.isValid()) |
| { |
| super.runTest(configTest, result); |
| } |
| } |
| else |
| { |
| super.runTest(test, result); |
| } |
| } |
| |
| private void addTestsFromTestCase(final Class<?> theClass, ConfigTestSuite suite) |
| throws ConstraintsViolatedException |
| { |
| setName(theClass.getName()); |
| |
| try |
| { |
| getTestConstructor(theClass); // Avoid generating multiple error messages |
| } |
| catch (NoSuchMethodException e) |
| { |
| addTest(warning("Class " + theClass.getName() |
| + " has no public constructor TestCase(String name) or TestCase()")); |
| return; |
| } |
| |
| if (!Modifier.isPublic(theClass.getModifiers())) |
| { |
| addTest(warning("Class " + theClass.getName() + " is not public")); |
| return; |
| } |
| |
| Set<String> capabilities = scenario.getCapabilities(); |
| |
| Class<?> superClass = theClass; |
| while (Test.class.isAssignableFrom(superClass)) |
| { |
| if (!validateConstraints(superClass, capabilities)) |
| { |
| throw new ConstraintsViolatedException(); |
| } |
| |
| superClass = superClass.getSuperclass(); |
| } |
| |
| List<String> names = new ArrayList<String>(); |
| |
| superClass = theClass; |
| while (Test.class.isAssignableFrom(superClass)) |
| { |
| for (Method method : superClass.getDeclaredMethods()) |
| { |
| if (validateConstraints(method, capabilities)) |
| { |
| addTestMethod(method, names, theClass, suite); |
| } |
| } |
| |
| superClass = superClass.getSuperclass(); |
| } |
| } |
| |
| private boolean validateConstraints(AnnotatedElement element, Set<String> capabilities) |
| { |
| Requires requires = element.getAnnotation(Requires.class); |
| if (requires != null) |
| { |
| for (String require : requires.value()) |
| { |
| if (!capabilities.contains(require)) |
| { |
| return false; |
| } |
| } |
| } |
| |
| Skips skips = element.getAnnotation(Skips.class); |
| if (skips != null) |
| { |
| for (String skip : skips.value()) |
| { |
| if (capabilities.contains(skip)) |
| { |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| private void addTestMethod(Method m, List<String> names, Class<?> theClass, ConfigTestSuite suite) |
| { |
| String name = m.getName(); |
| if (names.contains(name)) |
| { |
| return; |
| } |
| |
| if (!isPublicTestMethod(m)) |
| { |
| if (isTestMethod(m)) |
| { |
| addTest(warning("Test method isn't public: " + m.getName() + "(" + theClass.getCanonicalName() + ")")); |
| } |
| |
| return; |
| } |
| |
| names.add(name); |
| Test test = createTest(theClass, name); |
| if (test instanceof ConfigTest) |
| { |
| ConfigTest configTest = (ConfigTest)test; |
| suite.prepareTest(configTest); |
| } |
| |
| addTest(test); |
| } |
| |
| private boolean isPublicTestMethod(Method m) |
| { |
| return isTestMethod(m) && Modifier.isPublic(m.getModifiers()); |
| } |
| |
| private boolean isTestMethod(Method m) |
| { |
| return m.getParameterTypes().length == 0 && m.getName().startsWith("test") && m.getReturnType().equals(Void.TYPE); |
| } |
| } |
| } |