Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docs for startup strategy information/examples (#1157) #2565

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/examples/junit4/generic/build.gradle
Expand Up @@ -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'
}
@@ -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().withTimeout(Duration.ofSeconds(3))
rnorth marked this conversation as resolved.
Show resolved Hide resolved
);
// }

@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();
}
}
}
49 changes: 49 additions & 0 deletions docs/features/startup_and_waits.md
Expand Up @@ -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.

<!--codeinclude-->
[Using one shot startup strategy](../examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java) inside_block:withOneShotStrategy
<!--/codeinclude-->

### 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.

<!--codeinclude-->
[Using indefinite one shot startup strategy](../examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java) inside_block:withIndefiniteOneShotStrategy
<!--/codeinclude-->

### Minimum duration startup strategy example

Checks that the container is running and has been running for a defined minimum period of time.

<!--codeinclude-->
[Using minimum duration strategy](../examples/junit4/generic/src/test/java/org/testcontainers/containers/startupcheck/StartupCheckStrategyTest.java) inside_block:withMinimumDurationStrategy
<!--/codeinclude-->

### 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.