Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,28 @@
*/
public class Timeouts {

private static final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool(new ThreadFactory() {
private static final AtomicInteger THREAD_COUNTER = new AtomicInteger(0);

final AtomicInteger threadCounter = new AtomicInteger(0);
private static final ThreadFactory THREAD_FACTORY = r -> {
Thread thread = new Thread(r, "ducttape-" + THREAD_COUNTER.getAndIncrement());
thread.setDaemon(true);
return thread;
};

@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r, "ducttape-" + threadCounter.getAndIncrement());
thread.setDaemon(true);
return thread;
private static volatile ExecutorService executorService;

private static synchronized ExecutorService getExecutorService() {
if (executorService == null || executorService.isShutdown()) {
executorService = Executors.newCachedThreadPool(THREAD_FACTORY);
}
});
return executorService;
}

public static void shutdown() {
EXECUTOR_SERVICE.shutdown();
public static synchronized void shutdown() {
if (executorService != null) {
executorService.shutdown();
executorService = null;
}
}

/**
Expand All @@ -40,7 +48,7 @@ public static <T> T getWithTimeout(final int timeout, final TimeUnit timeUnit, f

check("timeout must be greater than zero", timeout > 0);

Future<T> future = EXECUTOR_SERVICE.submit(lambda);
Future<T> future = getExecutorService().submit(lambda);
return callFuture(timeout, timeUnit, future);
}

Expand All @@ -57,7 +65,7 @@ public static void doWithTimeout(final int timeout, final TimeUnit timeUnit, fin

check("timeout must be greater than zero", timeout > 0);

Future<?> future = EXECUTOR_SERVICE.submit(lambda);
Future<?> future = getExecutorService().submit(lambda);
callFuture(timeout, timeUnit, future);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.testcontainers.utility;

import org.junit.Test;
import org.testcontainers.utility.ducttape.Timeouts;

import java.util.concurrent.TimeUnit;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Verifies that {@link Timeouts} works correctly across shutdown/reuse cycles.
* After {@code shutdown()} the executor is re-created on next use.
*/
public class TimeoutsShutdownTest {

@Test
public void timeoutsWorkAfterShutdown() {
// First use
String result1 = Timeouts.getWithTimeout(5, TimeUnit.SECONDS, () -> "container-1-ready");
assertThat(result1).isEqualTo("container-1-ready");

// Shutdown (as GenericContainer.stop() does)
Timeouts.shutdown();

// Second use — should transparently create a fresh executor
String result2 = Timeouts.getWithTimeout(5, TimeUnit.SECONDS, () -> "container-2-ready");
assertThat(result2).isEqualTo("container-2-ready");

// Shutdown and use again to confirm repeatable
Timeouts.shutdown();

String result3 = Timeouts.getWithTimeout(5, TimeUnit.SECONDS, () -> "container-3-ready");
assertThat(result3).isEqualTo("container-3-ready");
}
}
Loading