mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-29 02:39:04 +00:00
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:
committed by
Brian Clozel
parent
13a43e76cb
commit
bbfe6a0473
+10
-8
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user