package org.testcontainers.utility; import com.google.common.util.concurrent.Futures; import lombok.SneakyThrows; import org.junit.Test; import java.util.Collections; import java.util.List; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; import static java.util.stream.Collectors.toList; import static org.rnorth.visibleassertions.VisibleAssertions.*; public class LazyFutureTest { @Test public void testLazyness() throws Exception { AtomicInteger counter = new AtomicInteger(); Future<Integer> lazyFuture = new LazyFuture<Integer>() { @Override protected Integer resolve() { return counter.incrementAndGet(); } }; assertEquals("No resolve() invocations before get()", 0, counter.get()); assertEquals("get() call returns proper result", 1, lazyFuture.get()); assertEquals("resolve() was called only once after single get() call", 1, counter.get()); counter.incrementAndGet(); assertEquals("result of resolve() must be cached", 1, lazyFuture.get()); } @Test(timeout = 5_000) public void timeoutWorks() throws Exception { Future<Void> lazyFuture = new LazyFuture<Void>() { @Override @SneakyThrows(InterruptedException.class) protected Void resolve() { TimeUnit.MINUTES.sleep(1); return null; } }; assertThrows("Should timeout", TimeoutException.class, () -> lazyFuture.get(10, TimeUnit.MILLISECONDS)); pass("timeout works"); } @Test(timeout = 5_000) public void testThreadSafety() throws Exception { final int numOfThreads = 3; CountDownLatch latch = new CountDownLatch(numOfThreads); AtomicInteger counter = new AtomicInteger(); Future<Integer> lazyFuture = new LazyFuture<Integer>() { @Override @SneakyThrows(InterruptedException.class) protected Integer resolve() { latch.await(); return counter.incrementAndGet(); } }; Future<List<Integer>> task = new ForkJoinPool(numOfThreads).submit(() -> { return IntStream.rangeClosed(1, numOfThreads).parallel().mapToObj(i -> Futures.getUnchecked(lazyFuture)).collect(toList()); }); while (latch.getCount() > 0) { latch.countDown(); } assertEquals("All threads receives the same result", Collections.nCopies(numOfThreads, 1), task.get()); } }