From 47f1959047e62d79ee0b0917a092b00b07c1c63e Mon Sep 17 00:00:00 2001 From: Richard North Date: Sat, 15 Apr 2017 20:52:23 +0100 Subject: [PATCH 1/3] Resolve #326, making browser container startup timeout configurable. Reduces default browser container startup timeout to 15s, down from an unnecessarily high 120s. This also replaces inheritance-based `waitUntilContainerStarted` with composition-based `WaitStrategy`. The new `LogMessageWaitStrategy` allows us to wait based upon the Selenium container log output, rather than the relatively expensive process of repeatedly trying to create and connect a `RemoteWebDriver` instance. --- .../containers/GenericContainer.java | 3 +- .../containers/BrowserWebDriverContainer.java | 35 ++++++++----------- ...stomWaitTimeoutWebDriverContainerTest.java | 27 ++++++++++++++ 3 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 modules/selenium/src/test/java/org/testcontainers/junit/CustomWaitTimeoutWebDriverContainerTest.java diff --git a/core/src/main/java/org/testcontainers/containers/GenericContainer.java b/core/src/main/java/org/testcontainers/containers/GenericContainer.java index 167ea5864b9..8055650ef41 100644 --- a/core/src/main/java/org/testcontainers/containers/GenericContainer.java +++ b/core/src/main/java/org/testcontainers/containers/GenericContainer.java @@ -867,8 +867,9 @@ public ExecResult execInContainer(Charset outputCharset, String... command) * * @param attempts number of attempts */ - public void withStartupAttempts(int attempts) { + public SELF withStartupAttempts(int attempts) { this.startupAttempts = attempts; + return self(); } @Override diff --git a/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java b/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java index 1798ec41116..2003c91894c 100644 --- a/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java +++ b/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java @@ -1,28 +1,28 @@ package org.testcontainers.containers; -import com.google.common.util.concurrent.Uninterruptibles; +import com.github.dockerjava.api.command.InspectContainerResponse; import org.jetbrains.annotations.Nullable; import org.junit.runner.Description; import org.openqa.selenium.remote.BrowserType; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; -import org.rnorth.ducttape.unreliables.Unreliables; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testcontainers.containers.traits.LinkableContainer; import org.testcontainers.containers.traits.VncService; +import org.testcontainers.containers.wait.LogMessageWaitStrategy; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; +import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.Date; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import static com.google.common.base.Preconditions.checkState; +import static java.time.temporal.ChronoUnit.SECONDS; /** * A chrome/firefox/custom container based on SeleniumHQ's standalone container sets. @@ -55,7 +55,9 @@ public class BrowserWebDriverContainer { - Uninterruptibles.sleepUninterruptibly(backoff.getAndUpdate(current -> (int)(current * 1.5)), TimeUnit.MILLISECONDS); - RemoteWebDriver driver = new RemoteWebDriver(getSeleniumAddress(), desiredCapabilities); - driver.getCurrentUrl(); - - logger().info("Obtained a connection to container ({})", BrowserWebDriverContainer.this.getSeleniumAddress()); - return driver; - }); - + protected void containerIsStarted(InspectContainerResponse containerInfo) { if (recordingMode != VncRecordingMode.SKIP) { LOGGER.debug("Starting VNC recording"); - VncRecordingSidekickContainer recordingSidekickContainer = new VncRecordingSidekickContainer<>(this); + + // Use multiple startup attempts due to race condition between Selenium being available and VNC being available + VncRecordingSidekickContainer recordingSidekickContainer = new VncRecordingSidekickContainer<>(this) + .withStartupAttempts(3); + recordingSidekickContainer.start(); currentVncRecordings.add(recordingSidekickContainer); } + this.driver = new RemoteWebDriver(getSeleniumAddress(), desiredCapabilities); } /** diff --git a/modules/selenium/src/test/java/org/testcontainers/junit/CustomWaitTimeoutWebDriverContainerTest.java b/modules/selenium/src/test/java/org/testcontainers/junit/CustomWaitTimeoutWebDriverContainerTest.java new file mode 100644 index 00000000000..d189ba34a24 --- /dev/null +++ b/modules/selenium/src/test/java/org/testcontainers/junit/CustomWaitTimeoutWebDriverContainerTest.java @@ -0,0 +1,27 @@ +package org.testcontainers.junit; + +import org.junit.Rule; +import org.junit.Test; +import org.openqa.selenium.remote.DesiredCapabilities; +import org.testcontainers.containers.BrowserWebDriverContainer; + +import java.io.IOException; +import java.time.Duration; + +import static java.time.temporal.ChronoUnit.SECONDS; + +/** + * + */ +public class CustomWaitTimeoutWebDriverContainerTest extends BaseWebDriverContainerTest { + + @Rule + public BrowserWebDriverContainer chromeWithCustomTimeout = new BrowserWebDriverContainer<>() + .withDesiredCapabilities(DesiredCapabilities.chrome()) + .withStartupTimeout(Duration.of(30, SECONDS)); + + @Test + public void simpleTest() throws IOException { + doSimpleWebdriverTest(chromeWithCustomTimeout); + } +} From c962b0f634a86b785f66cf1569081badb6b8c3c6 Mon Sep 17 00:00:00 2001 From: Richard North Date: Sun, 30 Apr 2017 19:52:08 +0100 Subject: [PATCH 2/3] Resolve shading-related inheritance issues with BrowserWebDriverContainer This change makes docker-java NO LONGER SHADED into testcontainers core JAR --- core/pom.xml | 7 ++----- modules/selenium/pom.xml | 10 +++++++++- pom.xml | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/core/pom.xml b/core/pom.xml index 3251ede0877..7d6eb11395e 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -18,7 +18,8 @@ com.github.docker-java docker-java - 3.0.9 + ${docker-java.version} + compile @@ -151,10 +152,6 @@ com.fasterxml.jackson org.testcontainers.shaded.com.fasterxml.jackson - - com.github.dockerjava - org.testcontainers.shaded.com.github.dockerjava - jersey.repackaged org.testcontainers.shaded.jersey.repackaged diff --git a/modules/selenium/pom.xml b/modules/selenium/pom.xml index 676a7241082..76aa623396c 100644 --- a/modules/selenium/pom.xml +++ b/modules/selenium/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 @@ -18,6 +19,12 @@ testcontainers ${project.version} + + com.github.docker-java + docker-java + ${docker-java.version} + provided + com.google.guava @@ -39,6 +46,7 @@ org.mortbay.jetty jetty 6.1.25 + test diff --git a/pom.xml b/pom.xml index 89e073fcd1b..4c4310cef0b 100644 --- a/pom.xml +++ b/pom.xml @@ -157,6 +157,7 @@ UTF-8 + 3.0.9 From 2754c28d3d39b604212e3856f1a84a7d4f591dd5 Mon Sep 17 00:00:00 2001 From: Richard North Date: Sun, 30 Apr 2017 20:02:00 +0100 Subject: [PATCH 3/3] Trim WaitingConsumer output frame text to eliminate double-newline effect --- .../org/testcontainers/containers/output/WaitingConsumer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/testcontainers/containers/output/WaitingConsumer.java b/core/src/main/java/org/testcontainers/containers/output/WaitingConsumer.java index add8907595d..3cd0a7cecca 100644 --- a/core/src/main/java/org/testcontainers/containers/output/WaitingConsumer.java +++ b/core/src/main/java/org/testcontainers/containers/output/WaitingConsumer.java @@ -86,7 +86,8 @@ private void waitUntil(Predicate predicate, long expiry, int times) OutputFrame frame = frames.pollLast(100, TimeUnit.MILLISECONDS); if (frame != null) { - LOGGER.debug("{}: {}", frame.getType(), frame.getUtf8String()); + final String trimmedFrameText = frame.getUtf8String().replaceFirst("\n$", ""); + LOGGER.debug("{}: {}", frame.getType(), trimmedFrameText); if (predicate.test(frame)) { numberOfMatches++;