Make immediate-cancel task termination test deterministic

The taskTerminationTimeoutWithImmediateCancel test submitted a task and
immediately closed the executor, then asserted that the future was
cancelled. The cancellation flag is set by close() on the calling thread,
while it is checked at the start of the task on a separate worker thread.
With no ordering guarantee between the two, a quickly scheduled worker
could pass the cancellation check before close() set the flag, complete
the trivial task normally, and leave the future uncancelled, making the
test fail intermittently under load.

Override doExecute to capture the task-tracking wrapper instead of
running it on a background thread, then run it on the test thread after
close() has set the cancellation flag. This exercises the same
cancellation path deterministically, with no reliance on thread
scheduling.

Signed-off-by: junhyeong9812 <pickjog@gmail.com>
This commit is contained in:
junhyeong9812
2026-07-10 20:30:19 +02:00
committed by Brian Clozel
parent 13a43e76cb
commit bbfe6a0473
@@ -21,6 +21,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Test;
@@ -153,17 +154,18 @@ class SimpleAsyncTaskExecutorTests {
@Test
void taskTerminationTimeoutWithImmediateCancel() {
AtomicBoolean finished = new AtomicBoolean();
AtomicReference<Runnable> captured = new AtomicReference<>();
Future<?> future;
try (SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor()) {
try (SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor() {
@Override
protected void doExecute(Runnable task) {
captured.set(task);
}
}) {
executor.setTaskTerminationTimeout(100);
future = executor.submit(() -> {
if (finished.get()) {
throw new IllegalStateException();
}
});
future = executor.submit(() -> {});
}
finished.set(true);
assertThatExceptionOfType(CancellationException.class).isThrownBy(captured.get()::run);
assertThatExceptionOfType(CancellationException.class).isThrownBy(future::get);
}