From c0277514327097abadaed58dadaa375c32fcdb5c Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Mon, 11 Nov 2019 16:09:25 +0100 Subject: [PATCH] Make `Startables#deepStart` always iterate sequentially (#2053) * Reproduce the issue with passing parallel Stream into Startables#deepStart * Fix the issue by sanitizing the input stream --- .../org/testcontainers/lifecycle/Startables.java | 1 + .../testcontainers/junit/DependenciesTest.java | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/testcontainers/lifecycle/Startables.java b/core/src/main/java/org/testcontainers/lifecycle/Startables.java index 0e6452c1914..6cf57cc6f6e 100644 --- a/core/src/main/java/org/testcontainers/lifecycle/Startables.java +++ b/core/src/main/java/org/testcontainers/lifecycle/Startables.java @@ -60,6 +60,7 @@ public CompletableFuture deepStart(Stream startables) { */ private CompletableFuture deepStart(Map> started, Stream startables) { CompletableFuture[] futures = startables + .sequential() .map(it -> { // avoid a recursive update in `computeIfAbsent` Map> subStarted = new HashMap<>(started); diff --git a/core/src/test/java/org/testcontainers/junit/DependenciesTest.java b/core/src/test/java/org/testcontainers/junit/DependenciesTest.java index df7e85a31f8..4f2ee01bc6d 100644 --- a/core/src/test/java/org/testcontainers/junit/DependenciesTest.java +++ b/core/src/test/java/org/testcontainers/junit/DependenciesTest.java @@ -9,9 +9,11 @@ import org.testcontainers.lifecycle.Startables; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; import java.util.stream.Stream; public class DependenciesTest { @@ -117,6 +119,19 @@ public void shouldHandleDiamondDependencies() throws Exception { VisibleAssertions.assertEquals("D started", 1, d.getStartInvocationCount().intValue()); } + @Test + public void shouldHandleParallelStream() throws Exception { + List startables = Stream.generate(InvocationCountingStartable::new) + .limit(10) + .collect(Collectors.toList()); + + for (int i = 1; i < startables.size(); i++) { + startables.get(0).getDependencies().add(startables.get(i)); + } + + Startables.deepStart(startables.parallelStream()).get(1, TimeUnit.SECONDS); + } + private static class InvocationCountingStartable implements Startable { @Getter @@ -131,7 +146,6 @@ private static class InvocationCountingStartable implements Startable { @Override public void start() { startInvocationCount.getAndIncrement(); - } @Override