Skip to content

Commit

Permalink
Add test code
Browse files Browse the repository at this point in the history
  • Loading branch information
YongGoose committed Jan 18, 2025
1 parent 96951ce commit 78c5c80
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public void execute(ExecutionRequest request) {

private void executeAllChildren(VintageEngineDescriptor engineDescriptor,
EngineExecutionListener engineExecutionListener, ExecutionRequest request) {
initializeParallelExecution(request);
initializeParallelExecutionParameters(request);

boolean parallelExecutionEnabled = getParallelExecutionEnabled(request);
if (!parallelExecutionEnabled) {
Expand Down Expand Up @@ -155,13 +155,6 @@ private boolean executeInParallel(VintageEngineDescriptor engineDescriptor,
return wasInterrupted;
}

private RunnerTestDescriptor parallelMethodExecutor(RunnerTestDescriptor runnerTestDescriptor,
ExecutorService executorService) {
runnerTestDescriptor.setExecutorService(executorService);

return runnerTestDescriptor;
}

private List<RunnerTestDescriptor> collectRunnerTestDescriptors(VintageEngineDescriptor engineDescriptor,
ExecutorService executorService) {
List<RunnerTestDescriptor> runnerTestDescriptors = new ArrayList<>();
Expand All @@ -177,6 +170,12 @@ private List<RunnerTestDescriptor> collectRunnerTestDescriptors(VintageEngineDes
return runnerTestDescriptors;
}

private RunnerTestDescriptor parallelMethodExecutor(RunnerTestDescriptor runnerTestDescriptor,
ExecutorService executorService) {
runnerTestDescriptor.setExecutorService(executorService);
return runnerTestDescriptor;
}

private void shutdownExecutorService(ExecutorService executorService) {
try {
executorService.shutdown();
Expand Down Expand Up @@ -204,7 +203,7 @@ private boolean getParallelExecutionEnabled(ExecutionRequest request) {
return request.getConfigurationParameters().getBoolean(PARALLEL_EXECUTION_ENABLED).orElse(false);
}

private void initializeParallelExecution(ExecutionRequest request) {
private void initializeParallelExecutionParameters(ExecutionRequest request) {
classes = request.getConfigurationParameters().getBoolean(Constants.PARALLEL_CLASS_EXECUTION).orElse(false);
methods = request.getConfigurationParameters().getBoolean(Constants.PARALLEL_METHOD_EXECUTION).orElse(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,19 @@
import static org.junit.platform.testkit.engine.EventConditions.event;
import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully;
import static org.junit.platform.testkit.engine.EventConditions.started;
import static org.junit.platform.testkit.engine.EventConditions.test;
import static org.junit.vintage.engine.Constants.PARALLEL_CLASS_EXECUTION;
import static org.junit.vintage.engine.Constants.PARALLEL_EXECUTION_ENABLED;
import static org.junit.vintage.engine.Constants.PARALLEL_METHOD_EXECUTION;
import static org.junit.vintage.engine.Constants.PARALLEL_POOL_SIZE;
import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_RUNNER;
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.AbstractBlockingTestCase;
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.FirstTestCase;
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.ThirdTestCase;
import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_TEST;
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelClassesTestCase.FirstClassTestCase;
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelClassesTestCase.SecondClassTestCase;
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelClassesTestCase.ThirdClassTestCase;
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelMethodsTestCase.FirstMethodTestCase;
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelMethodsTestCase.SecondMethodTestCase;
import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelMethodsTestCase.ThirdMethodTestCase;

import java.time.Instant;
import java.util.Arrays;
Expand All @@ -42,22 +47,23 @@
import org.junit.platform.testkit.engine.Event;
import org.junit.platform.testkit.engine.Events;
import org.junit.vintage.engine.VintageTestEngine;
import org.junit.vintage.engine.samples.junit4.JUnit4ParallelTestCase.SecondTestCase;
import org.junit.vintage.engine.samples.junit4.JUnit4ParallelClassesTestCase;
import org.junit.vintage.engine.samples.junit4.JUnit4ParallelMethodsTestCase;

class ParallelExecutionIntegrationTests {

@Test
void executesTestClassesInParallel(TestReporter reporter) {
AbstractBlockingTestCase.threadNames.clear();
AbstractBlockingTestCase.countDownLatch = new CountDownLatch(3);
JUnit4ParallelClassesTestCase.AbstractBlockingTestCase.threadNames.clear();
JUnit4ParallelClassesTestCase.AbstractBlockingTestCase.countDownLatch = new CountDownLatch(3);

var events = executeInParallelSuccessfully(3, FirstTestCase.class, SecondTestCase.class,
ThirdTestCase.class).list();
var events = executeInParallelSuccessfully(3, true, false, FirstClassTestCase.class, SecondClassTestCase.class,
ThirdClassTestCase.class).list();

var startedTimestamps = getTimestampsFor(events, event(container(SEGMENT_TYPE_RUNNER), started()));
var finishedTimestamps = getTimestampsFor(events,
event(container(SEGMENT_TYPE_RUNNER), finishedSuccessfully()));
var threadNames = new HashSet<>(AbstractBlockingTestCase.threadNames);
var threadNames = new HashSet<>(JUnit4ParallelClassesTestCase.AbstractBlockingTestCase.threadNames);

reporter.publishEntry("startedTimestamps", startedTimestamps.toString());
reporter.publishEntry("finishedTimestamps", finishedTimestamps.toString());
Expand All @@ -69,6 +75,62 @@ void executesTestClassesInParallel(TestReporter reporter) {
assertThat(threadNames).hasSize(3);
}

@Test
void executesTestMethodsInParallel(TestReporter reporter) {
JUnit4ParallelMethodsTestCase.AbstractBlockingTestCase.threadNames.clear();
JUnit4ParallelMethodsTestCase.AbstractBlockingTestCase.countDownLatch = new CountDownLatch(3);

var events = executeInParallelSuccessfully(3, false, true, FirstMethodTestCase.class).list();

var startedTimestamps = getTimestampsFor(events, event(test(SEGMENT_TYPE_TEST), started()));
var finishedTimestamps = getTimestampsFor(events, event(test(SEGMENT_TYPE_TEST), finishedSuccessfully()));
var threadNames = new HashSet<>(JUnit4ParallelMethodsTestCase.AbstractBlockingTestCase.threadNames);

reporter.publishEntry("startedTimestamps", startedTimestamps.toString());
reporter.publishEntry("finishedTimestamps", finishedTimestamps.toString());

assertThat(startedTimestamps).hasSize(3);
assertThat(finishedTimestamps).hasSize(3);
assertThat(startedTimestamps).allMatch(startTimestamp -> finishedTimestamps.stream().noneMatch(
finishedTimestamp -> finishedTimestamp.isBefore(startTimestamp)));
assertThat(threadNames).hasSize(3);
}

@Test
void executesTestClassesAndMethodsInParallel(TestReporter reporter) {
JUnit4ParallelMethodsTestCase.AbstractBlockingTestCase.threadNames.clear();
JUnit4ParallelMethodsTestCase.AbstractBlockingTestCase.countDownLatch = new CountDownLatch(9);

var events = executeInParallelSuccessfully(3, true, true, FirstMethodTestCase.class, SecondMethodTestCase.class,
ThirdMethodTestCase.class).list();

var startedClassesTimestamps = getTimestampsFor(events, event(container(SEGMENT_TYPE_RUNNER), started()));
var finishedClassesTimestamps = getTimestampsFor(events,
event(container(SEGMENT_TYPE_RUNNER), finishedSuccessfully()));
var startedMethodsTimestamps = getTimestampsFor(events, event(test(SEGMENT_TYPE_TEST), started()));
var finishedMethodsTimestamps = getTimestampsFor(events,
event(test(SEGMENT_TYPE_TEST), finishedSuccessfully()));

var threadNames = new HashSet<>(JUnit4ParallelMethodsTestCase.AbstractBlockingTestCase.threadNames);

reporter.publishEntry("startedClassesTimestamps", startedClassesTimestamps.toString());
reporter.publishEntry("finishedClassesTimestamps", finishedClassesTimestamps.toString());
reporter.publishEntry("startedMethodsTimestamps", startedMethodsTimestamps.toString());
reporter.publishEntry("finishedMethodsTimestamps", finishedMethodsTimestamps.toString());

assertThat(startedClassesTimestamps).hasSize(3);
assertThat(finishedClassesTimestamps).hasSize(3);
assertThat(startedMethodsTimestamps).hasSize(9);
assertThat(finishedMethodsTimestamps).hasSize(9);

assertThat(startedClassesTimestamps).allMatch(startTimestamp -> finishedClassesTimestamps.stream().noneMatch(
finishedTimestamp -> finishedTimestamp.isBefore(startTimestamp)));
assertThat(startedMethodsTimestamps).allMatch(startTimestamp -> finishedMethodsTimestamps.stream().noneMatch(
finishedTimestamp -> finishedTimestamp.isBefore(startTimestamp)));

assertThat(threadNames).hasSize(3);
}

private List<Instant> getTimestampsFor(List<Event> events, Condition<Event> condition) {
// @formatter:off
return events.stream()
Expand All @@ -78,8 +140,9 @@ private List<Instant> getTimestampsFor(List<Event> events, Condition<Event> cond
// @formatter:on
}

private Events executeInParallelSuccessfully(int poolSize, Class<?>... testClasses) {
var events = execute(poolSize, testClasses).allEvents();
private Events executeInParallelSuccessfully(int poolSize, boolean parallelClasses, boolean parallelMethods,
Class<?>... testClasses) {
var events = execute(poolSize, parallelClasses, parallelMethods, testClasses).allEvents();
try {
return events.assertStatistics(it -> it.failed(0));
}
Expand All @@ -89,11 +152,14 @@ private Events executeInParallelSuccessfully(int poolSize, Class<?>... testClass
}
}

private static EngineExecutionResults execute(int poolSize, Class<?>... testClass) {
return EngineTestKit.execute(new VintageTestEngine(), request(poolSize, testClass));
private static EngineExecutionResults execute(int poolSize, boolean parallelClasses, boolean parallelMethods,
Class<?>... testClass) {
return EngineTestKit.execute(new VintageTestEngine(),
request(poolSize, parallelClasses, parallelMethods, testClass));
}

private static LauncherDiscoveryRequest request(int poolSize, Class<?>... testClasses) {
private static LauncherDiscoveryRequest request(int poolSize, boolean parallelClasses, boolean parallelMethods,
Class<?>... testClasses) {
var classSelectors = Arrays.stream(testClasses) //
.map(DiscoverySelectors::selectClass) //
.toArray(ClassSelector[]::new);
Expand All @@ -102,8 +168,8 @@ private static LauncherDiscoveryRequest request(int poolSize, Class<?>... testCl
.selectors(classSelectors) //
.configurationParameter(PARALLEL_EXECUTION_ENABLED, String.valueOf(true)) //
.configurationParameter(PARALLEL_POOL_SIZE, String.valueOf(poolSize)) //
.configurationParameter(PARALLEL_CLASS_EXECUTION, String.valueOf(true)) //
.configurationParameter(PARALLEL_METHOD_EXECUTION, String.valueOf(true)) //
.configurationParameter(PARALLEL_CLASS_EXECUTION, String.valueOf(parallelClasses)) //
.configurationParameter(PARALLEL_METHOD_EXECUTION, String.valueOf(parallelMethods)) //
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class JUnit4ParallelTestCase {
public class JUnit4ParallelClassesTestCase {

public static class AbstractBlockingTestCase {

Expand Down Expand Up @@ -56,12 +56,12 @@ private static long estimateSimulatedTestDurationInMilliseconds() {
}
}

public static class FirstTestCase extends AbstractBlockingTestCase {
public static class FirstClassTestCase extends AbstractBlockingTestCase {
}

public static class SecondTestCase extends AbstractBlockingTestCase {
public static class SecondClassTestCase extends AbstractBlockingTestCase {
}

public static class ThirdTestCase extends AbstractBlockingTestCase {
public static class ThirdClassTestCase extends AbstractBlockingTestCase {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2015-2025 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.vintage.engine.samples.junit4;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;

import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;

@RunWith(Enclosed.class)
public class JUnit4ParallelMethodsTestCase {

public static class AbstractBlockingTestCase {

public static final Set<String> threadNames = ConcurrentHashMap.newKeySet();
public static CountDownLatch countDownLatch;

@Rule
public final TestWatcher testWatcher = new TestWatcher() {
@Override
protected void starting(Description description) {
AbstractBlockingTestCase.threadNames.add(Thread.currentThread().getName());
}
};

@Test
public void fistTest() throws Exception {
countDownAndBlock(countDownLatch);
}

@Test
public void secondTest() throws Exception {
countDownAndBlock(countDownLatch);
}

@Test
public void thirdTest() throws Exception {
countDownAndBlock(countDownLatch);
}

@SuppressWarnings("ResultOfMethodCallIgnored")
private static void countDownAndBlock(CountDownLatch countDownLatch) throws InterruptedException {
countDownLatch.countDown();
countDownLatch.await(estimateSimulatedTestDurationInMilliseconds(), MILLISECONDS);
}

private static long estimateSimulatedTestDurationInMilliseconds() {
var runningInCi = Boolean.parseBoolean(System.getenv("CI"));
return runningInCi ? 1000 : 100;
}
}

public static class FirstMethodTestCase extends JUnit4ParallelMethodsTestCase.AbstractBlockingTestCase {
}

public static class SecondMethodTestCase extends JUnit4ParallelMethodsTestCase.AbstractBlockingTestCase {
}

public static class ThirdMethodTestCase extends JUnit4ParallelMethodsTestCase.AbstractBlockingTestCase {
}
}

0 comments on commit 78c5c80

Please sign in to comment.