This is an automated email from the ASF dual-hosted git repository.
jaikiran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ant.git
The following commit(s) were added to refs/heads/master by this push:
new 89b0895ad junitlauncher - timeout should apply to all tests combined
when using forkMode=perTestClass
89b0895ad is described below
commit 89b0895adc5dec7990c18731743d7a9d9f8ee283
Author: Jaikiran Pai <[email protected]>
AuthorDate: Wed Aug 16 13:25:48 2023 +0530
junitlauncher - timeout should apply to all tests combined when using
forkMode=perTestClass
---
manual/Tasks/junitlauncher.html | 6 +++-
.../junitlauncher/confined/JUnitLauncherTask.java | 40 +++++++++++++++++-----
2 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/manual/Tasks/junitlauncher.html b/manual/Tasks/junitlauncher.html
index 2e33a17c4..ed4f4358b 100644
--- a/manual/Tasks/junitlauncher.html
+++ b/manual/Tasks/junitlauncher.html
@@ -645,7 +645,11 @@ the new JVM instance that will be created to launch the
tests.
<td>Controls how many JVMs are launched for the forked tests. Allowed
values are:
<ul class="inlinelist">
<li><code>perTestClass</code> - This mode launches each test
class in a
- separately forked JVM</li>
+ separately forked JVM. Each of these JVMs will be forked
sequentially
+ one at a time, as and when each test class execution
completes.
+ If any <code>timeout</code> value is specified, then that
timeout applies to
+ the time that all tests use together, not to an individual
test.
+ </li>
</ul>
<p><em>Since Ant 1.10.14</em></p>
</td>
diff --git
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java
index 6dca664a4..15f685666 100644
---
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java
+++
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/JUnitLauncherTask.java
@@ -42,11 +42,14 @@ 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.StringTokenizer;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static
org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.Constants.LD_XML_ATTR_EXCLUDE_TAGS;
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_TAGS;
@@ -82,8 +85,8 @@ public class JUnitLauncherTask extends Task {
private boolean printSummary;
private final List<TestDefinition> tests = new ArrayList<>();
private final List<ListenerDefinition> listeners = new ArrayList<>();
- private List<String> includeTags = new ArrayList<>();
- private List<String> excludeTags = new ArrayList<>();
+ private final List<String> includeTags = new ArrayList<>();
+ private final List<String> excludeTags = new ArrayList<>();
public JUnitLauncherTask() {
}
@@ -105,8 +108,13 @@ public class JUnitLauncherTask extends Task {
launchViaReflection(new
InVMLaunch(Collections.singletonList(test)));
} else {
final List<ForkedRepresentation> forkedReps =
test.toForkedRepresentations();
+ final long timeout = forkDefinition.getTimeout(); // in millis
+ // compute the "end time" (if any)
+ final Optional<Long> deadlineNanos = timeout == -1
+ ? Optional.empty() // no timeout
+ : Optional.of(System.nanoTime() +
MILLISECONDS.toNanos(timeout));
for (final ForkedRepresentation forkedRep : forkedReps) {
- forkTest(test, forkDefinition, forkedRep);
+ forkTest(test, forkDefinition, forkedRep, deadlineNanos);
}
}
}
@@ -244,7 +252,8 @@ public class JUnitLauncherTask extends Task {
}
private void forkTest(final TestDefinition test, final ForkDefinition
forkDefinition,
- final ForkedRepresentation forkedRepresentation) {
+ final ForkedRepresentation forkedRepresentation,
+ final Optional<Long> deadlineNanos) {
// create launch command
final CommandlineJava commandlineJava =
forkDefinition.generateCommandLine(this);
if (this.classPath != null) {
@@ -302,7 +311,7 @@ public class JUnitLauncherTask extends Task {
commandlineJava.createArgument().setValue(launchDefXmlPath.toAbsolutePath().toString());
// launch the process and wait for process to complete
- final int exitCode = executeForkedTest(forkDefinition,
commandlineJava);
+ final int exitCode = executeForkedTest(forkDefinition,
commandlineJava, deadlineNanos);
switch (exitCode) {
case Constants.FORK_EXIT_CODE_SUCCESS: {
// success
@@ -359,11 +368,26 @@ public class JUnitLauncherTask extends Task {
.collect(Collectors.joining(", "));
}
- private int executeForkedTest(final ForkDefinition forkDefinition, final
CommandlineJava commandlineJava) {
+ private int executeForkedTest(final ForkDefinition forkDefinition, final
CommandlineJava commandlineJava,
+ final Optional<Long> deadlineNanos) {
final LogOutputStream outStream = new LogOutputStream(this,
Project.MSG_INFO);
final LogOutputStream errStream = new LogOutputStream(this,
Project.MSG_WARN);
- final ExecuteWatchdog watchdog = forkDefinition.getTimeout() > 0
- ? createExecuteWatchdog(forkDefinition.getTimeout()) : null;
+ final ExecuteWatchdog watchdog;
+ if (deadlineNanos.isPresent()) {
+ final long remainingNanos = deadlineNanos.get() -
System.nanoTime();
+ if (remainingNanos <= 0) {
+ // already timed out
+ return Constants.FORK_EXIT_CODE_TIMED_OUT;
+ }
+ final long timeoutInMillis = NANOSECONDS.toMillis(remainingNanos);
+ if (timeoutInMillis == 0) {
+ // already timed out
+ return Constants.FORK_EXIT_CODE_TIMED_OUT;
+ }
+ watchdog = createExecuteWatchdog(timeoutInMillis);
+ } else {
+ watchdog = null; // no timeout specified
+ }
final Execute execute = new Execute(new PumpStreamHandler(outStream,
errStream), watchdog);
execute.setCommandline(commandlineJava.getCommandline());
execute.setAntRun(getProject());