From 211f83a402bbb6e780b8dacc821364cd3e8bd90b Mon Sep 17 00:00:00 2001 From: Benedikt Waldvogel Date: Thu, 22 Aug 2024 10:37:34 +0200 Subject: [PATCH 1/4] Make ExecutorServiceExtension.TestNameUtils static --- src/main/java/de/cronn/testutils/ExecutorServiceExtension.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/cronn/testutils/ExecutorServiceExtension.java b/src/main/java/de/cronn/testutils/ExecutorServiceExtension.java index b37ca0a..76a4e7b 100644 --- a/src/main/java/de/cronn/testutils/ExecutorServiceExtension.java +++ b/src/main/java/de/cronn/testutils/ExecutorServiceExtension.java @@ -62,7 +62,7 @@ public void awaitAllFutures() throws Exception { } } - class TestNameUtils { + static class TestNameUtils { private TestNameUtils() { } From 443095d60ce287da6a4c0519c7533c56546dafcd Mon Sep 17 00:00:00 2001 From: Benedikt Waldvogel Date: Thu, 22 Aug 2024 10:42:35 +0200 Subject: [PATCH 2/4] Introduce ExecutorServiceExtensionTest --- .../ExecutorServiceExtensionTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/java/de/cronn/testutils/ExecutorServiceExtensionTest.java diff --git a/src/test/java/de/cronn/testutils/ExecutorServiceExtensionTest.java b/src/test/java/de/cronn/testutils/ExecutorServiceExtensionTest.java new file mode 100644 index 0000000..22fb34b --- /dev/null +++ b/src/test/java/de/cronn/testutils/ExecutorServiceExtensionTest.java @@ -0,0 +1,34 @@ +package de.cronn.testutils; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.util.List; +import java.util.concurrent.Future; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(ThreadLeakCheck.class) +class ExecutorServiceExtensionTest { + + @RegisterExtension + ExecutorServiceExtension executorServiceExtension = new ExecutorServiceExtension(10_000); + + @Test + void testHappyCase() throws Exception { + executorServiceExtension.submit(() -> "one"); + executorServiceExtension.submit(() -> "two"); + executorServiceExtension.submit(() -> "three"); + + executorServiceExtension.awaitAllFutures(); + + List> futures = executorServiceExtension.getFutures(); + assertThat(futures).hasSize(3); + assertThat(futures) + .map(Future::get) + .map(Object::toString) + .containsExactlyInAnyOrder("one", "two", "three"); + } + +} From 02d85c4837b783a14ef7f779124e95b34dc70043 Mon Sep 17 00:00:00 2001 From: Benedikt Waldvogel Date: Thu, 22 Aug 2024 10:46:57 +0200 Subject: [PATCH 3/4] Allow using java.time.Duration for timeout values in ExecutorService utilities --- .../testutils/ExecutorServiceExtension.java | 11 +++++--- .../cronn/testutils/ExecutorServiceUtils.java | 27 +++++++++++++++---- .../ExecutorServiceExtensionTest.java | 3 ++- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/cronn/testutils/ExecutorServiceExtension.java b/src/main/java/de/cronn/testutils/ExecutorServiceExtension.java index 76a4e7b..754921a 100644 --- a/src/main/java/de/cronn/testutils/ExecutorServiceExtension.java +++ b/src/main/java/de/cronn/testutils/ExecutorServiceExtension.java @@ -1,5 +1,6 @@ package de.cronn.testutils; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; @@ -15,17 +16,21 @@ public class ExecutorServiceExtension implements BeforeEachCallback, AfterEachCallback { - private final long testTimeoutMillis; + private final Duration testTimeout; private ExecutorService executorService; private List> futures; public ExecutorServiceExtension(long testTimeoutMillis) { - this.testTimeoutMillis = testTimeoutMillis; + this(Duration.ofMillis(testTimeoutMillis)); + } + + public ExecutorServiceExtension(Duration testTimeout) { + this.testTimeout = testTimeout; } @Override public void afterEach(ExtensionContext context) { - ExecutorServiceUtils.shutdownOrThrow(executorService, getTestName(context), testTimeoutMillis); + ExecutorServiceUtils.shutdownOrThrow(executorService, getTestName(context), testTimeout); } @Override diff --git a/src/main/java/de/cronn/testutils/ExecutorServiceUtils.java b/src/main/java/de/cronn/testutils/ExecutorServiceUtils.java index 96a5d70..38218b0 100644 --- a/src/main/java/de/cronn/testutils/ExecutorServiceUtils.java +++ b/src/main/java/de/cronn/testutils/ExecutorServiceUtils.java @@ -1,5 +1,6 @@ package de.cronn.testutils; +import java.time.Duration; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; @@ -16,11 +17,15 @@ public final class ExecutorServiceUtils { private ExecutorServiceUtils() { } - public static void shutdownOrThrow(ExecutorService executor, String executorServiceName, long timeoutMs) { + public static void shutdownOrThrow(ExecutorService executor, String executorServiceName, long timeoutMillis) { + shutdownOrThrow(executor, executorServiceName, Duration.ofMillis(timeoutMillis)); + } + + public static void shutdownOrThrow(ExecutorService executor, String executorServiceName, Duration timeout) { if (executor != null) { try { - if (!shutdownGracefully(executor, executorServiceName, timeoutMs)) { - boolean success = shutdownNow(executor, executorServiceName, timeoutMs); + if (!shutdownGracefully(executor, executorServiceName, timeout)) { + boolean success = shutdownNow(executor, executorServiceName, timeout); Assertions.assertTrue(success, String.format("Failed to shutdown %s", executorServiceName)); } } catch (InterruptedException e) { @@ -31,11 +36,23 @@ public static void shutdownOrThrow(ExecutorService executor, String executorServ } public static boolean shutdownNow(ExecutorService executorService, String executorServiceName, long timeoutMillis) throws InterruptedException { - return shutdown(executorService, executorServiceName, timeoutMillis, true); + return shutdownNow(executorService, executorServiceName, Duration.ofMillis(timeoutMillis)); + } + + public static boolean shutdownNow(ExecutorService executorService, String executorServiceName, Duration timeout) throws InterruptedException { + return shutdown(executorService, executorServiceName, timeout, true); } public static boolean shutdownGracefully(ExecutorService executorService, String executorServiceName, long timeoutMillis) throws InterruptedException { - return shutdown(executorService, executorServiceName, timeoutMillis, false); + return shutdownGracefully(executorService, executorServiceName, Duration.ofMillis(timeoutMillis)); + } + + public static boolean shutdownGracefully(ExecutorService executorService, String executorServiceName, Duration timeout) throws InterruptedException { + return shutdown(executorService, executorServiceName, timeout, false); + } + + private static boolean shutdown(ExecutorService executorService, String executorServiceName, Duration timeout, boolean shutdownWithInterrupt) throws InterruptedException { + return shutdown(executorService, executorServiceName, timeout.toMillis(), shutdownWithInterrupt); } private static boolean shutdown(ExecutorService executorService, String executorServiceName, long timeoutMillis, boolean shutdownWithInterrupt) throws InterruptedException { diff --git a/src/test/java/de/cronn/testutils/ExecutorServiceExtensionTest.java b/src/test/java/de/cronn/testutils/ExecutorServiceExtensionTest.java index 22fb34b..89f1e4b 100644 --- a/src/test/java/de/cronn/testutils/ExecutorServiceExtensionTest.java +++ b/src/test/java/de/cronn/testutils/ExecutorServiceExtensionTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.RegisterExtension; +import java.time.Duration; import java.util.List; import java.util.concurrent.Future; @@ -13,7 +14,7 @@ class ExecutorServiceExtensionTest { @RegisterExtension - ExecutorServiceExtension executorServiceExtension = new ExecutorServiceExtension(10_000); + ExecutorServiceExtension executorServiceExtension = new ExecutorServiceExtension(Duration.ofSeconds(10)); @Test void testHappyCase() throws Exception { From e60abad9c3e3fb0c8e600e586ffe4020c3e66436 Mon Sep 17 00:00:00 2001 From: Benedikt Waldvogel Date: Thu, 22 Aug 2024 10:48:29 +0200 Subject: [PATCH 4/4] Use pattern variables where possible --- src/main/java/de/cronn/testutils/ExecutorServiceUtils.java | 6 ++---- .../java/de/cronn/testutils/spring/ResetClockExtension.java | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/cronn/testutils/ExecutorServiceUtils.java b/src/main/java/de/cronn/testutils/ExecutorServiceUtils.java index 38218b0..4ef7e88 100644 --- a/src/main/java/de/cronn/testutils/ExecutorServiceUtils.java +++ b/src/main/java/de/cronn/testutils/ExecutorServiceUtils.java @@ -70,8 +70,7 @@ private static boolean shutdown(ExecutorService executorService, String executor if (success) { log.info("Finished shutdown of '{}'", executorServiceName); } else { - if (executorService instanceof ThreadPoolExecutor) { - ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService; + if (executorService instanceof ThreadPoolExecutor threadPoolExecutor) { log.warn("Shutdown of '{}' timed out after {} ms. Active tasks: {}", executorServiceName, timeoutMillis, threadPoolExecutor.getActiveCount()); } else { log.warn("Shutdown of '{}' timed out after {} ms.", executorServiceName, timeoutMillis); @@ -81,8 +80,7 @@ private static boolean shutdown(ExecutorService executorService, String executor } private static void clearQueue(ExecutorService executorService, String executorServiceName) { - if (executorService instanceof ThreadPoolExecutor) { - ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executorService; + if (executorService instanceof ThreadPoolExecutor threadPoolExecutor) { BlockingQueue queue = threadPoolExecutor.getQueue(); if (!queue.isEmpty()) { int queueSize = queue.size(); diff --git a/src/main/java/de/cronn/testutils/spring/ResetClockExtension.java b/src/main/java/de/cronn/testutils/spring/ResetClockExtension.java index 44d8779..e124d35 100644 --- a/src/main/java/de/cronn/testutils/spring/ResetClockExtension.java +++ b/src/main/java/de/cronn/testutils/spring/ResetClockExtension.java @@ -45,8 +45,8 @@ public static boolean hasDeclaredMethodOrder(ExtensionContext context) { protected void resetClock(ExtensionContext context) { ApplicationContext applicationContext = SpringExtension.getApplicationContext(context); Clock clock = applicationContext.getBean(Clock.class); - if (clock instanceof TestClock) { - ((TestClock) clock).reset(); + if (clock instanceof TestClock testClock) { + testClock.reset(); } }