diff --git a/core/src/test/java/org/testcontainers/junit/FixedHostPortContainerTest.java b/core/src/test/java/org/testcontainers/junit/FixedHostPortContainerTest.java index 516fcb8516a..dba48da4db1 100644 --- a/core/src/test/java/org/testcontainers/junit/FixedHostPortContainerTest.java +++ b/core/src/test/java/org/testcontainers/junit/FixedHostPortContainerTest.java @@ -1,10 +1,19 @@ package org.testcontainers.junit; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import com.google.common.util.concurrent.Uninterruptibles; import org.junit.Test; +import org.rnorth.ducttape.unreliables.Unreliables; import org.testcontainers.containers.FixedHostPortGenericContainer; import org.testcontainers.containers.GenericContainer; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; +import java.net.Socket; +import java.util.concurrent.TimeUnit; /** * Test of {@link FixedHostPortGenericContainer}. Note that this is not an example of typical use (usually, a container @@ -14,28 +23,74 @@ */ public class FixedHostPortContainerTest { - private static final int REDIS_PORT = 6379; + private static final String TEST_IMAGE = "alpine:3.2"; + + /** + * Default http server port (just something different from default) + */ + private static final int TEST_PORT = 5678; + + /** + * test response + */ + private static final String TEST_RESPONSE = "test-response"; + + /** + * *nix pipe to fire test response on test port + */ + private static final String HTTP_ECHO_CMD = + String.format("while true; do echo \"%s\" | nc -l -p %d; done", TEST_RESPONSE, TEST_PORT); @Test public void testFixedHostPortMapping() throws IOException { // first find a free port on the docker host that will work for testing - GenericContainer portDiscoveryRedis = new GenericContainer("redis:3.0.2").withExposedPorts(REDIS_PORT); - portDiscoveryRedis.start(); - Integer freePort = portDiscoveryRedis.getMappedPort(REDIS_PORT); - portDiscoveryRedis.stop(); - - - // Set up a FixedHostPortGenericContainer as if this were a @Rule - FixedHostPortGenericContainer redis = new FixedHostPortGenericContainer("redis:3.0.2").withFixedExposedPort(freePort, REDIS_PORT); - redis.start(); - -// Config redisConfig = new Config(); -// redisConfig.useSingleServer().setAddress(redis.getContainerIpAddress() + ":" + freePort); -// Redisson redisson = Redisson.create(redisConfig); -// -// redisson.getBucket("test").set("foo"); -// -// assertEquals("The bucket content was successfully set", "foo", redisson.getBucket("test").get()); -// assertEquals("The container returns the fixed port from getMappedPort(...)", freePort, redis.getMappedPort(REDIS_PORT)); + final Integer unusedHostPort; + try ( + final GenericContainer echoServer = new GenericContainer<>(TEST_IMAGE) + .withExposedPorts(TEST_PORT) + .withCommand("/bin/sh", "-c", HTTP_ECHO_CMD) + ) { + echoServer.start(); + unusedHostPort = echoServer.getMappedPort(TEST_PORT); + } + + // now starting echo server container mapped to known-as-free host port + try ( + final GenericContainer echoServer = new FixedHostPortGenericContainer(TEST_IMAGE) + // using workaround for port bind+expose + .withFixedExposedPort(unusedHostPort, TEST_PORT) + .withExposedPorts(TEST_PORT) + .withCommand("/bin/sh", "-c", HTTP_ECHO_CMD) + ) { + echoServer.start(); + + assertThat("Port mapping does not seem to match given fixed port", + echoServer.getMappedPort(TEST_PORT), equalTo(unusedHostPort)); + + final String content = this.readResponse(echoServer, unusedHostPort); + assertThat("Returned echo from fixed port does not match expected", content, equalTo(TEST_RESPONSE)); + } + } + + /** + * Simple socket content reader from given container:port + * + * @param container to query + * @param port to send request to + * @return socket reader content + * @throws IOException if any + */ + private String readResponse(GenericContainer container, Integer port) throws IOException { + try ( + final BufferedReader reader = Unreliables.retryUntilSuccess(10, TimeUnit.SECONDS, + () -> { + Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); + final Socket socket = new Socket(container.getContainerIpAddress(), port); + return new BufferedReader(new InputStreamReader(socket.getInputStream())); + } + ) + ) { + return reader.readLine(); + } } }