From c0fc42ff60bdf639ce28ab6dc3d97117548f1e0a Mon Sep 17 00:00:00 2001 From: vcvitaly Date: Thu, 21 May 2020 20:02:23 +0300 Subject: [PATCH] Add docs for startup strategy information/examples (#1157) (#2565) * Add startup strategy information/examples to mkdocs #1157 * Update docs/examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java Co-authored-by: Sergei Egorov Co-authored-by: Richard North --- docs/examples/junit4/generic/build.gradle | 1 + .../StartupCheckStrategyTest.java | 90 +++++++++++++++++++ docs/features/startup_and_waits.md | 49 ++++++++++ 3 files changed, 140 insertions(+) create mode 100644 docs/examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java diff --git a/docs/examples/junit4/generic/build.gradle b/docs/examples/junit4/generic/build.gradle index 97902d5d9ca..5ce878c7ba2 100644 --- a/docs/examples/junit4/generic/build.gradle +++ b/docs/examples/junit4/generic/build.gradle @@ -5,4 +5,5 @@ dependencies { testCompile project(":testcontainers") testCompile project(":selenium") testCompile "org.seleniumhq.selenium:selenium-api:3.141.59" + testCompile 'org.assertj:assertj-core:3.15.0' } diff --git a/docs/examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java b/docs/examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java new file mode 100644 index 00000000000..5ab32919bb2 --- /dev/null +++ b/docs/examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java @@ -0,0 +1,90 @@ +package org.testcontainers.containers.startupcheck; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import lombok.SneakyThrows; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.WaitingConsumer; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.testcontainers.containers.output.OutputFrame.OutputType.STDOUT; +import static org.testcontainers.containers.startupcheck.StartupCheckStrategyTest.IndefiniteOneShotStrategyTest; +import static org.testcontainers.containers.startupcheck.StartupCheckStrategyTest.MinimumDurationStrategyTest; +import static org.testcontainers.containers.startupcheck.StartupCheckStrategyTest.OneShotStrategyTest; + +@RunWith(Suite.class) +@Suite.SuiteClasses({OneShotStrategyTest.class, IndefiniteOneShotStrategyTest.class, MinimumDurationStrategyTest.class}) +public class StartupCheckStrategyTest { + + private static final String HELLO_TESTCONTAINERS = "Hello Testcontainers!"; + + private static void waitForHello(GenericContainer container) throws TimeoutException { + WaitingConsumer consumer = new WaitingConsumer(); + container.followOutput(consumer, STDOUT); + + consumer.waitUntil(frame -> + frame.getUtf8String().contains(HELLO_TESTCONTAINERS), 30, TimeUnit.SECONDS); + } + + public static class OneShotStrategyTest { + @Rule + // withOneShotStrategy { + public GenericContainer bboxWithOneShot = new GenericContainer("busybox:1.31.1") + .withCommand(String.format("echo %s", HELLO_TESTCONTAINERS)) + .withStartupCheckStrategy( + new OneShotStartupCheckStrategy().withTimeout(Duration.ofSeconds(3)) + ); + // } + + @SneakyThrows + @Test + public void testCommandIsExecuted() { + waitForHello(bboxWithOneShot); + + assertThat(bboxWithOneShot.isRunning()).isFalse(); + } + } + + public static class IndefiniteOneShotStrategyTest { + @Rule + // withIndefiniteOneShotStrategy { + public GenericContainer bboxWithIndefiniteOneShot = new GenericContainer("busybox:1.31.1") + .withCommand("sh", "-c", String.format("sleep 5 && echo \"%s\"", HELLO_TESTCONTAINERS)) + .withStartupCheckStrategy( + new IndefiniteWaitOneShotStartupCheckStrategy() + ); + // } + + @SneakyThrows + @Test + public void testCommandIsExecuted() { + waitForHello(bboxWithIndefiniteOneShot); + + assertThat(bboxWithIndefiniteOneShot.isRunning()).isFalse(); + } + } + + public static class MinimumDurationStrategyTest { + @Rule + // withMinimumDurationStrategy { + public GenericContainer bboxWithMinimumDuration = new GenericContainer("busybox:1.31.1") + .withCommand("sh", "-c", String.format("sleep 5 && echo \"%s\"", HELLO_TESTCONTAINERS)) + .withStartupCheckStrategy( + new MinimumDurationRunningStartupCheckStrategy(Duration.ofSeconds(5)) + ); + // } + + @SneakyThrows + @Test + public void testCommandIsExecuted() { + waitForHello(bboxWithMinimumDuration); + + assertThat(bboxWithMinimumDuration.isRunning()).isTrue(); + } + } +} diff --git a/docs/features/startup_and_waits.md b/docs/features/startup_and_waits.md index e1d30457e5c..3cbec97af0d 100644 --- a/docs/features/startup_and_waits.md +++ b/docs/features/startup_and_waits.md @@ -74,3 +74,52 @@ If none of these options meet your requirements, you can create your own subclas appropriate wait mechanism in `waitUntilReady()`. The `GenericContainer.waitingFor()` method accepts any valid [`WaitStrategy`](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/wait/strategy/WaitStrategy.html). + +## Startup check Strategies + +Ordinarily Testcontainers will check that the container has reached the running state and has not exited. +In order to do that inspect is executed against the container and state parameter is extracted. + +All logic is implemented in [`StartupCheckStrategy`](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/startupcheck/StartupCheckStrategy.html) child classes. + +### Running startup strategy example + +This is the strategy used by default. Testcontainers just checks if container is running. + +Implemented in [`IsRunningStartupCheckStrategy`](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers/startupcheck/IsRunningStartupCheckStrategy.html) class. + +### One shot startup strategy example + +This strategy is intended for use with containers that only run briefly and exit of their own accord. As such, success is deemed to be when +the container has stopped with exit code 0. + + +[Using one shot startup strategy](../examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java) inside_block:withOneShotStrategy + + +### Indefinite one shot startup strategy example + +Variant of one shot strategy that does not impose a timeout. Intended for situation such as when a long running task forms part of + container startup. + +It has to be assumed that the container will stop of its own accord, either with a success or failure exit code. + + +[Using indefinite one shot startup strategy](../examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java) inside_block:withIndefiniteOneShotStrategy + + +### Minimum duration startup strategy example + +Checks that the container is running and has been running for a defined minimum period of time. + + +[Using minimum duration strategy](../examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java) inside_block:withMinimumDurationStrategy + + +### Other startup strategies + +If none of these options meet your requirements, you can create your own subclass of +[`StartupCheckStrategy`](http://static.javadoc.io/org.testcontainers/testcontainers/{{ latest_version }}/org/testcontainers/containers +/startupcheck/StartupCheckStrategy.html) with an appropriate startup check mechanism in `waitUntilStartupSuccessful()`. +Or you can leave it as is and just implement the `checkStartupState(DockerClient dockerClient, String containerId)` if you still want to check state + periodically.