| @@ -161,7 +161,7 @@ jjdoc=org.apache.tools.ant.taskdefs.optional.javacc.JJDoc | |||
| jjtree=org.apache.tools.ant.taskdefs.optional.javacc.JJTree | |||
| junit=org.apache.tools.ant.taskdefs.optional.junit.JUnitTask | |||
| junitreport=org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator | |||
| junitlauncher=org.apache.tools.ant.taskdefs.optional.junitlauncher.JUnitLauncherTask | |||
| junitlauncher=org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask | |||
| native2ascii=org.apache.tools.ant.taskdefs.optional.Native2Ascii | |||
| netrexxc=org.apache.tools.ant.taskdefs.optional.NetRexxC | |||
| propertyfile=org.apache.tools.ant.taskdefs.optional.PropertyFile | |||
| @@ -1,54 +0,0 @@ | |||
| /* | |||
| * Licensed to the Apache Software Foundation (ASF) under one or more | |||
| * contributor license agreements. See the NOTICE file distributed with | |||
| * this work for additional information regarding copyright ownership. | |||
| * The ASF licenses this file to You 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 org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| /** | |||
| * Constants used within the junitlauncher task | |||
| */ | |||
| final class Constants { | |||
| static final int FORK_EXIT_CODE_SUCCESS = 0; | |||
| static final int FORK_EXIT_CODE_EXCEPTION = 1; | |||
| static final int FORK_EXIT_CODE_TESTS_FAILED = 2; | |||
| static final int FORK_EXIT_CODE_TIMED_OUT = 3; | |||
| static final String ARG_PROPERTIES = "--properties"; | |||
| static final String ARG_LAUNCH_DEFINITION = "--launch-definition"; | |||
| static final String LD_XML_ELM_LAUNCH_DEF = "launch-definition"; | |||
| static final String LD_XML_ELM_TEST = "test"; | |||
| static final String LD_XML_ELM_TEST_CLASSES = "test-classes"; | |||
| static final String LD_XML_ATTR_HALT_ON_FAILURE = "haltOnFailure"; | |||
| static final String LD_XML_ATTR_OUTPUT_DIRECTORY = "outDir"; | |||
| static final String LD_XML_ATTR_INCLUDE_ENGINES = "includeEngines"; | |||
| static final String LD_XML_ATTR_EXCLUDE_ENGINES = "excludeEngines"; | |||
| static final String LD_XML_ATTR_CLASS_NAME = "classname"; | |||
| static final String LD_XML_ATTR_METHODS = "methods"; | |||
| static final String LD_XML_ATTR_PRINT_SUMMARY = "printSummary"; | |||
| static final String LD_XML_ELM_LISTENER = "listener"; | |||
| static final String LD_XML_ATTR_SEND_SYS_ERR = "sendSysErr"; | |||
| static final String LD_XML_ATTR_SEND_SYS_OUT = "sendSysOut"; | |||
| static final String LD_XML_ATTR_LISTENER_RESULT_FILE = "resultFile"; | |||
| private Constants() { | |||
| } | |||
| } | |||
| @@ -0,0 +1,50 @@ | |||
| /* | |||
| * Licensed to the Apache Software Foundation (ASF) under one or more | |||
| * contributor license agreements. See the NOTICE file distributed with | |||
| * this work for additional information regarding copyright ownership. | |||
| * The ASF licenses this file to You 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 org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask; | |||
| import java.util.Optional; | |||
| import java.util.Properties; | |||
| /** | |||
| * Used during in-vm (non-forked mode) launching of tests | |||
| */ | |||
| public class InVMExecution implements TestExecutionContext { | |||
| private final JUnitLauncherTask task; | |||
| private final Properties props; | |||
| public InVMExecution(final JUnitLauncherTask task) { | |||
| this.task = task; | |||
| this.props = new Properties(); | |||
| this.props.putAll(task.getProject().getProperties()); | |||
| } | |||
| @Override | |||
| public Properties getProperties() { | |||
| return this.props; | |||
| } | |||
| @Override | |||
| public Optional<Project> getProject() { | |||
| return Optional.of(this.task.getProject()); | |||
| } | |||
| } | |||
| @@ -21,12 +21,22 @@ package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.MagicNames; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.LaunchDefinition; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.ListenerDefinition; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.NamedTest; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.SingleTestClass; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestClasses; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestDefinition; | |||
| import org.apache.tools.ant.util.FileUtils; | |||
| import org.apache.tools.ant.util.KeepAliveOutputStream; | |||
| import org.junit.platform.engine.Filter; | |||
| import org.junit.platform.engine.discovery.DiscoverySelectors; | |||
| import org.junit.platform.launcher.EngineFilter; | |||
| import org.junit.platform.launcher.Launcher; | |||
| import org.junit.platform.launcher.LauncherDiscoveryRequest; | |||
| import org.junit.platform.launcher.TestExecutionListener; | |||
| import org.junit.platform.launcher.TestPlan; | |||
| import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; | |||
| import org.junit.platform.launcher.core.LauncherFactory; | |||
| import org.junit.platform.launcher.listeners.SummaryGeneratingListener; | |||
| import org.junit.platform.launcher.listeners.TestExecutionSummary; | |||
| @@ -67,23 +77,33 @@ import java.util.concurrent.TimeUnit; | |||
| * <p> | |||
| * This class is not thread-safe and isn't expected to be used for launching from | |||
| * multiple different threads simultaneously. | |||
| * <p>This class is an internal implementation detail of the Ant project and although | |||
| * it's a public class, it isn't meant to be used outside of this project. This class | |||
| * can be changed, across releases, without any backward compatible guarantees and hence | |||
| * shouldn't be used or relied upon outside of this project. | |||
| */ | |||
| class LauncherSupport { | |||
| public class LauncherSupport { | |||
| private final LaunchDefinition launchDefinition; | |||
| private final TestExecutionContext testExecutionContext; | |||
| private boolean testsFailed; | |||
| /** | |||
| * Create a {@link LauncherSupport} for the passed {@link LaunchDefinition} | |||
| * | |||
| * @param definition The launch definition which will be used for launching the tests | |||
| * @param definition The launch definition which will be used for launching the tests | |||
| * @param testExecutionContext The {@link TestExecutionContext} to use for the tests | |||
| */ | |||
| LauncherSupport(final LaunchDefinition definition) { | |||
| public LauncherSupport(final LaunchDefinition definition, final TestExecutionContext testExecutionContext) { | |||
| if (definition == null) { | |||
| throw new IllegalArgumentException("Launch definition cannot be null"); | |||
| } | |||
| if (testExecutionContext == null) { | |||
| throw new IllegalArgumentException("Test execution context cannot be null"); | |||
| } | |||
| this.launchDefinition = definition; | |||
| this.testExecutionContext = testExecutionContext; | |||
| } | |||
| /** | |||
| @@ -93,7 +113,7 @@ class LauncherSupport { | |||
| * an exception, or if any other exception occurred before or after launching | |||
| * the tests | |||
| */ | |||
| void launch() throws BuildException { | |||
| public void launch() throws BuildException { | |||
| final ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader(); | |||
| try { | |||
| Thread.currentThread().setContextClassLoader(this.launchDefinition.getClassLoader()); | |||
| @@ -162,7 +182,14 @@ class LauncherSupport { | |||
| } | |||
| final List<TestRequest> requests = new ArrayList<>(); | |||
| for (final TestDefinition test : tests) { | |||
| final List<TestRequest> testRequests = test.createTestRequests(); | |||
| final List<TestRequest> testRequests; | |||
| if (test instanceof SingleTestClass) { | |||
| testRequests = createTestRequests((SingleTestClass) test); | |||
| } else if (test instanceof TestClasses) { | |||
| testRequests = createTestRequests((TestClasses) test); | |||
| } else { | |||
| throw new BuildException("Unexpected test definition type " + test.getClass().getName()); | |||
| } | |||
| if (testRequests == null || testRequests.isEmpty()) { | |||
| continue; | |||
| } | |||
| @@ -176,7 +203,7 @@ class LauncherSupport { | |||
| final List<ListenerDefinition> applicableListenerElements = test.getListeners().isEmpty() | |||
| ? this.launchDefinition.getListeners() : test.getListeners(); | |||
| final List<TestExecutionListener> listeners = new ArrayList<>(); | |||
| final Optional<Project> project = this.launchDefinition.getTestExecutionContext().getProject(); | |||
| final Optional<Project> project = this.testExecutionContext.getProject(); | |||
| for (final ListenerDefinition applicableListener : applicableListenerElements) { | |||
| if (project.isPresent() && !applicableListener.shouldUse(project.get())) { | |||
| log("Excluding listener " + applicableListener.getClassName() + " since it's not applicable" + | |||
| @@ -198,7 +225,7 @@ class LauncherSupport { | |||
| testRequest.closeUponCompletion(resultFormatter); | |||
| // set the execution context | |||
| resultFormatter.setContext(this.launchDefinition.getTestExecutionContext()); | |||
| resultFormatter.setContext(this.testExecutionContext); | |||
| // set the destination output stream for writing out the formatted result | |||
| final java.nio.file.Path resultOutputFile = getListenerOutputFile(testRequest, formatterDefinition); | |||
| try { | |||
| @@ -230,7 +257,7 @@ class LauncherSupport { | |||
| return Paths.get(test.getOutputDir(), filename); | |||
| } | |||
| // neither listener nor the test define a output dir, so use basedir of the project | |||
| final TestExecutionContext testExecutionContext = this.launchDefinition.getTestExecutionContext(); | |||
| final TestExecutionContext testExecutionContext = this.testExecutionContext; | |||
| final String baseDir = testExecutionContext.getProperties().getProperty(MagicNames.PROJECT_BASEDIR); | |||
| return Paths.get(baseDir, filename); | |||
| } | |||
| @@ -270,7 +297,7 @@ class LauncherSupport { | |||
| if (hasTestFailures && test.getFailureProperty() != null) { | |||
| // if there are test failures and the test is configured to set a property in case | |||
| // of failure, then set the property to true | |||
| final TestExecutionContext testExecutionContext = this.launchDefinition.getTestExecutionContext(); | |||
| final TestExecutionContext testExecutionContext = this.testExecutionContext; | |||
| if (testExecutionContext.getProject().isPresent()) { | |||
| final Project project = testExecutionContext.getProject().get(); | |||
| project.setNewProperty(test.getFailureProperty(), "true"); | |||
| @@ -351,7 +378,7 @@ class LauncherSupport { | |||
| } | |||
| private void log(final String message, final Throwable t, final int level) { | |||
| final TestExecutionContext testExecutionContext = this.launchDefinition.getTestExecutionContext(); | |||
| final TestExecutionContext testExecutionContext = this.testExecutionContext; | |||
| if (testExecutionContext.getProject().isPresent()) { | |||
| testExecutionContext.getProject().get().log(message, t, level); | |||
| return; | |||
| @@ -364,6 +391,63 @@ class LauncherSupport { | |||
| } | |||
| } | |||
| private List<TestRequest> createTestRequests(final TestDefinition test) { | |||
| // create a TestRequest and add necessary selectors, filters to it | |||
| final LauncherDiscoveryRequestBuilder requestBuilder = LauncherDiscoveryRequestBuilder.request(); | |||
| final TestRequest request = new TestRequest(test, requestBuilder); | |||
| addDiscoverySelectors(request); | |||
| addFilters(request); | |||
| return Collections.singletonList(request); | |||
| } | |||
| private void addDiscoverySelectors(final TestRequest testRequest) { | |||
| final TestDefinition test = testRequest.getOwner(); | |||
| final LauncherDiscoveryRequestBuilder requestBuilder = testRequest.getDiscoveryRequest(); | |||
| if (test instanceof SingleTestClass) { | |||
| final SingleTestClass singleTestClass = (SingleTestClass) test; | |||
| final String[] methods = singleTestClass.getMethods(); | |||
| if (methods == null) { | |||
| requestBuilder.selectors(DiscoverySelectors.selectClass(singleTestClass.getName())); | |||
| } else { | |||
| // add specific methods | |||
| for (final String method : methods) { | |||
| requestBuilder.selectors(DiscoverySelectors.selectMethod(singleTestClass.getName(), method)); | |||
| } | |||
| } | |||
| return; | |||
| } | |||
| if (test instanceof TestClasses) { | |||
| final TestClasses testClasses = (TestClasses) test; | |||
| final List<String> testClassNames = testClasses.getTestClassNames(); | |||
| if (testClassNames.isEmpty()) { | |||
| return; | |||
| } | |||
| for (final String testClass : testClassNames) { | |||
| requestBuilder.selectors(DiscoverySelectors.selectClass(testClass)); | |||
| } | |||
| return; | |||
| } | |||
| } | |||
| /** | |||
| * Add necessary {@link Filter JUnit filters} to the {@code testRequest} | |||
| * | |||
| * @param testRequest The test request | |||
| */ | |||
| private void addFilters(final TestRequest testRequest) { | |||
| final LauncherDiscoveryRequestBuilder requestBuilder = testRequest.getDiscoveryRequest(); | |||
| // add any engine filters | |||
| final String[] enginesToInclude = testRequest.getOwner().getIncludeEngines(); | |||
| if (enginesToInclude != null && enginesToInclude.length > 0) { | |||
| requestBuilder.filters(EngineFilter.includeEngines(enginesToInclude)); | |||
| } | |||
| final String[] enginesToExclude = testRequest.getOwner().getExcludeEngines(); | |||
| if (enginesToExclude != null && enginesToExclude.length > 0) { | |||
| requestBuilder.filters(EngineFilter.excludeEngines(enginesToExclude)); | |||
| } | |||
| } | |||
| private enum StreamType { | |||
| SYS_OUT, | |||
| SYS_ERR | |||
| @@ -20,6 +20,13 @@ package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.LaunchDefinition; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.ListenerDefinition; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.SingleTestClass; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestClasses; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestDefinition; | |||
| import javax.xml.stream.XMLInputFactory; | |||
| import javax.xml.stream.XMLStreamReader; | |||
| @@ -37,12 +44,12 @@ import static javax.xml.stream.XMLStreamConstants.END_DOCUMENT; | |||
| import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; | |||
| import static javax.xml.stream.XMLStreamConstants.START_DOCUMENT; | |||
| import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_HALT_ON_FAILURE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_PRINT_SUMMARY; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ELM_LAUNCH_DEF; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ELM_LISTENER; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ELM_TEST; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ELM_TEST_CLASSES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_HALT_ON_FAILURE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_PRINT_SUMMARY; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_LAUNCH_DEF; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_LISTENER; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST_CLASSES; | |||
| /** | |||
| * Used for launching forked tests from the {@link JUnitLauncherTask}. | |||
| @@ -98,8 +105,7 @@ public class StandaloneLauncher { | |||
| i = i + numArgsConsumed; | |||
| } | |||
| launchDefinition.setTestExecutionContext(forkedExecution); | |||
| final LauncherSupport launcherSupport = new LauncherSupport(launchDefinition); | |||
| final LauncherSupport launcherSupport = new LauncherSupport(launchDefinition, forkedExecution); | |||
| try { | |||
| launcherSupport.launch(); | |||
| } catch (Throwable t) { | |||
| @@ -240,19 +246,9 @@ public class StandaloneLauncher { | |||
| return this; | |||
| } | |||
| public ForkedLaunch setTestExecutionContext(final TestExecutionContext testExecutionContext) { | |||
| this.testExecutionContext = testExecutionContext; | |||
| return this; | |||
| } | |||
| @Override | |||
| public ClassLoader getClassLoader() { | |||
| return this.getClass().getClassLoader(); | |||
| } | |||
| @Override | |||
| public TestExecutionContext getTestExecutionContext() { | |||
| return this.testExecutionContext; | |||
| } | |||
| } | |||
| } | |||
| @@ -18,6 +18,7 @@ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask; | |||
| import java.util.Optional; | |||
| import java.util.Properties; | |||
| @@ -17,6 +17,8 @@ | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestDefinition; | |||
| import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; | |||
| import java.io.Closeable; | |||
| @@ -0,0 +1,54 @@ | |||
| /* | |||
| * Licensed to the Apache Software Foundation (ASF) under one or more | |||
| * contributor license agreements. See the NOTICE file distributed with | |||
| * this work for additional information regarding copyright ownership. | |||
| * The ASF licenses this file to You 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 org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| /** | |||
| * Constants used within the junitlauncher task | |||
| */ | |||
| public final class Constants { | |||
| public static final int FORK_EXIT_CODE_SUCCESS = 0; | |||
| public static final int FORK_EXIT_CODE_EXCEPTION = 1; | |||
| public static final int FORK_EXIT_CODE_TESTS_FAILED = 2; | |||
| public static final int FORK_EXIT_CODE_TIMED_OUT = 3; | |||
| public static final String ARG_PROPERTIES = "--properties"; | |||
| public static final String ARG_LAUNCH_DEFINITION = "--launch-definition"; | |||
| public static final String LD_XML_ELM_LAUNCH_DEF = "launch-definition"; | |||
| public static final String LD_XML_ELM_TEST = "test"; | |||
| public static final String LD_XML_ELM_TEST_CLASSES = "test-classes"; | |||
| public static final String LD_XML_ATTR_HALT_ON_FAILURE = "haltOnFailure"; | |||
| public static final String LD_XML_ATTR_OUTPUT_DIRECTORY = "outDir"; | |||
| public static final String LD_XML_ATTR_INCLUDE_ENGINES = "includeEngines"; | |||
| public static final String LD_XML_ATTR_EXCLUDE_ENGINES = "excludeEngines"; | |||
| public static final String LD_XML_ATTR_CLASS_NAME = "classname"; | |||
| public static final String LD_XML_ATTR_METHODS = "methods"; | |||
| public static final String LD_XML_ATTR_PRINT_SUMMARY = "printSummary"; | |||
| public static final String LD_XML_ELM_LISTENER = "listener"; | |||
| public static final String LD_XML_ATTR_SEND_SYS_ERR = "sendSysErr"; | |||
| public static final String LD_XML_ATTR_SEND_SYS_OUT = "sendSysOut"; | |||
| public static final String LD_XML_ATTR_LISTENER_RESULT_FILE = "resultFile"; | |||
| private Constants() { | |||
| } | |||
| } | |||
| @@ -16,23 +16,16 @@ | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.launch.AntMain; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.StandaloneLauncher; | |||
| import org.apache.tools.ant.types.Commandline; | |||
| import org.apache.tools.ant.types.CommandlineJava; | |||
| import org.apache.tools.ant.types.Environment; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.types.PropertySet; | |||
| import org.apache.tools.ant.util.LoaderUtils; | |||
| import org.junit.platform.commons.annotation.Testable; | |||
| import org.junit.platform.engine.TestEngine; | |||
| import org.junit.platform.launcher.core.LauncherFactory; | |||
| import java.io.File; | |||
| /** | |||
| * Represents the {@code fork} element within test definitions of the | |||
| @@ -124,45 +117,26 @@ public class ForkDefinition { | |||
| cmdLine.setClassname(StandaloneLauncher.class.getName()); | |||
| // VM arguments | |||
| final Project project = task.getProject(); | |||
| final Path antRuntimeResourceSources = new Path(project); | |||
| final ClassLoader taskClassLoader = task.getClass().getClassLoader(); | |||
| // Ant runtime classes | |||
| if (this.includeAntRuntimeLibraries) { | |||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(AntMain.class)); | |||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(Task.class)); | |||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(JUnitLauncherTask.class)); | |||
| final Path antRuntimeResources = new Path(project); | |||
| JUnitLauncherClassPathUtil.addAntRuntimeResourceLocations(antRuntimeResources, taskClassLoader); | |||
| final Path classPath = cmdLine.createClasspath(project); | |||
| classPath.createPath().append(antRuntimeResources); | |||
| } else { | |||
| task.log("Excluding Ant runtime libraries from forked JVM classpath", Project.MSG_DEBUG); | |||
| } | |||
| // JUnit platform classes | |||
| if (this.includeJUnitPlatformLibraries) { | |||
| // platform-engine | |||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(TestEngine.class)); | |||
| // platform-launcher | |||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(LauncherFactory.class)); | |||
| // platform-commons | |||
| addAntRuntimeResourceSource(antRuntimeResourceSources, task, toResourceName(Testable.class)); | |||
| final Path junitPlatformResources = new Path(project); | |||
| JUnitLauncherClassPathUtil.addJUnitPlatformResourceLocations(junitPlatformResources, taskClassLoader); | |||
| final Path classPath = cmdLine.createClasspath(project); | |||
| classPath.createPath().append(junitPlatformResources); | |||
| } else { | |||
| task.log("Excluding JUnit platform libraries from forked JVM classpath", Project.MSG_DEBUG); | |||
| } | |||
| final Path classPath = cmdLine.createClasspath(project); | |||
| classPath.createPath().append(antRuntimeResourceSources); | |||
| return cmdLine; | |||
| } | |||
| private static boolean addAntRuntimeResourceSource(final Path path, final JUnitLauncherTask task, final String resource) { | |||
| final File f = LoaderUtils.getResourceSource(task.getClass().getClassLoader(), resource); | |||
| if (f == null) { | |||
| task.log("Could not locate source of resource " + resource); | |||
| return false; | |||
| } | |||
| task.log("Found source " + f + " of resource " + resource); | |||
| path.createPath().setLocation(f); | |||
| return true; | |||
| } | |||
| private static String toResourceName(final Class klass) { | |||
| final String name = klass.getName(); | |||
| return name.replaceAll("\\.", "/") + ".class"; | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| /* | |||
| * Licensed to the Apache Software Foundation (ASF) under one or more | |||
| * contributor license agreements. See the NOTICE file distributed with | |||
| * this work for additional information regarding copyright ownership. | |||
| * The ASF licenses this file to You 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 org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.launch.AntMain; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.util.LoaderUtils; | |||
| import java.io.File; | |||
| /** | |||
| * | |||
| */ | |||
| final class JUnitLauncherClassPathUtil { | |||
| private static final String RESOURCE_IN_PLATFORM_ENGINE = "org/junit/platform/engine/TestEngine.class"; | |||
| private static final String RESOURCE_IN_PLATFORM_LAUNCHER = "org/junit/platform/launcher/core/LauncherFactory.class"; | |||
| private static final String RESOURCE_IN_PLATFORM_COMMON = "org/junit/platform/commons/annotation/Testable.class"; | |||
| private static final String RESOURCE_NAME_LAUNCHER_SUPPORT = "org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.class"; | |||
| static void addAntRuntimeResourceLocations(final Path path, final ClassLoader classLoader) { | |||
| addResourceLocationToPath(path, classLoader, toResourceName(AntMain.class)); | |||
| addResourceLocationToPath(path, classLoader, toResourceName(Task.class)); | |||
| addResourceLocationToPath(path, classLoader, RESOURCE_NAME_LAUNCHER_SUPPORT); | |||
| } | |||
| static void addLauncherSupportResourceLocation(final Path path, final ClassLoader classLoader) { | |||
| addResourceLocationToPath(path, classLoader, RESOURCE_NAME_LAUNCHER_SUPPORT); | |||
| } | |||
| static void addJUnitPlatformResourceLocations(final Path path, final ClassLoader classLoader) { | |||
| // platform-engine | |||
| addResourceLocationToPath(path, classLoader, RESOURCE_IN_PLATFORM_ENGINE); | |||
| // platform-launcher | |||
| addResourceLocationToPath(path, classLoader, RESOURCE_IN_PLATFORM_LAUNCHER); | |||
| // platform-commons | |||
| addResourceLocationToPath(path, classLoader, RESOURCE_IN_PLATFORM_COMMON); | |||
| } | |||
| static boolean addResourceLocationToPath(final Path path, final ClassLoader classLoader, final String resource) { | |||
| final File f = LoaderUtils.getResourceSource(classLoader, resource); | |||
| if (f == null) { | |||
| return false; | |||
| } | |||
| path.createPath().setLocation(f); | |||
| return true; | |||
| } | |||
| static boolean hasJUnitPlatformResources(final ClassLoader cl) { | |||
| final File f = LoaderUtils.getResourceSource(cl, RESOURCE_IN_PLATFORM_ENGINE); | |||
| return f != null; | |||
| } | |||
| private static String toResourceName(final Class klass) { | |||
| final String name = klass.getName(); | |||
| return name.replaceAll("\\.", "/") + ".class"; | |||
| } | |||
| } | |||
| @@ -15,7 +15,7 @@ | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| import org.apache.tools.ant.AntClassLoader; | |||
| import org.apache.tools.ant.BuildException; | |||
| @@ -40,13 +40,12 @@ import java.util.ArrayList; | |||
| import java.util.Collections; | |||
| import java.util.Hashtable; | |||
| import java.util.List; | |||
| import java.util.Optional; | |||
| import java.util.Properties; | |||
| import java.util.concurrent.TimeoutException; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_HALT_ON_FAILURE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_PRINT_SUMMARY; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ELM_LAUNCH_DEF; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_HALT_ON_FAILURE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_PRINT_SUMMARY; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_LAUNCH_DEF; | |||
| /** | |||
| * An Ant {@link Task} responsible for launching the JUnit platform for running tests. | |||
| @@ -66,6 +65,10 @@ import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_ | |||
| */ | |||
| public class JUnitLauncherTask extends Task { | |||
| private static final String LAUNCHER_SUPPORT_CLASS_NAME = "org.apache.tools.ant.taskdefs.optional.junitlauncher.LauncherSupport"; | |||
| private static final String IN_VM_TEST_EXECUTION_CONTEXT_CLASS_NAME = "org.apache.tools.ant.taskdefs.optional.junitlauncher.InVMExecution"; | |||
| private static final String TEST_EXECUTION_CONTEXT_CLASS_NAME = "org.apache.tools.ant.taskdefs.optional.junitlauncher.TestExecutionContext"; | |||
| private Path classPath; | |||
| private boolean haltOnFailure; | |||
| private String failureProperty; | |||
| @@ -91,8 +94,7 @@ public class JUnitLauncherTask extends Task { | |||
| if (test.getForkDefinition() != null) { | |||
| forkTest(test); | |||
| } else { | |||
| final LauncherSupport launcherSupport = new LauncherSupport(new InVMLaunch(Collections.singletonList(test))); | |||
| launcherSupport.launch(); | |||
| launchViaReflection(new InVMLaunch(Collections.singletonList(test))); | |||
| } | |||
| } | |||
| } | |||
| @@ -165,14 +167,29 @@ public class JUnitLauncherTask extends Task { | |||
| } | |||
| } | |||
| private ClassLoader createClassLoaderForTestExecution() { | |||
| if (this.classPath == null) { | |||
| return this.getClass().getClassLoader(); | |||
| private void launchViaReflection(final InVMLaunch launchDefinition) { | |||
| final ClassLoader cl = launchDefinition.getClassLoader(); | |||
| // instantiate a new TestExecutionContext instance using the launch definition's classloader | |||
| final Class<?> testExecutionCtxClass; | |||
| final Object testExecutionCtx; | |||
| try { | |||
| testExecutionCtxClass = Class.forName(TEST_EXECUTION_CONTEXT_CLASS_NAME, false, cl); | |||
| final Class<?> klass = Class.forName(IN_VM_TEST_EXECUTION_CONTEXT_CLASS_NAME, false, cl); | |||
| testExecutionCtx = klass.getConstructor(JUnitLauncherTask.class).newInstance(this); | |||
| } catch (Exception e) { | |||
| throw new BuildException("Failed to create a test execution context for in-vm tests", e); | |||
| } | |||
| // instantiate a new LauncherSupport instance using the launch definition's ClassLoader | |||
| try { | |||
| final Class<?> klass = Class.forName(LAUNCHER_SUPPORT_CLASS_NAME, false, cl); | |||
| final Object launcherSupport = klass.getConstructor(LaunchDefinition.class, testExecutionCtxClass) | |||
| .newInstance(launchDefinition, testExecutionCtx); | |||
| klass.getMethod("launch").invoke(launcherSupport); | |||
| } catch (Exception e) { | |||
| throw new BuildException("Failed to launch in-vm tests", e); | |||
| } | |||
| return new AntClassLoader(this.getClass().getClassLoader(), getProject(), this.classPath, true); | |||
| } | |||
| private java.nio.file.Path dumpProjectProperties() throws IOException { | |||
| final java.nio.file.Path propsPath = Files.createTempFile(null, "properties"); | |||
| propsPath.toFile().deleteOnExit(); | |||
| @@ -312,35 +329,14 @@ public class JUnitLauncherTask extends Task { | |||
| return xmlFilePath; | |||
| } | |||
| private final class InVMExecution implements TestExecutionContext { | |||
| private final Properties props; | |||
| InVMExecution() { | |||
| this.props = new Properties(); | |||
| this.props.putAll(JUnitLauncherTask.this.getProject().getProperties()); | |||
| } | |||
| @Override | |||
| public Properties getProperties() { | |||
| return this.props; | |||
| } | |||
| @Override | |||
| public Optional<Project> getProject() { | |||
| return Optional.of(JUnitLauncherTask.this.getProject()); | |||
| } | |||
| } | |||
| private final class InVMLaunch implements LaunchDefinition { | |||
| private final TestExecutionContext testExecutionContext = new InVMExecution(); | |||
| private final List<TestDefinition> inVMTests; | |||
| private final ClassLoader executionCL; | |||
| private InVMLaunch(final List<TestDefinition> inVMTests) { | |||
| this.inVMTests = inVMTests; | |||
| this.executionCL = createClassLoaderForTestExecution(); | |||
| this.executionCL = createInVMExecutionClassLoader(); | |||
| } | |||
| @Override | |||
| @@ -368,9 +364,73 @@ public class JUnitLauncherTask extends Task { | |||
| return this.executionCL; | |||
| } | |||
| private ClassLoader createInVMExecutionClassLoader() { | |||
| final Path taskConfiguredClassPath = JUnitLauncherTask.this.classPath; | |||
| if (taskConfiguredClassPath == null) { | |||
| // no specific classpath configured for the task, so use the classloader | |||
| // of this task | |||
| return JUnitLauncherTask.class.getClassLoader(); | |||
| } | |||
| // there's a classpath configured for the task. | |||
| // we first check if the Ant runtime classpath has JUnit platform classes. | |||
| // - if it does, then we use the Ant runtime classpath plus the task's configured classpath | |||
| // with the traditional parent first loading. | |||
| // - else (i.e. Ant runtime classpath doesn't have JUnit platform classes), then we | |||
| // expect/assume the task's configured classpath to have the JUnit platform classes and we | |||
| // then create a "overriding" classloader which prefers certain resources (specifically the classes | |||
| // from org.apache.tools.ant.taskdefs.optional.junitlauncher package), from the task's | |||
| // classpath, even if the Ant's runtime classpath has those resources. | |||
| if (JUnitLauncherClassPathUtil.hasJUnitPlatformResources(JUnitLauncherTask.class.getClassLoader())) { | |||
| return new AntClassLoader(JUnitLauncherTask.class.getClassLoader(), getProject(), taskConfiguredClassPath, true); | |||
| } | |||
| final Path cp = new Path(getProject()); | |||
| cp.add(taskConfiguredClassPath); | |||
| // add the Ant runtime resources to this path | |||
| JUnitLauncherClassPathUtil.addLauncherSupportResourceLocation(cp, JUnitLauncherTask.class.getClassLoader()); | |||
| return new TaskConfiguredPathClassLoader(JUnitLauncherTask.class.getClassLoader(), cp, getProject()); | |||
| } | |||
| } | |||
| /** | |||
| * A {@link ClassLoader}, very similar to the {@link org.apache.tools.ant.util.SplitClassLoader}, | |||
| * which uses the {@link #TaskConfiguredPathClassLoader(ClassLoader, Path, Project) configured Path} | |||
| * to load a class, if the class belongs to the {@code org.apache.tools.ant.taskdefs.optional.junitlauncher} | |||
| * package. | |||
| * <p> | |||
| * While looking for classes belonging to the {@code org.apache.tools.ant.taskdefs.optional.junitlauncher} | |||
| * package, this classloader completely ignores Ant runtime classpath, even if that classpath has | |||
| * those classes. This allows the users of this classloader to use a custom location and thus more control over | |||
| * where these classes reside, when running the {@code junitlauncher} task | |||
| */ | |||
| private final class TaskConfiguredPathClassLoader extends AntClassLoader { | |||
| /** | |||
| * @param parent ClassLoader | |||
| * @param path Path | |||
| * @param project Project | |||
| */ | |||
| private TaskConfiguredPathClassLoader(ClassLoader parent, Path path, Project project) { | |||
| super(parent, project, path, true); | |||
| } | |||
| // forceLoadClass is not convenient here since it would not | |||
| // properly deal with inner classes of these classes. | |||
| @Override | |||
| public TestExecutionContext getTestExecutionContext() { | |||
| return this.testExecutionContext; | |||
| protected synchronized Class<?> loadClass(String classname, boolean resolve) | |||
| throws ClassNotFoundException { | |||
| Class<?> theClass = findLoadedClass(classname); | |||
| if (theClass != null) { | |||
| return theClass; | |||
| } | |||
| final String packageName = classname.substring(0, classname.lastIndexOf('.')); | |||
| if (packageName.equals("org.apache.tools.ant.taskdefs.optional.junitlauncher")) { | |||
| theClass = findClass(classname); | |||
| if (resolve) { | |||
| resolveClass(theClass); | |||
| } | |||
| return theClass; | |||
| } | |||
| return super.loadClass(classname, resolve); | |||
| } | |||
| } | |||
| } | |||
| @@ -16,7 +16,7 @@ | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| import java.util.List; | |||
| @@ -28,42 +28,31 @@ public interface LaunchDefinition { | |||
| /** | |||
| * @return Returns the {@link TestDefinition tests} that have to be launched | |||
| * | |||
| */ | |||
| List<TestDefinition> getTests(); | |||
| /** | |||
| * @return Returns the default {@link ListenerDefinition listeners} that will be used | |||
| * for the tests, if the {@link #getTests() tests} themselves don't specify any | |||
| * | |||
| */ | |||
| List<ListenerDefinition> getListeners(); | |||
| /** | |||
| * @return Returns true if a summary needs to be printed out after the execution of the | |||
| * tests. False otherwise. | |||
| * | |||
| */ | |||
| boolean isPrintSummary(); | |||
| /** | |||
| * @return Returns true if any remaining tests launch need to be stopped if any test execution | |||
| * failed. False otherwise. | |||
| * | |||
| */ | |||
| boolean isHaltOnFailure(); | |||
| /** | |||
| * @return Returns the {@link ClassLoader} that has to be used for launching and execution of the | |||
| * tests | |||
| * | |||
| */ | |||
| ClassLoader getClassLoader(); | |||
| /** | |||
| * @return Returns the {@link TestExecutionContext} that will be passed to {@link TestResultFormatter#setContext(TestExecutionContext) | |||
| * result formatters} which are applicable during the execution of the tests. | |||
| * | |||
| */ | |||
| TestExecutionContext getTestExecutionContext(); | |||
| } | |||
| @@ -15,7 +15,7 @@ | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.PropertyHelper; | |||
| @@ -26,11 +26,11 @@ import javax.xml.stream.XMLStreamException; | |||
| import javax.xml.stream.XMLStreamReader; | |||
| import javax.xml.stream.XMLStreamWriter; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_CLASS_NAME; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_LISTENER_RESULT_FILE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_SEND_SYS_ERR; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_SEND_SYS_OUT; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ELM_LISTENER; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_CLASS_NAME; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_LISTENER_RESULT_FILE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_SEND_SYS_ERR; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_SEND_SYS_OUT; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_LISTENER; | |||
| /** | |||
| * Represents the {@code <listener>} element within the {@code <junitlauncher>} | |||
| @@ -59,7 +59,7 @@ public class ListenerDefinition { | |||
| this.className = className; | |||
| } | |||
| String getClassName() { | |||
| public String getClassName() { | |||
| return this.className; | |||
| } | |||
| @@ -100,7 +100,7 @@ public class ListenerDefinition { | |||
| this.resultFile = filename; | |||
| } | |||
| String requireResultFile(final TestDefinition test) { | |||
| public String requireResultFile(final TestDefinition test) { | |||
| if (this.resultFile != null) { | |||
| return this.resultFile; | |||
| } | |||
| @@ -125,7 +125,7 @@ public class ListenerDefinition { | |||
| this.sendSysOut = sendSysOut; | |||
| } | |||
| boolean shouldSendSysOut() { | |||
| public boolean shouldSendSysOut() { | |||
| return this.sendSysOut; | |||
| } | |||
| @@ -133,7 +133,7 @@ public class ListenerDefinition { | |||
| this.sendSysErr = sendSysErr; | |||
| } | |||
| boolean shouldSendSysErr() { | |||
| public boolean shouldSendSysErr() { | |||
| return this.sendSysErr; | |||
| } | |||
| @@ -147,11 +147,11 @@ public class ListenerDefinition { | |||
| this.outputDir = dir; | |||
| } | |||
| String getOutputDir() { | |||
| public String getOutputDir() { | |||
| return this.outputDir; | |||
| } | |||
| protected boolean shouldUse(final Project project) { | |||
| public boolean shouldUse(final Project project) { | |||
| final PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(project); | |||
| return propertyHelper.testIfCondition(this.ifProperty) && propertyHelper.testUnlessCondition(this.unlessProperty); | |||
| } | |||
| @@ -175,7 +175,7 @@ public class ListenerDefinition { | |||
| writer.writeEndElement(); | |||
| } | |||
| static ListenerDefinition fromForkedRepresentation(final XMLStreamReader reader) throws XMLStreamException { | |||
| public static ListenerDefinition fromForkedRepresentation(final XMLStreamReader reader) throws XMLStreamException { | |||
| reader.require(XMLStreamConstants.START_ELEMENT, null, LD_XML_ELM_LISTENER); | |||
| final ListenerDefinition listenerDef = new ListenerDefinition(); | |||
| final String className = requireAttributeValue(reader, LD_XML_ATTR_CLASS_NAME); | |||
| @@ -15,7 +15,7 @@ | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| /** | |||
| * A test that has a name associated with it | |||
| @@ -15,10 +15,7 @@ | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| import org.junit.platform.engine.discovery.DiscoverySelectors; | |||
| import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| import javax.xml.stream.XMLStreamConstants; | |||
| import javax.xml.stream.XMLStreamException; | |||
| @@ -29,13 +26,13 @@ import java.util.LinkedHashSet; | |||
| import java.util.Set; | |||
| import java.util.StringTokenizer; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_CLASS_NAME; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_EXCLUDE_ENGINES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_HALT_ON_FAILURE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_INCLUDE_ENGINES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_METHODS; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_OUTPUT_DIRECTORY; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ELM_TEST; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_CLASS_NAME; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_EXCLUDE_ENGINES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_HALT_ON_FAILURE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_INCLUDE_ENGINES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_METHODS; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_OUTPUT_DIRECTORY; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST; | |||
| /** | |||
| * Represents the single {@code test} (class) that's configured to be launched by the {@link JUnitLauncherTask} | |||
| @@ -86,27 +83,13 @@ public class SingleTestClass extends TestDefinition implements NamedTest { | |||
| return this.testMethods != null && !this.testMethods.isEmpty(); | |||
| } | |||
| String[] getMethods() { | |||
| public String[] getMethods() { | |||
| if (!hasMethodsSpecified()) { | |||
| return null; | |||
| } | |||
| return this.testMethods.toArray(new String[this.testMethods.size()]); | |||
| } | |||
| @Override | |||
| void addDiscoverySelectors(final TestRequest testRequest) { | |||
| final LauncherDiscoveryRequestBuilder requestBuilder = testRequest.getDiscoveryRequest(); | |||
| if (!this.hasMethodsSpecified()) { | |||
| requestBuilder.selectors(DiscoverySelectors.selectClass(this.testClass)); | |||
| } else { | |||
| // add specific methods | |||
| for (final String method : this.getMethods()) { | |||
| requestBuilder.selectors(DiscoverySelectors.selectMethod(this.testClass, method)); | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| protected void toForkedRepresentation(final JUnitLauncherTask task, final XMLStreamWriter writer) throws XMLStreamException { | |||
| writer.writeStartElement(LD_XML_ELM_TEST); | |||
| @@ -146,7 +129,7 @@ public class SingleTestClass extends TestDefinition implements NamedTest { | |||
| writer.writeEndElement(); | |||
| } | |||
| static TestDefinition fromForkedRepresentation(final XMLStreamReader reader) throws XMLStreamException { | |||
| public static TestDefinition fromForkedRepresentation(final XMLStreamReader reader) throws XMLStreamException { | |||
| reader.require(XMLStreamConstants.START_ELEMENT, null, LD_XML_ELM_TEST); | |||
| final SingleTestClass testDefinition = new SingleTestClass(); | |||
| final String testClassName = requireAttributeValue(reader, LD_XML_ATTR_CLASS_NAME); | |||
| @@ -15,14 +15,12 @@ | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| import org.apache.tools.ant.types.Resource; | |||
| import org.apache.tools.ant.types.ResourceCollection; | |||
| import org.apache.tools.ant.types.resources.Resources; | |||
| import org.apache.tools.ant.types.resources.StringResource; | |||
| import org.junit.platform.engine.discovery.DiscoverySelectors; | |||
| import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; | |||
| import javax.xml.stream.XMLStreamConstants; | |||
| import javax.xml.stream.XMLStreamException; | |||
| @@ -33,13 +31,13 @@ import java.util.ArrayList; | |||
| import java.util.Collections; | |||
| import java.util.List; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_CLASS_NAME; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_EXCLUDE_ENGINES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_HALT_ON_FAILURE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_INCLUDE_ENGINES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ATTR_OUTPUT_DIRECTORY; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ELM_TEST; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.Constants.LD_XML_ELM_TEST_CLASSES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_CLASS_NAME; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_EXCLUDE_ENGINES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_HALT_ON_FAILURE; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_INCLUDE_ENGINES; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_OUTPUT_DIRECTORY; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST; | |||
| import static org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ELM_TEST_CLASSES; | |||
| /** | |||
| * Represents a {@code testclasses} that's configured to be launched by the {@link JUnitLauncherTask} | |||
| @@ -56,19 +54,7 @@ public class TestClasses extends TestDefinition { | |||
| this.resources.add(resourceCollection); | |||
| } | |||
| @Override | |||
| void addDiscoverySelectors(final TestRequest testRequest) { | |||
| final List<String> tests = getTestClassNames(); | |||
| if (tests.isEmpty()) { | |||
| return; | |||
| } | |||
| final LauncherDiscoveryRequestBuilder requestBuilder = testRequest.getDiscoveryRequest(); | |||
| for (final String test : tests) { | |||
| requestBuilder.selectors(DiscoverySelectors.selectClass(test)); | |||
| } | |||
| } | |||
| private List<String> getTestClassNames() { | |||
| public List<String> getTestClassNames() { | |||
| if (this.resources.isEmpty()) { | |||
| return Collections.emptyList(); | |||
| } | |||
| @@ -122,7 +108,7 @@ public class TestClasses extends TestDefinition { | |||
| writer.writeEndElement(); | |||
| } | |||
| static List<TestDefinition> fromForkedRepresentation(final XMLStreamReader reader) throws XMLStreamException { | |||
| public static List<TestDefinition> fromForkedRepresentation(final XMLStreamReader reader) throws XMLStreamException { | |||
| reader.require(XMLStreamConstants.START_ELEMENT, null, LD_XML_ELM_TEST_CLASSES); | |||
| final TestClasses testDefinition = new TestClasses(); | |||
| // read out as multiple SingleTestClass representations | |||
| @@ -15,14 +15,11 @@ | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.PropertyHelper; | |||
| import org.junit.platform.engine.Filter; | |||
| import org.junit.platform.launcher.EngineFilter; | |||
| import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; | |||
| import javax.xml.stream.XMLStreamException; | |||
| import javax.xml.stream.XMLStreamWriter; | |||
| @@ -33,7 +30,7 @@ import java.util.List; | |||
| /** | |||
| * Represents the configuration details of a test that needs to be launched by the {@link JUnitLauncherTask} | |||
| */ | |||
| abstract class TestDefinition { | |||
| public abstract class TestDefinition { | |||
| protected String ifProperty; | |||
| protected String unlessProperty; | |||
| @@ -62,7 +59,7 @@ abstract class TestDefinition { | |||
| this.unlessProperty = unlessProperty; | |||
| } | |||
| boolean isHaltOnFailure() { | |||
| public boolean isHaltOnFailure() { | |||
| return this.haltOnFailure != null && this.haltOnFailure; | |||
| } | |||
| @@ -74,7 +71,7 @@ abstract class TestDefinition { | |||
| this.haltOnFailure = haltonfailure; | |||
| } | |||
| String getFailureProperty() { | |||
| public String getFailureProperty() { | |||
| return failureProperty; | |||
| } | |||
| @@ -86,7 +83,7 @@ abstract class TestDefinition { | |||
| this.listeners.add(listener); | |||
| } | |||
| List<ListenerDefinition> getListeners() { | |||
| public List<ListenerDefinition> getListeners() { | |||
| return Collections.unmodifiableList(this.listeners); | |||
| } | |||
| @@ -94,7 +91,7 @@ abstract class TestDefinition { | |||
| this.outputDir = dir; | |||
| } | |||
| String getOutputDir() { | |||
| public String getOutputDir() { | |||
| return this.outputDir; | |||
| } | |||
| @@ -110,54 +107,12 @@ abstract class TestDefinition { | |||
| return this.forkDefinition; | |||
| } | |||
| /** | |||
| * Create and return the {@link TestRequest TestRequests} for this test definition. This | |||
| * typically involves creating the JUnit test discovery request(s) and applying the necessary | |||
| * discovery selectors, filters and other necessary constructs. | |||
| * | |||
| * @return Returns the test requests | |||
| */ | |||
| List<TestRequest> createTestRequests() { | |||
| // create a TestRequest and add necessary selectors, filters to it | |||
| final LauncherDiscoveryRequestBuilder requestBuilder = LauncherDiscoveryRequestBuilder.request(); | |||
| final TestRequest request = new TestRequest(this, requestBuilder); | |||
| addDiscoverySelectors(request); | |||
| addFilters(request); | |||
| return Collections.singletonList(request); | |||
| } | |||
| /** | |||
| * Add necessary {@link org.junit.platform.engine.DiscoverySelector JUnit discovery selectors} to | |||
| * the {@code testRequest} | |||
| * | |||
| * @param testRequest The test request | |||
| */ | |||
| abstract void addDiscoverySelectors(final TestRequest testRequest); | |||
| /** | |||
| * Add necessary {@link Filter JUnit filters} to the {@code testRequest} | |||
| * | |||
| * @param testRequest The test request | |||
| */ | |||
| void addFilters(final TestRequest testRequest) { | |||
| final LauncherDiscoveryRequestBuilder requestBuilder = testRequest.getDiscoveryRequest(); | |||
| // add any engine filters | |||
| final String[] enginesToInclude = this.getIncludeEngines(); | |||
| if (enginesToInclude != null && enginesToInclude.length > 0) { | |||
| requestBuilder.filters(EngineFilter.includeEngines(enginesToInclude)); | |||
| } | |||
| final String[] enginesToExclude = this.getExcludeEngines(); | |||
| if (enginesToExclude != null && enginesToExclude.length > 0) { | |||
| requestBuilder.filters(EngineFilter.excludeEngines(enginesToExclude)); | |||
| } | |||
| } | |||
| protected boolean shouldRun(final Project project) { | |||
| final PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(project); | |||
| return propertyHelper.testIfCondition(this.ifProperty) && propertyHelper.testUnlessCondition(this.unlessProperty); | |||
| } | |||
| String[] getIncludeEngines() { | |||
| public String[] getIncludeEngines() { | |||
| return includeEngines == null ? new String[0] : split(this.includeEngines, ","); | |||
| } | |||
| @@ -165,7 +120,7 @@ abstract class TestDefinition { | |||
| this.includeEngines = includeEngines; | |||
| } | |||
| String[] getExcludeEngines() { | |||
| public String[] getExcludeEngines() { | |||
| return excludeEngines == null ? new String[0] : split(this.excludeEngines, ","); | |||
| } | |||
| @@ -0,0 +1,27 @@ | |||
| /* | |||
| * Licensed to the Apache Software Foundation (ASF) under one or more | |||
| * contributor license agreements. See the NOTICE file distributed with | |||
| * this work for additional information regarding copyright ownership. | |||
| * The ASF licenses this file to You 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. | |||
| * | |||
| */ | |||
| /** | |||
| * The classes/interfaces in this package <em>must not</em> | |||
| * have any compile time dependency on any of JUnit platform or | |||
| * engine classes/interfaces. They <em>must not</em> even have any | |||
| * compile time dependency on any classes/interfaces that belong to the | |||
| * {@link org.apache.tools.ant.taskdefs.optional.junitlauncher} package. | |||
| * | |||
| * @since Ant 1.10.6 | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined; | |||
| @@ -0,0 +1,28 @@ | |||
| /* | |||
| * Licensed to the Apache Software Foundation (ASF) under one or more | |||
| * contributor license agreements. See the NOTICE file distributed with | |||
| * this work for additional information regarding copyright ownership. | |||
| * The ASF licenses this file to You 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. | |||
| * | |||
| */ | |||
| /** | |||
| * The classes/interfaces in this package are allowed | |||
| * to have compile time dependency on JUnit platform classes/interfaces. | |||
| * Furthermore classes/interfaces in this package are also | |||
| * allowed to have compile time dependency on the | |||
| * {@link org.apache.tools.ant.taskdefs.optional.junitlauncher.confined} | |||
| * package | |||
| * | |||
| * @since Ant 1.10.6 | |||
| */ | |||
| package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| @@ -20,6 +20,7 @@ package org.apache.tools.ant.taskdefs.optional.junitlauncher; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.BuildFileRule; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.JUnitLauncherTask; | |||
| import org.apache.tools.ant.util.LoaderUtils; | |||
| import org.example.junitlauncher.jupiter.JupiterSampleTest; | |||
| import org.example.junitlauncher.vintage.AlwaysFailingJUnit4Test; | |||