in src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java [254:363]
private void forkTest(final TestDefinition test, final ForkDefinition forkDefinition,
final ForkedRepresentation forkedRepresentation,
final Optional<Long> deadlineNanos) {
// create launch command
final CommandlineJava commandlineJava = forkDefinition.generateCommandLine(this);
if (this.classPath != null) {
commandlineJava.createClasspath(getProject()).createPath().append(this.classPath);
}
final java.nio.file.Path projectPropsPath;
try {
projectPropsPath = dumpProjectProperties();
} catch (IOException e) {
throw new BuildException("Could not create the necessary properties file while forking a process" +
" for a test", e);
}
// --properties <path-to-properties-file>
commandlineJava.createArgument().setValue(Constants.ARG_PROPERTIES);
commandlineJava.createArgument().setValue(projectPropsPath.toAbsolutePath().toString());
final java.nio.file.Path launchDefXmlPath = newLaunchDefinitionXml();
try (final OutputStream os = Files.newOutputStream(launchDefXmlPath)) {
final XMLStreamWriter writer = XMLOutputFactory.newFactory().createXMLStreamWriter(os, "UTF-8");
try {
writer.writeStartDocument();
writer.writeStartElement(LD_XML_ELM_LAUNCH_DEF);
if (this.printSummary) {
writer.writeAttribute(LD_XML_ATTR_PRINT_SUMMARY, "true");
}
if (this.haltOnFailure) {
writer.writeAttribute(LD_XML_ATTR_HALT_ON_FAILURE, "true");
}
if (this.includeTags.size() > 0) {
writer.writeAttribute(LD_XML_ATTR_INCLUDE_TAGS, commaSeparatedListElements(includeTags));
}
if (this.excludeTags.size() > 0) {
writer.writeAttribute(LD_XML_ATTR_EXCLUDE_TAGS, commaSeparatedListElements(excludeTags));
}
// task level listeners
for (final ListenerDefinition listenerDef : this.listeners) {
if (!listenerDef.shouldUse(getProject())) {
continue;
}
// construct the listener definition argument
listenerDef.toForkedRepresentation(writer);
}
// test definition as XML
forkedRepresentation.write(this, writer);
writer.writeEndElement();
writer.writeEndDocument();
} finally {
writer.close();
}
} catch (Exception e) {
throw new BuildException("Failed to construct command line for test", e);
}
// --launch-definition <xml-file-path>
commandlineJava.createArgument().setValue(Constants.ARG_LAUNCH_DEFINITION);
commandlineJava.createArgument().setValue(launchDefXmlPath.toAbsolutePath().toString());
// launch the process and wait for process to complete
final int exitCode = executeForkedTest(forkDefinition, commandlineJava, deadlineNanos);
switch (exitCode) {
case Constants.FORK_EXIT_CODE_SUCCESS: {
// success
break;
}
case Constants.FORK_EXIT_CODE_EXCEPTION: {
// process failed with some exception
throw new BuildException("Forked test(s) failed with an exception");
}
case Constants.FORK_EXIT_CODE_TESTS_FAILED: {
// test has failure(s)
try {
if (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
this.getProject().setNewProperty(test.getFailureProperty(), "true");
}
} finally {
if (test.isHaltOnFailure()) {
// if the test is configured to halt on test failures, throw a build error
final String errorMessage;
if (test instanceof NamedTest) {
errorMessage = "Test " + ((NamedTest) test).getName() + " has failure(s)";
} else {
errorMessage = "Some test(s) have failure(s)";
}
throw new BuildException(errorMessage);
}
}
break;
}
case Constants.FORK_EXIT_CODE_TIMED_OUT: {
// test has failure(s)
try {
if (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
this.getProject().setNewProperty(test.getFailureProperty(), "true");
}
} finally {
if (test.isHaltOnFailure()) {
throw new BuildException(new TimeoutException("Forked test(s) timed out"));
} else {
log("Timeout occurred. Please note the time in the report does not reflect the time until the timeout.");
}
}
}
}
}