@@ -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; | |||