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 f7f3bdfa0 bz-65176 introduce forkMode for use in forked tests of 
junitlauncher task
f7f3bdfa0 is described below

commit f7f3bdfa033b2c77e001c2fc485bf200a682227d
Author: Jaikiran Pai <[email protected]>
AuthorDate: Sat Aug 12 20:04:47 2023 +0530

    bz-65176 introduce forkMode for use in forked tests of junitlauncher task
---
 WHATSNEW                                           |   5 +
 manual/Tasks/junitlauncher.html                    |  11 ++
 .../testcases/taskdefs/optional/junitlauncher.xml  |  53 +++++++
 .../junitlauncher/confined/ForkDefinition.java     |  33 ++++
 .../junitlauncher/confined/JUnitLauncherTask.java  |  17 +-
 .../junitlauncher/confined/SingleTestClass.java    |  74 +++++----
 .../junitlauncher/confined/TestClasses.java        |  84 +++++++---
 .../junitlauncher/confined/TestDefinition.java     |   6 +-
 .../junitlauncher/JUnitLauncherTaskTest.java       | 172 ++++++++++++++-------
 .../org/example/junitlauncher/FooBarData.java      |  31 ++++
 .../jupiter/SharedDataAccessorTest1.java           |  41 +++++
 .../jupiter/SharedDataAccessorTest2.java           |  41 +++++
 12 files changed, 448 insertions(+), 120 deletions(-)

diff --git a/WHATSNEW b/WHATSNEW
index f5737de10..8e202fb3a 100644
--- a/WHATSNEW
+++ b/WHATSNEW
@@ -65,6 +65,11 @@ Other changes:
    setLogLevel(LogLevel level) method.
    Bugzilla Report 66238
 
+ * The <fork> element of junitlaunchertask now allows a "forkMode"
+   attribute. forkMode=perTestClass can now be used to launch
+   each test class in a separate forked JVM.
+   Bugzilla Report 65176
+
 Changes from Ant 1.10.12 TO Ant 1.10.13
 =======================================
 
diff --git a/manual/Tasks/junitlauncher.html b/manual/Tasks/junitlauncher.html
index 29ec62828..2e33a17c4 100644
--- a/manual/Tasks/junitlauncher.html
+++ b/manual/Tasks/junitlauncher.html
@@ -640,6 +640,17 @@ the new JVM instance that will be created to launch the 
tests.
         </td>
         <td>No</td>
     </tr>
+    <tr>
+        <td>forkMode</td>
+        <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>
+            </ul>
+            <p><em>Since Ant 1.10.14</em></p>
+        </td>
+        <td>No; defaults to launching all test classes in one single forked 
JVM.</td>
+    </tr>
 </table>
 
 The <code>fork</code> element allows the following nested elements:
diff --git a/src/etc/testcases/taskdefs/optional/junitlauncher.xml 
b/src/etc/testcases/taskdefs/optional/junitlauncher.xml
index c6aed61c8..0a736d714 100644
--- a/src/etc/testcases/taskdefs/optional/junitlauncher.xml
+++ b/src/etc/testcases/taskdefs/optional/junitlauncher.xml
@@ -142,6 +142,7 @@
                 <fileset dir="${build.classes.dir}">
                     <include name="org/example/**/junitlauncher/**/"/>
                     <exclude 
name="org/example/**/junitlauncher/**/ForkedTest.class"/>
+                    <exclude 
name="org/example/**/junitlauncher/**/SharedDataAccessorTest*.class"/>
                 </fileset>
                 <listener type="legacy-brief" sendSysOut="true"/>
                 <listener type="legacy-xml" sendSysErr="true" 
sendSysOut="true"/>
@@ -431,5 +432,57 @@
         </junitreport>
     </target>
 
+    <target name="test-fork-one-jvm-all-tests" depends="init">
+        <property name="junitlauncher.test.tracker.append.file"
+                  
value="${output.dir}/${test-fork-one-jvm-all-tests.tracker}"/>
+        <junitlauncher>
+            <classpath refid="test.classpath"/>
+            <testclasses outputdir="${output.dir}">
+                <fileset dir="${build.classes.dir}">
+                    <!-- order is important here since the second test is 
asserted,
+                        in 
JUnitLauncherTaskTest.testTestClassesDefaultForkMode(), to fail -->
+                    <include 
name="org/example/**/junitlauncher/**/SharedDataAccessorTest1.class"/>
+                    <include 
name="org/example/**/junitlauncher/**/SharedDataAccessorTest2.class"/>
+                </fileset>
+                <fork/>
+                <listener classname="org.example.junitlauncher.Tracker"
+                          if="test-fork-one-jvm-all-tests.tracker"/>
+                <listener type="legacy-xml" sendSysErr="true" 
sendSysOut="true"/>
+            </testclasses>
+        </junitlauncher>
+    </target>
+
+    <target name="test-fork-per-test-class" depends="init">
+        <property name="junitlauncher.test.tracker.append.file"
+                  value="${output.dir}/${test-fork-per-test-class.tracker}"/>
+        <junitlauncher>
+            <classpath refid="test.classpath"/>
+            <testclasses outputdir="${output.dir}">
+                <fileset dir="${build.classes.dir}">
+                    <include 
name="org/example/**/junitlauncher/**/SharedDataAccessorTest1.class"/>
+                    <include 
name="org/example/**/junitlauncher/**/SharedDataAccessorTest2.class"/>
+                </fileset>
+                <fork forkMode="perTestClass"/>
+                <listener classname="org.example.junitlauncher.Tracker"
+                          if="test-fork-per-test-class.tracker"/>
+                <listener type="legacy-xml" sendSysErr="true" 
sendSysOut="true"/>
+            </testclasses>
+        </junitlauncher>
+    </target>
+
+    <target name="test-single-test-explicit-fork-mode" depends="init">
+        <property name="junitlauncher.test.tracker.append.file"
+                  
value="${output.dir}/${test-single-test-explicit-fork-mode.tracker}"/>
+        <junitlauncher>
+            <classpath refid="test.classpath"/>
+            <test 
name="org.example.junitlauncher.jupiter.SharedDataAccessorTest2"
+                  outputdir="${output.dir}">
+                <fork forkMode="perTestClass"/>
+                <listener classname="org.example.junitlauncher.Tracker"
+                          if="test-single-test-explicit-fork-mode.tracker"/>
+                <listener type="legacy-xml" sendSysErr="true" 
sendSysOut="true"/>
+            </test>
+        </junitlauncher>
+    </target>
 </project>
 
diff --git 
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ForkDefinition.java
 
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ForkDefinition.java
index c8a40c6f8..50e3bcfe9 100644
--- 
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ForkDefinition.java
+++ 
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/ForkDefinition.java
@@ -22,6 +22,7 @@ import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
 import org.apache.tools.ant.types.Commandline;
 import org.apache.tools.ant.types.CommandlineJava;
+import org.apache.tools.ant.types.EnumeratedAttribute;
 import org.apache.tools.ant.types.Environment;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.PropertySet;
@@ -36,6 +37,7 @@ public class ForkDefinition {
 
     private boolean includeAntRuntimeLibraries = true;
     private boolean includeJUnitPlatformLibraries = true;
+    private ForkMode forkMode;
 
     private final CommandlineJava commandLineJava;
     private final Environment env = new Environment();
@@ -112,6 +114,20 @@ public class ForkDefinition {
         this.commandLineJava.setVm(java);
     }
 
+    /**
+     * The {@code forkMode} to use when launching the tests in a forked JVM.
+     *
+     * @param forkMode Can be null, in which case an internal implementation 
default will be used.
+     * @since Ant 1.10.14
+     */
+    public void setForkMode(final ForkMode forkMode) {
+        this.forkMode = forkMode;
+    }
+
+    ForkMode getForkMode() {
+        return this.forkMode;
+    }
+
     /**
      * Generates a new {@link CommandlineJava} constructed out of the 
configurations set on this
      * {@link ForkDefinition}
@@ -151,4 +167,21 @@ public class ForkDefinition {
         return cmdLine;
     }
 
+    public static final class ForkMode extends EnumeratedAttribute {
+
+        static final String FORK_EVERY_TEST_CLASS = "perTestClass";
+
+        public ForkMode() {
+            // public no-arg constructor required by Ant introspection
+        }
+
+        private ForkMode(final String val) {
+            this.setValue(val);
+        }
+
+        @Override
+        public String[] getValues() {
+            return new String[] {FORK_EVERY_TEST_CLASS};
+        }
+    }
 }
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 c7440cf96..6dca664a4 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
@@ -25,6 +25,7 @@ import org.apache.tools.ant.taskdefs.Execute;
 import org.apache.tools.ant.taskdefs.ExecuteWatchdog;
 import org.apache.tools.ant.taskdefs.LogOutputStream;
 import org.apache.tools.ant.taskdefs.PumpStreamHandler;
+import 
org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.TestDefinition.ForkedRepresentation;
 import org.apache.tools.ant.types.CommandlineJava;
 import org.apache.tools.ant.types.Environment;
 import org.apache.tools.ant.types.Path;
@@ -99,10 +100,14 @@ public class JUnitLauncherTask extends Task {
                         "in context of project " + project, Project.MSG_DEBUG);
                 continue;
             }
-            if (test.getForkDefinition() != null) {
-                forkTest(test);
-            } else {
+            final ForkDefinition forkDefinition = test.getForkDefinition();
+            if (forkDefinition == null) {
                 launchViaReflection(new 
InVMLaunch(Collections.singletonList(test)));
+            } else {
+                final List<ForkedRepresentation> forkedReps = 
test.toForkedRepresentations();
+                for (final ForkedRepresentation forkedRep : forkedReps) {
+                    forkTest(test, forkDefinition, forkedRep);
+                }
             }
         }
     }
@@ -238,9 +243,9 @@ public class JUnitLauncherTask extends Task {
         return propsPath;
     }
 
-    private void forkTest(final TestDefinition test) {
+    private void forkTest(final TestDefinition test, final ForkDefinition 
forkDefinition,
+                          final ForkedRepresentation forkedRepresentation) {
         // create launch command
-        final ForkDefinition forkDefinition = test.getForkDefinition();
         final CommandlineJava commandlineJava = 
forkDefinition.generateCommandLine(this);
         if (this.classPath != null) {
             
commandlineJava.createClasspath(getProject()).createPath().append(this.classPath);
@@ -283,7 +288,7 @@ public class JUnitLauncherTask extends Task {
                     listenerDef.toForkedRepresentation(writer);
                 }
                 // test definition as XML
-                test.toForkedRepresentation(this, writer);
+                forkedRepresentation.write(this, writer);
                 writer.writeEndElement();
                 writer.writeEndDocument();
             } finally {
diff --git 
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/SingleTestClass.java
 
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/SingleTestClass.java
index 603869eab..fcf09ea7b 100644
--- 
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/SingleTestClass.java
+++ 
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/SingleTestClass.java
@@ -25,6 +25,7 @@ import javax.xml.stream.XMLStreamWriter;
 import java.io.File;
 import java.util.Collections;
 import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.StringTokenizer;
 
@@ -93,42 +94,53 @@ public class SingleTestClass extends TestDefinition 
implements NamedTest {
     }
 
     @Override
-    protected void toForkedRepresentation(final JUnitLauncherTask task, final 
XMLStreamWriter writer) throws XMLStreamException {
-        writer.writeStartElement(LD_XML_ELM_TEST);
-        writer.writeAttribute(LD_XML_ATTR_CLASS_NAME, testClass);
-        if (testMethods != null) {
-            final StringBuilder sb = new StringBuilder();
-            for (final String method : testMethods) {
-                if (sb.length() != 0) {
-                    sb.append(",");
+    protected List<ForkedRepresentation> toForkedRepresentations() throws 
IllegalStateException {
+        if (this.forkDefinition == null) {
+            throw new IllegalStateException("tests haven't been configured to 
run in forked JVM");
+        }
+        return Collections.singletonList(new SingleTestFork());
+    }
+
+    private final class SingleTestFork extends ForkedRepresentation {
+        @Override
+        public void write(final JUnitLauncherTask task, final XMLStreamWriter 
writer)
+                throws XMLStreamException {
+            writer.writeStartElement(LD_XML_ELM_TEST);
+            writer.writeAttribute(LD_XML_ATTR_CLASS_NAME, testClass);
+            if (testMethods != null) {
+                final StringBuilder sb = new StringBuilder();
+                for (final String method : testMethods) {
+                    if (sb.length() != 0) {
+                        sb.append(",");
+                    }
+                    sb.append(method);
                 }
-                sb.append(method);
+                writer.writeAttribute(LD_XML_ATTR_METHODS, sb.toString());
             }
-            writer.writeAttribute(LD_XML_ATTR_METHODS, sb.toString());
-        }
-        if (haltOnFailure != null) {
-            writer.writeAttribute(LD_XML_ATTR_HALT_ON_FAILURE, 
haltOnFailure.toString());
-        }
-        if (outputDir != null) {
-            writer.writeAttribute(LD_XML_ATTR_OUTPUT_DIRECTORY, 
outputDir.getPath());
-        }
-        if (includeEngines != null) {
-            writer.writeAttribute(LD_XML_ATTR_INCLUDE_ENGINES, includeEngines);
-        }
-        if (excludeEngines != null) {
-            writer.writeAttribute(LD_XML_ATTR_EXCLUDE_ENGINES, excludeEngines);
-        }
-        // listeners for this test
-        if (listeners != null) {
-            for (final ListenerDefinition listenerDef : getListeners()) {
-                if (!listenerDef.shouldUse(task.getProject())) {
-                    // not applicable
-                    continue;
+            if (haltOnFailure != null) {
+                writer.writeAttribute(LD_XML_ATTR_HALT_ON_FAILURE, 
haltOnFailure.toString());
+            }
+            if (outputDir != null) {
+                writer.writeAttribute(LD_XML_ATTR_OUTPUT_DIRECTORY, 
outputDir.getPath());
+            }
+            if (includeEngines != null) {
+                writer.writeAttribute(LD_XML_ATTR_INCLUDE_ENGINES, 
includeEngines);
+            }
+            if (excludeEngines != null) {
+                writer.writeAttribute(LD_XML_ATTR_EXCLUDE_ENGINES, 
excludeEngines);
+            }
+            // listeners for this test
+            if (listeners != null) {
+                for (final ListenerDefinition listenerDef : getListeners()) {
+                    if (!listenerDef.shouldUse(task.getProject())) {
+                        // not applicable
+                        continue;
+                    }
+                    listenerDef.toForkedRepresentation(writer);
                 }
-                listenerDef.toForkedRepresentation(writer);
             }
+            writer.writeEndElement();
         }
-        writer.writeEndElement();
     }
 
     public static TestDefinition fromForkedRepresentation(final 
XMLStreamReader reader) throws XMLStreamException {
diff --git 
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestClasses.java
 
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestClasses.java
index 86aa525d9..cc275b4d0 100644
--- 
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestClasses.java
+++ 
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestClasses.java
@@ -17,6 +17,8 @@
  */
 package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined;
 
+import org.apache.tools.ant.BuildException;
+import 
org.apache.tools.ant.taskdefs.optional.junitlauncher.confined.ForkDefinition.ForkMode;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
 import org.apache.tools.ant.types.resources.Resources;
@@ -74,37 +76,71 @@ public class TestClasses extends TestDefinition {
     }
 
     @Override
-    protected void toForkedRepresentation(final JUnitLauncherTask task, final 
XMLStreamWriter writer) throws XMLStreamException {
-        writer.writeStartElement(LD_XML_ELM_TEST_CLASSES);
-        // write out each test class
-        for (final String test : getTestClassNames()) {
-            writer.writeStartElement(LD_XML_ELM_TEST);
-            writer.writeAttribute(LD_XML_ATTR_CLASS_NAME, test);
-            if (haltOnFailure != null) {
-                writer.writeAttribute(LD_XML_ATTR_HALT_ON_FAILURE, 
haltOnFailure.toString());
-            }
-            if (outputDir != null) {
-                writer.writeAttribute(LD_XML_ATTR_OUTPUT_DIRECTORY, 
outputDir.getPath());
-            }
-            if (includeEngines != null) {
-                writer.writeAttribute(LD_XML_ATTR_INCLUDE_ENGINES, 
includeEngines);
+    protected List<ForkedRepresentation> toForkedRepresentations() throws 
IllegalStateException {
+        if (this.forkDefinition == null) {
+            throw new IllegalStateException("tests haven't been configured to 
run in forked JVM");
+        }
+        final ForkMode forkMode = this.forkDefinition.getForkMode();
+        if (forkMode == null) {
+            // launch all test classes in a single forked JVM
+            return Collections.singletonList(new 
ForkModeRep(this.getTestClassNames()));
+        }
+        switch (forkMode.getValue()) {
+            case ForkMode.FORK_EVERY_TEST_CLASS: {
+                // launch each test class in a separate forked JVM
+                final List<ForkedRepresentation> forkModeReps = new 
ArrayList<>();
+                for (final String testClass : getTestClassNames()) {
+                    forkModeReps.add(new 
ForkModeRep(Collections.singletonList(testClass)));
+                }
+                return Collections.unmodifiableList(forkModeReps);
             }
-            if (excludeEngines != null) {
-                writer.writeAttribute(LD_XML_ATTR_EXCLUDE_ENGINES, 
excludeEngines);
+            default: {
+                throw new BuildException("Unsupported fork mode: " + 
forkMode.getValue());
             }
-            // listeners for this test
-            if (listeners != null) {
-                for (final ListenerDefinition listenerDef : getListeners()) {
-                    if (!listenerDef.shouldUse(task.getProject())) {
-                        // not applicable
-                        continue;
+        }
+    }
+
+    private final class ForkModeRep extends ForkedRepresentation {
+        private final List<String> testClassesToFork;
+
+        private ForkModeRep(final List<String> testClassesToFork) {
+            this.testClassesToFork = testClassesToFork;
+        }
+
+        @Override
+        public void write(final JUnitLauncherTask task, final XMLStreamWriter 
writer)
+                throws XMLStreamException {
+            writer.writeStartElement(LD_XML_ELM_TEST_CLASSES);
+            // write out each test class
+            for (final String test : this.testClassesToFork) {
+                writer.writeStartElement(LD_XML_ELM_TEST);
+                writer.writeAttribute(LD_XML_ATTR_CLASS_NAME, test);
+                if (haltOnFailure != null) {
+                    writer.writeAttribute(LD_XML_ATTR_HALT_ON_FAILURE, 
haltOnFailure.toString());
+                }
+                if (outputDir != null) {
+                    writer.writeAttribute(LD_XML_ATTR_OUTPUT_DIRECTORY, 
outputDir.getPath());
+                }
+                if (includeEngines != null) {
+                    writer.writeAttribute(LD_XML_ATTR_INCLUDE_ENGINES, 
includeEngines);
+                }
+                if (excludeEngines != null) {
+                    writer.writeAttribute(LD_XML_ATTR_EXCLUDE_ENGINES, 
excludeEngines);
+                }
+                // listeners for this test
+                if (listeners != null) {
+                    for (final ListenerDefinition listenerDef : 
getListeners()) {
+                        if (!listenerDef.shouldUse(task.getProject())) {
+                            // not applicable
+                            continue;
+                        }
+                        listenerDef.toForkedRepresentation(writer);
                     }
-                    listenerDef.toForkedRepresentation(writer);
                 }
+                writer.writeEndElement();
             }
             writer.writeEndElement();
         }
-        writer.writeEndElement();
     }
 
     public static List<TestDefinition> fromForkedRepresentation(final 
XMLStreamReader reader) throws XMLStreamException {
diff --git 
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestDefinition.java
 
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestDefinition.java
index 34b8eb8f8..e53f2f9d6 100644
--- 
a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestDefinition.java
+++ 
b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/confined/TestDefinition.java
@@ -145,6 +145,10 @@ public abstract class TestDefinition {
         return parts.toArray(new String[0]);
     }
 
-    protected abstract void toForkedRepresentation(JUnitLauncherTask task, 
XMLStreamWriter writer) throws XMLStreamException;
+    protected abstract List<ForkedRepresentation> toForkedRepresentations() 
throws IllegalStateException;
 
+    public static abstract class ForkedRepresentation {
+        public abstract void write(JUnitLauncherTask task, XMLStreamWriter 
writer)
+                throws XMLStreamException;
+    }
 }
diff --git 
a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
 
b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
index ab19d6435..051c23eef 100644
--- 
a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
+++ 
b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junitlauncher/JUnitLauncherTaskTest.java
@@ -22,10 +22,13 @@ import static 
org.example.junitlauncher.Tracker.verifySetupFailed;
 import static org.example.junitlauncher.Tracker.verifySkipped;
 import static org.example.junitlauncher.Tracker.verifySuccess;
 import static org.example.junitlauncher.Tracker.wasTestRun;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
 import java.io.File;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -40,6 +43,8 @@ import org.apache.tools.ant.util.LoaderUtils;
 import org.example.junitlauncher.jupiter.JupiterSampleTest;
 import org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll;
 import org.example.junitlauncher.jupiter.JupiterTagSampleTest;
+import org.example.junitlauncher.jupiter.SharedDataAccessorTest1;
+import org.example.junitlauncher.jupiter.SharedDataAccessorTest2;
 import org.example.junitlauncher.vintage.AlwaysFailingJUnit4Test;
 import org.example.junitlauncher.vintage.ForkedTest;
 import org.example.junitlauncher.vintage.JUnit4SampleTest;
@@ -95,9 +100,9 @@ public class JUnitLauncherTaskTest {
         final Path trackerFile = setupTrackerProperty(targetName);
         buildRule.executeTarget(targetName);
         // make sure the test that was expected to be run (and fail), did 
indeed fail
-        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected 
to run", wasTestRun(trackerFile,
+        assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to run", 
wasTestRun(trackerFile,
                 AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
-        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected 
to fail", verifyFailed(trackerFile,
+        assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to 
fail", verifyFailed(trackerFile,
                 AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
     }
 
@@ -110,8 +115,8 @@ public class JUnitLauncherTaskTest {
         final Path trackerFile = setupTrackerProperty(targetName);
         buildRule.executeTarget(targetName);
         // make sure the right test(s) were run
-        Assert.assertTrue("JUnit4SampleTest test was expected to be run", 
wasTestRun(trackerFile, JUnit4SampleTest.class.getName()));
-        Assert.assertTrue("JUnit4SampleTest#testFoo was expected to succeed", 
verifySuccess(trackerFile,
+        assertTrue("JUnit4SampleTest test was expected to be run", 
wasTestRun(trackerFile, JUnit4SampleTest.class.getName()));
+        assertTrue("JUnit4SampleTest#testFoo was expected to succeed", 
verifySuccess(trackerFile,
                 JUnit4SampleTest.class.getName(), "testFoo"));
     }
 
@@ -124,20 +129,20 @@ public class JUnitLauncherTaskTest {
         final Path tracker1 = setupTrackerProperty(targetSpecificMethod);
         buildRule.executeTarget(targetSpecificMethod);
         // verify only that specific method was run
-        Assert.assertTrue("testBar was expected to be run", 
wasTestRun(tracker1, JUnit4SampleTest.class.getName(),
+        assertTrue("testBar was expected to be run", wasTestRun(tracker1, 
JUnit4SampleTest.class.getName(),
                 "testBar"));
-        Assert.assertFalse("testFoo wasn't expected to be run", 
wasTestRun(tracker1, JUnit4SampleTest.class.getName(),
+        assertFalse("testFoo wasn't expected to be run", wasTestRun(tracker1, 
JUnit4SampleTest.class.getName(),
                 "testFoo"));
 
 
         final String targetMultipleMethods = "test-multiple-specific-methods";
         final Path tracker2 = setupTrackerProperty(targetMultipleMethods);
         buildRule.executeTarget(targetMultipleMethods);
-        Assert.assertTrue("testFooBar was expected to be run", 
wasTestRun(tracker2, JUnit4SampleTest.class.getName(),
+        assertTrue("testFooBar was expected to be run", wasTestRun(tracker2, 
JUnit4SampleTest.class.getName(),
                 "testFooBar"));
-        Assert.assertTrue("testFoo was expected to be run", 
wasTestRun(tracker2, JUnit4SampleTest.class.getName(),
+        assertTrue("testFoo was expected to be run", wasTestRun(tracker2, 
JUnit4SampleTest.class.getName(),
                 "testFoo"));
-        Assert.assertFalse("testBar wasn't expected to be run", 
wasTestRun(tracker2, JUnit4SampleTest.class.getName(),
+        assertFalse("testBar wasn't expected to be run", wasTestRun(tracker2, 
JUnit4SampleTest.class.getName(),
                 "testBar"));
     }
 
@@ -151,9 +156,9 @@ public class JUnitLauncherTaskTest {
         final Path trackerFile2 = setupTrackerProperty(targetName + "-2");
         buildRule.executeTarget(targetName);
 
-        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected 
to be run", wasTestRun(trackerFile1,
+        assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to be 
run", wasTestRun(trackerFile1,
                 AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
-        Assert.assertTrue("JUnit4SampleTest#testFoo was expected to be run", 
wasTestRun(trackerFile2,
+        assertTrue("JUnit4SampleTest#testFoo was expected to be run", 
wasTestRun(trackerFile2,
                 JUnit4SampleTest.class.getName(), "testFoo"));
     }
 
@@ -167,17 +172,17 @@ public class JUnitLauncherTaskTest {
         final Path trackerFile = setupTrackerProperty(targetName);
         buildRule.executeTarget(targetName);
 
-        Assert.assertTrue("JUnit4SampleTest#testFoo was expected to succeed", 
verifySuccess(trackerFile,
+        assertTrue("JUnit4SampleTest#testFoo was expected to succeed", 
verifySuccess(trackerFile,
                 JUnit4SampleTest.class.getName(), "testFoo"));
-        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected 
to fail", verifyFailed(trackerFile,
+        assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to 
fail", verifyFailed(trackerFile,
                 AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
-        Assert.assertTrue("JupiterSampleTest#testSucceeds was expected to 
succeed", verifySuccess(trackerFile,
+        assertTrue("JupiterSampleTest#testSucceeds was expected to succeed", 
verifySuccess(trackerFile,
                 JupiterSampleTest.class.getName(), "testSucceeds"));
-        Assert.assertTrue("JupiterSampleTest#testFails was expected to 
succeed", verifyFailed(trackerFile,
+        assertTrue("JupiterSampleTest#testFails was expected to succeed", 
verifyFailed(trackerFile,
                 JupiterSampleTest.class.getName(), "testFails"));
-        Assert.assertTrue("JupiterSampleTest#testSkipped was expected to be 
skipped", verifySkipped(trackerFile,
+        assertTrue("JupiterSampleTest#testSkipped was expected to be skipped", 
verifySkipped(trackerFile,
                 JupiterSampleTest.class.getName(), "testSkipped"));
-        Assert.assertFalse("ForkedTest wasn't expected to be run", 
wasTestRun(trackerFile, ForkedTest.class.getName()));
+        assertFalse("ForkedTest wasn't expected to be run", 
wasTestRun(trackerFile, ForkedTest.class.getName()));
 
         
verifyLegacyXMLFile("TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingBeforeAll.xml",
 "<failure message=\"Intentional failure\" 
type=\"java.lang.RuntimeException\">");
         
verifyLegacyXMLFile("TEST-org.example.junitlauncher.jupiter.JupiterSampleTestFailingStatic.xml",
 "Caused by: java.lang.RuntimeException: Intentional exception from static init 
block");
@@ -187,9 +192,9 @@ public class JUnitLauncherTaskTest {
         final String outputDir = 
buildRule.getProject().getProperty("output.dir");
         final Path xmlFile = Paths.get(outputDir, fileName);
 
-        Assert.assertTrue("XML file doesn't exist: " + xmlFile, 
Files.exists(xmlFile));
+        assertTrue("XML file doesn't exist: " + xmlFile, 
Files.exists(xmlFile));
         final String content = new String(Files.readAllBytes(xmlFile), 
StandardCharsets.UTF_8);
-        Assert.assertTrue(fileName + " doesn't contain " + 
expectedContentExtract, content.contains(expectedContentExtract));
+        assertTrue(fileName + " doesn't contain " + expectedContentExtract, 
content.contains(expectedContentExtract));
     }
 
     /**
@@ -207,7 +212,7 @@ public class JUnitLauncherTaskTest {
         Assert.assertEquals("System property " + ForkedTest.SYS_PROP_ONE + " 
was unexpected updated",
                 "dummy", System.getProperty(ForkedTest.SYS_PROP_ONE));
 
-        Assert.assertTrue("ForkedTest#testSysProp was expected to succeed", 
verifySuccess(trackerFile,
+        assertTrue("ForkedTest#testSysProp was expected to succeed", 
verifySuccess(trackerFile,
                 ForkedTest.class.getName(), "testSysProp"));
     }
 
@@ -233,7 +238,7 @@ public class JUnitLauncherTaskTest {
             }
         }
         final String exclusionLogMsg = "Excluding JUnit platform libraries";
-        Assert.assertTrue("JUnit platform libraries weren't excluded from 
classpath", buildRule.getFullLog().contains(exclusionLogMsg));
+        assertTrue("JUnit platform libraries weren't excluded from classpath", 
buildRule.getFullLog().contains(exclusionLogMsg));
     }
 
     /**
@@ -259,7 +264,7 @@ public class JUnitLauncherTaskTest {
             }
         }
         final String exclusionLogMsg = "Excluding Ant runtime libraries";
-        Assert.assertTrue("Ant runtime libraries weren't excluded from 
classpath", buildRule.getFullLog().contains(exclusionLogMsg));
+        assertTrue("Ant runtime libraries weren't excluded from classpath", 
buildRule.getFullLog().contains(exclusionLogMsg));
     }
 
 
@@ -275,10 +280,10 @@ public class JUnitLauncherTaskTest {
         final Path trackerFile = setupTrackerProperty(targetName);
         buildRule.executeTarget(targetName);
         final String exclusionLogMsg = "Excluding JUnit platform libraries";
-        Assert.assertTrue("JUnit platform libraries weren't excluded from 
classpath", buildRule.getFullLog().contains(exclusionLogMsg));
-        Assert.assertTrue("JupiterSampleTest#testSucceeds was expected to 
succeed", verifySuccess(trackerFile,
+        assertTrue("JUnit platform libraries weren't excluded from classpath", 
buildRule.getFullLog().contains(exclusionLogMsg));
+        assertTrue("JupiterSampleTest#testSucceeds was expected to succeed", 
verifySuccess(trackerFile,
                 JupiterSampleTest.class.getName(), "testSucceeds"));
-        Assert.assertTrue("JupiterSampleTest#testFails was expected to fail", 
verifyFailed(trackerFile,
+        assertTrue("JupiterSampleTest#testFails was expected to fail", 
verifyFailed(trackerFile,
                 JupiterSampleTest.class.getName(), "testFails"));
     }
 
@@ -296,14 +301,14 @@ public class JUnitLauncherTaskTest {
         // run the target
         buildRule.executeTarget(targetName);
         final String exclusionLogMsg = "Excluding Ant runtime libraries";
-        Assert.assertTrue("Ant runtime libraries weren't excluded from 
classpath", buildRule.getFullLog().contains(exclusionLogMsg));
-        Assert.assertTrue("JupiterSampleTest#testSucceeds was expected to 
succeed", verifySuccess(trackerFile,
+        assertTrue("Ant runtime libraries weren't excluded from classpath", 
buildRule.getFullLog().contains(exclusionLogMsg));
+        assertTrue("JupiterSampleTest#testSucceeds was expected to succeed", 
verifySuccess(trackerFile,
                 JupiterSampleTest.class.getName(), "testSucceeds"));
-        Assert.assertTrue("JupiterSampleTest#testFails was expected to fail", 
verifyFailed(trackerFile,
+        assertTrue("JupiterSampleTest#testFails was expected to fail", 
verifyFailed(trackerFile,
                 JupiterSampleTest.class.getName(), "testFails"));
-        Assert.assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected 
to fail", verifyFailed(trackerFile,
+        assertTrue("AlwaysFailingJUnit4Test#testWillFail was expected to 
fail", verifyFailed(trackerFile,
                 AlwaysFailingJUnit4Test.class.getName(), "testWillFail"));
-        Assert.assertTrue("ForkedTest#testSysProp was expected to succeed", 
verifySuccess(trackerFile,
+        assertTrue("ForkedTest#testSysProp was expected to succeed", 
verifySuccess(trackerFile,
                 ForkedTest.class.getName(), "testSysProp"));
 
 
@@ -324,12 +329,12 @@ public class JUnitLauncherTaskTest {
         // run the target
         buildRule.executeTarget(targetName);
 
-        Assert.assertTrue("Ant runtime libraries weren't excluded from 
classpath",
+        assertTrue("Ant runtime libraries weren't excluded from classpath",
                 buildRule.getFullLog().contains("Excluding Ant runtime 
libraries"));
-        Assert.assertTrue("JUnit platform libraries weren't excluded from 
classpath",
+        assertTrue("JUnit platform libraries weren't excluded from classpath",
                 buildRule.getFullLog().contains("Excluding JUnit platform 
libraries"));
 
-        Assert.assertTrue("JUnit4SampleTest#testBar was expected to pass", 
verifySuccess(trackerFile,
+        assertTrue("JUnit4SampleTest#testBar was expected to pass", 
verifySuccess(trackerFile,
                 JUnit4SampleTest.class.getName(), "testBar"));
     }
 
@@ -342,9 +347,9 @@ public class JUnitLauncherTaskTest {
         final Path tracker2 = setupTrackerProperty(target);
         buildRule.executeTarget(target);
         // verify only that specific method was run
-        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be 
run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
+        assertTrue("testMethodIncludeTagisExecuted was expected to be run", 
wasTestRun(tracker2, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisExecuted"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT 
to be run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be 
run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecuted"));
     }
 
@@ -357,9 +362,9 @@ public class JUnitLauncherTaskTest {
         final Path tracker2 = setupTrackerProperty(target);
         buildRule.executeTarget(target);
         // verify only that specific method was run
-        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be 
run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
+        assertTrue("testMethodIncludeTagisExecuted was expected to be run", 
wasTestRun(tracker2, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisExecuted"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT 
to be run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be 
run", wasTestRun(tracker2, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecuted"));
     }
 
@@ -375,15 +380,15 @@ public class JUnitLauncherTaskTest {
 
         buildRule.executeTarget(target);
         // verify only that specific method was run
-        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be 
run", wasTestRun(tracker1, JupiterSampleTest.class.getName(),
+        assertTrue("testMethodIncludeTagisExecuted was expected to be run", 
wasTestRun(tracker1, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisExecuted"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT 
to be run", wasTestRun(tracker1, JupiterSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be 
run", wasTestRun(tracker1, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecuted"));
-        Assert.assertTrue("testMethodIncludeTagisExecutedTagSampleTest was 
expected to be run", wasTestRun(tracker2, JupiterTagSampleTest.class.getName(),
+        assertTrue("testMethodIncludeTagisExecutedTagSampleTest was expected 
to be run", wasTestRun(tracker2, JupiterTagSampleTest.class.getName(),
                 "testMethodIncludeTagisExecutedTagSampleTest"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest was 
expected NOT to be run", wasTestRun(tracker2, 
JupiterTagSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest was 
expected NOT to be run", wasTestRun(tracker2, 
JupiterTagSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecutedTagSampleTest"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest2 
was expected NOT to be run", wasTestRun(tracker2, 
JupiterTagSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest2 was 
expected NOT to be run", wasTestRun(tracker2, 
JupiterTagSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecutedTagSampleTest2"));
     }
     
@@ -416,7 +421,7 @@ public class JUnitLauncherTaskTest {
         final String targetName = "test-beforeall-failure-continues-build";
         final Path trackerFile = setupTrackerProperty(targetName);
         buildRule.executeTarget(targetName);
-        Assert.assertTrue("Expected @BeforeAll failure to lead to failing 
testcase", verifySetupFailed(trackerFile, 
JupiterSampleTestFailingBeforeAll.class.getName()));
+        assertTrue("Expected @BeforeAll failure to lead to failing testcase", 
verifySetupFailed(trackerFile, 
JupiterSampleTestFailingBeforeAll.class.getName()));
     }
 
 
@@ -430,15 +435,15 @@ public class JUnitLauncherTaskTest {
 
         buildRule.executeTarget(target);
         // verify only that specific method was run
-        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be 
run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
+        assertTrue("testMethodIncludeTagisExecuted was expected to be run", 
wasTestRun(tracker, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisExecuted"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT 
to be run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be 
run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecuted"));
-        Assert.assertTrue("testMethodIncludeTagisExecutedTagSampleTest was 
expected to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
+        assertTrue("testMethodIncludeTagisExecutedTagSampleTest was expected 
to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
                 "testMethodIncludeTagisExecutedTagSampleTest"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest was 
expected NOT to be run", wasTestRun(tracker, 
JupiterTagSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest was 
expected NOT to be run", wasTestRun(tracker, 
JupiterTagSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecutedTagSampleTest"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest2 
was expected NOT to be run", wasTestRun(tracker, 
JupiterTagSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest2 was 
expected NOT to be run", wasTestRun(tracker, 
JupiterTagSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecutedTagSampleTest2"));
     }
 
@@ -452,15 +457,15 @@ public class JUnitLauncherTaskTest {
 
         buildRule.executeTarget(target);
 
-        Assert.assertTrue("testMethodIncludeTagisExecuted was expected to be 
run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
+        assertTrue("testMethodIncludeTagisExecuted was expected to be run", 
wasTestRun(tracker, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisExecuted"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecuted was expected NOT 
to be run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecuted was expected NOT to be 
run", wasTestRun(tracker, JupiterSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecuted"));
-        Assert.assertTrue("testMethodIncludeTagisExecutedTagSampleTest was 
expected to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
+        assertTrue("testMethodIncludeTagisExecutedTagSampleTest was expected 
to be run", wasTestRun(tracker, JupiterTagSampleTest.class.getName(),
                 "testMethodIncludeTagisExecutedTagSampleTest"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest was 
expected NOT to be run", wasTestRun(tracker, 
JupiterTagSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest was 
expected NOT to be run", wasTestRun(tracker, 
JupiterTagSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecutedTagSampleTest"));
-        Assert.assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest2 
was expected NOT to be run", wasTestRun(tracker, 
JupiterTagSampleTest.class.getName(),
+        assertFalse("testMethodIncludeTagisNotExecutedTagSampleTest2 was 
expected NOT to be run", wasTestRun(tracker, 
JupiterTagSampleTest.class.getName(),
                 "testMethodIncludeTagisNotExecutedTagSampleTest2"));
 
         // Do it in the test, cause otherwise the file will be too big
@@ -478,7 +483,7 @@ public class JUnitLauncherTaskTest {
         final Path trackerFile = setupTrackerProperty(targetName);
         buildRule.executeTarget(targetName);
 
-        Assert.assertTrue("ForkedTest#testSysProp was expected to succeed", 
verifySuccess(trackerFile,
+        assertTrue("ForkedTest#testSysProp was expected to succeed", 
verifySuccess(trackerFile,
                 ForkedTest.class.getName(), "testSysProp"));
     }
 
@@ -494,7 +499,7 @@ public class JUnitLauncherTaskTest {
         final Path trackerFile = setupTrackerProperty(targetName);
         buildRule.executeTarget(targetName);
 
-        Assert.assertTrue("ForkedTest#testSysProp was expected to succeed", 
verifySuccess(trackerFile,
+        assertTrue("ForkedTest#testSysProp was expected to succeed", 
verifySuccess(trackerFile,
                 ForkedTest.class.getName(), "testSysProp"));
     }
 
@@ -506,17 +511,68 @@ public class JUnitLauncherTaskTest {
         final String targetName = "test-jupiter-parameterized-test";
         final Path trackerFile = setupTrackerProperty(targetName);
         buildRule.executeTarget(targetName);
-        Assert.assertTrue("JupiterSampleTest#testOddPasses was expected to 
succeed", verifySuccess(trackerFile,
+        assertTrue("JupiterSampleTest#testOddPasses was expected to succeed", 
verifySuccess(trackerFile,
                 JupiterSampleTest.class.getName(), "testOddPasses"));
-        Assert.assertTrue("JupiterSampleTest#testEvenFails was expected to 
fail", verifyFailed(trackerFile,
+        assertTrue("JupiterSampleTest#testEvenFails was expected to fail", 
verifyFailed(trackerFile,
                 JupiterSampleTest.class.getName(), "testEvenFails"));
     }
 
+    /**
+     * Tests usage of {@code <testclasses>} with {@code <fork>} with the 
default fork mode
+     */
+    @Test
+    public void testTestClassesDefaultForkMode() throws Exception {
+        final String targetName = "test-fork-one-jvm-all-tests";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        buildRule.executeTarget(targetName);
+
+        assertTrue("SharedDataAccessorTest1#testData was expected to pass",
+                verifySuccess(trackerFile, 
SharedDataAccessorTest1.class.getName(), "testData"));
+        assertTrue("SharedDataAccessorTest2#testData was expected to fail",
+                verifyFailed(trackerFile, 
SharedDataAccessorTest2.class.getName(), "testData"));
+    }
+
+    /**
+     * Tests usage of {@code <testclasses>} with {@code forkMode=perTestClass}
+     */
+    @Test
+    public void testForkPerTestClass() throws Exception {
+        final String targetName = "test-fork-per-test-class";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        buildRule.executeTarget(targetName);
+
+        assertTrue("SharedDataAccessorTest1#testData was expected to pass",
+                verifySuccess(trackerFile, 
SharedDataAccessorTest1.class.getName(), "testData"));
+        assertTrue("SharedDataAccessorTest2#testData was expected to pass",
+                verifySuccess(trackerFile, 
SharedDataAccessorTest2.class.getName(), "testData"));
+    }
+
+    /**
+     * Tests usage of {@code <test>} with {@code forkMode=perTestClass}
+     */
+    @Test
+    public void testSingleTestExplicitForkMode() throws Exception {
+        final String targetName = "test-single-test-explicit-fork-mode";
+        final Path trackerFile = setupTrackerProperty(targetName);
+        buildRule.executeTarget(targetName);
+
+        assertTrue("SharedDataAccessorTest2#testData was expected to pass",
+                verifySuccess(trackerFile, 
SharedDataAccessorTest2.class.getName(), "testData"));
+        assertFalse("SharedDataAccessorTest1 wasn't expected to be run",
+                wasTestRun(trackerFile, 
SharedDataAccessorTest1.class.getName()));
+    }
+
     private Path setupTrackerProperty(final String targetName) {
         final String filename = targetName + "-tracker.txt";
         buildRule.getProject().setProperty(targetName + ".tracker", filename);
         final String outputDir = 
buildRule.getProject().getProperty("output.dir");
-        return Paths.get(outputDir, filename);
+        final Path trackerFile = Paths.get(outputDir, filename);
+        try {
+            Files.deleteIfExists(trackerFile);
+        } catch (IOException e) {
+            throw new UncheckedIOException("Failed to delete tracker file " + 
trackerFile, e);
+        }
+        return trackerFile;
     }
 
     private void setupRuntimeClassesProperty() {
diff --git a/src/tests/junit/org/example/junitlauncher/FooBarData.java 
b/src/tests/junit/org/example/junitlauncher/FooBarData.java
new file mode 100644
index 000000000..37cc3a764
--- /dev/null
+++ b/src/tests/junit/org/example/junitlauncher/FooBarData.java
@@ -0,0 +1,31 @@
+/*
+ *  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
+ *
+ *      https://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.example.junitlauncher;
+
+public class FooBarData {
+
+    private static String data = null;
+
+    public static void setData(final String val) {
+        data = val;
+    }
+
+    public static String getData() {
+        return data;
+    }
+}
diff --git 
a/src/tests/junit/org/example/junitlauncher/jupiter/SharedDataAccessorTest1.java
 
b/src/tests/junit/org/example/junitlauncher/jupiter/SharedDataAccessorTest1.java
new file mode 100644
index 000000000..5e3bf4469
--- /dev/null
+++ 
b/src/tests/junit/org/example/junitlauncher/jupiter/SharedDataAccessorTest1.java
@@ -0,0 +1,41 @@
+/*
+ *  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
+ *
+ *      https://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.example.junitlauncher.jupiter;
+
+import org.example.junitlauncher.FooBarData;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class SharedDataAccessorTest1 {
+
+    @Test
+    void testData() {
+        final String firstAccess = FooBarData.getData();
+        assertNull(firstAccess, "expected FooBarData.getData() to return null 
on first call," +
+                " but returned " + firstAccess);
+        // now repeatedly set some data and expect the next call to getData() 
to return that value
+        final String prefix = this.getClass().getName() + "-"
+                + Thread.currentThread().getName() + "-";
+        for (int i = 0; i < 1000; i++) {
+            final String val = prefix + i;
+            FooBarData.setData(val);
+            assertEquals(val, FooBarData.getData(), "unexpected value from 
FooBarData.getData()");
+        }
+    }
+}
diff --git 
a/src/tests/junit/org/example/junitlauncher/jupiter/SharedDataAccessorTest2.java
 
b/src/tests/junit/org/example/junitlauncher/jupiter/SharedDataAccessorTest2.java
new file mode 100644
index 000000000..c7cf03aae
--- /dev/null
+++ 
b/src/tests/junit/org/example/junitlauncher/jupiter/SharedDataAccessorTest2.java
@@ -0,0 +1,41 @@
+/*
+ *  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
+ *
+ *      https://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.example.junitlauncher.jupiter;
+
+import org.example.junitlauncher.FooBarData;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class SharedDataAccessorTest2 {
+
+    @Test
+    void testData() {
+        final String firstAccess = FooBarData.getData();
+        assertNull(firstAccess, "expected FooBarData.getData() to return null 
on first call," +
+                " but returned " + firstAccess);
+        // now repeatedly set some data and expect the next call to getData() 
to return that value
+        final String prefix = this.getClass().getName() + "-"
+                + Thread.currentThread().getName() + "-";
+        for (int i = 0; i < 1000; i++) {
+            final String val = prefix + i;
+            FooBarData.setData(val);
+            assertEquals(val, FooBarData.getData(), "unexpected value from 
FooBarData.getData()");
+        }
+    }
+}

Reply via email to