Browse Source

[junitlauncher] Allow JUnit libraries to be part of the task's classpath instead of mandating it to be part of Ant's runtime classpath

master
Jaikiran Pai 6 years ago
parent
commit
0cb9d22b77
20 changed files with 500 additions and 288 deletions
  1. +1
    -1
      src/main/org/apache/tools/ant/taskdefs/defaults.properties
  2. +0
    -54
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/Constants.java
  3. +50
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/InVMExecution.java
  4. +94
    -10
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.java
  5. +14
    -18
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/StandaloneLauncher.java
  6. +1
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestExecutionContext.java
  7. +2
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestRequest.java
  8. +54
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/Constants.java
  9. +13
    -39
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ForkDefinition.java
  10. +76
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherClassPathUtil.java
  11. +96
    -36
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java
  12. +1
    -12
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/LaunchDefinition.java
  13. +13
    -13
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ListenerDefinition.java
  14. +1
    -1
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/NamedTest.java
  15. +10
    -27
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/SingleTestClass.java
  16. +10
    -24
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestClasses.java
  17. +8
    -53
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestDefinition.java
  18. +27
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/package-info.java
  19. +28
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/package-info.java
  20. +1
    -0
      src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java

+ 1
- 1
src/main/org/apache/tools/ant/taskdefs/defaults.properties View File

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


+ 0
- 54
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/Constants.java View File

@@ -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() {

}
}

+ 50
- 0
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/InVMExecution.java View File

@@ -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());
}
}

+ 94
- 10
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.java View File

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


+ 14
- 18
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/StandaloneLauncher.java View File

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

+ 1
- 0
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestExecutionContext.java View File

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


+ 2
- 0
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestRequest.java View File

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


+ 54
- 0
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/Constants.java View File

@@ -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() {

}
}

src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/ForkDefinition.java → src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ForkDefinition.java View File

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

}

+ 76
- 0
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherClassPathUtil.java View File

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

src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTask.java → src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java View File

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

src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LaunchDefinition.java → src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/LaunchDefinition.java View File

@@ -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();
}

src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/ListenerDefinition.java → src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ListenerDefinition.java View File

@@ -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 &lt;listener&gt;} element within the {@code &lt;junitlauncher&gt;}
@@ -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);

src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/NamedTest.java → src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/NamedTest.java View File

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

src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/SingleTestClass.java → src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/SingleTestClass.java View File

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

src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestClasses.java → src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestClasses.java View File

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

src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/TestDefinition.java → src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestDefinition.java View File

@@ -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, ",");
}


+ 27
- 0
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/package-info.java View File

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

+ 28
- 0
src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/package-info.java View File

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

+ 1
- 0
src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java View File

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


Loading…
Cancel
Save