Skip to content

Commit fb5f8d0

Browse files
committed
Add Toxiproxy container implementation under org.testcontainers.toxiproxy
1 parent d076937 commit fb5f8d0

File tree

4 files changed

+66
-36
lines changed

4 files changed

+66
-36
lines changed

docs/modules/toxiproxy.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ A Toxiproxy container can be placed in between test code and a container, or in
1717
In either scenario, it is necessary to create a `ToxiproxyContainer` instance on the same Docker network, as follows:
1818

1919
<!--codeinclude-->
20-
[Creating a Toxiproxy container](../../modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java) inside_block:creatingProxy
20+
[Creating a Toxiproxy container](../../modules/toxiproxy/src/test/java/org/testcontainers/toxiproxy/ToxiproxyContainerTest.java) inside_block:creatingProxy
2121
<!--/codeinclude-->
2222

2323
Next, it is necessary to instruct Toxiproxy to start proxying connections.
@@ -26,13 +26,13 @@ Each `ToxiproxyContainer` can proxy to many target containers if necessary.
2626
We do this as follows:
2727

2828
<!--codeinclude-->
29-
[Starting proxying connections to a target container](../../modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java) inside_block:obtainProxyObject
29+
[Starting proxying connections to a target container](../../modules/toxiproxy/src/test/java/org/testcontainers/toxiproxy/ToxiproxyContainerTest.java) inside_block:obtainProxyObject
3030
<!--/codeinclude-->
3131

3232
To establish a connection from the test code (on the host machine) to the target container via Toxiproxy, we obtain **Toxiproxy's** proxy host IP and port:
3333

3434
<!--codeinclude-->
35-
[Obtaining proxied host and port](../../modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java) inside_block:obtainProxiedHostAndPortForHostMachine
35+
[Obtaining proxied host and port](../../modules/toxiproxy/src/test/java/org/testcontainers/toxiproxy/ToxiproxyContainerTest.java) inside_block:obtainProxiedHostAndPortForHostMachine
3636
<!--/codeinclude-->
3737

3838
Code under test should connect to this proxied host IP and port.
@@ -56,13 +56,13 @@ Please see the [Toxiproxy documentation](https://github.com/Shopify/toxiproxy#to
5656
As one example, we can introduce latency and random jitter to proxied connections as follows:
5757

5858
<!--codeinclude-->
59-
[Adding latency to a connection](../../modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java) inside_block:addingLatency
59+
[Adding latency to a connection](../../modules/toxiproxy/src/test/java/org/testcontainers/toxiproxy/ToxiproxyContainerTest.java) inside_block:addingLatency
6060
<!--/codeinclude-->
6161

6262
Additionally we can disable the proxy to simulate a complete interruption to the network connection:
6363

6464
<!--codeinclude-->
65-
[Cutting a connection](../../modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java) inside_block:disableProxy
65+
[Cutting a connection](../../modules/toxiproxy/src/test/java/org/testcontainers/toxiproxy/ToxiproxyContainerTest.java) inside_block:disableProxy
6666
<!--/codeinclude-->
6767

6868
## Adding this module to your project dependencies
@@ -86,5 +86,3 @@ Add the following dependency to your `pom.xml`/`build.gradle` file:
8686
## Acknowledgements
8787

8888
This module was inspired by a [hotels.com blog post](https://medium.com/hotels-com-technology/i-dont-know-about-resilience-testing-and-so-can-you-b3c59d80012d).
89-
90-
[toxiproxy-java](https://github.com/trekawek/toxiproxy-java) is used to help control failure conditions.

modules/toxiproxy/src/main/java/org/testcontainers/containers/ToxiproxyContainer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
* <li>HTTP: 8474</li>
2727
* <li>Proxied Ports: 8666-8697</li>
2828
* </ul>
29+
*
30+
* @deprecated use {@link org.testcontainers.toxiproxy.ToxiproxyContainer} instead.
2931
*/
32+
@Deprecated
3033
public class ToxiproxyContainer extends GenericContainer<ToxiproxyContainer> {
3134

3235
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("shopify/toxiproxy");
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.testcontainers.toxiproxy;
2+
3+
import org.testcontainers.containers.GenericContainer;
4+
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
5+
import org.testcontainers.utility.DockerImageName;
6+
7+
/**
8+
* Testcontainers implementation for Toxiproxy.
9+
* <p>
10+
* Supported images: {@code ghcr.io/shopify/toxiproxy}, {@code shopify/toxiproxy}
11+
* <p>
12+
* Exposed ports:
13+
* <ul>
14+
* <li>HTTP: 8474</li>
15+
* <li>Proxied Ports: 8666-8697</li>
16+
* </ul>
17+
*/
18+
public class ToxiproxyContainer extends GenericContainer<ToxiproxyContainer> {
19+
20+
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("shopify/toxiproxy");
21+
22+
private static final DockerImageName GHCR_IMAGE_NAME = DockerImageName.parse("ghcr.io/shopify/toxiproxy");
23+
24+
private static final int TOXIPROXY_CONTROL_PORT = 8474;
25+
26+
private static final int FIRST_PROXIED_PORT = 8666;
27+
28+
private static final int LAST_PROXIED_PORT = 8666 + 31;
29+
30+
public ToxiproxyContainer(String dockerImageName) {
31+
this(DockerImageName.parse(dockerImageName));
32+
}
33+
34+
public ToxiproxyContainer(final DockerImageName dockerImageName) {
35+
super(dockerImageName);
36+
dockerImageName.assertCompatibleWith(DEFAULT_IMAGE_NAME, GHCR_IMAGE_NAME);
37+
38+
addExposedPorts(TOXIPROXY_CONTROL_PORT);
39+
setWaitStrategy(new HttpWaitStrategy().forPath("/version").forPort(TOXIPROXY_CONTROL_PORT));
40+
41+
// allow up to 32 ports to be proxied (arbitrary value). Here we make the ports exposed; whether or not
42+
// Toxiproxy will listen is controlled at runtime using getProxy(...)
43+
for (int i = FIRST_PROXIED_PORT; i <= LAST_PROXIED_PORT; i++) {
44+
addExposedPort(i);
45+
}
46+
}
47+
48+
/**
49+
* @return Publicly exposed Toxiproxy HTTP API control port.
50+
*/
51+
public int getControlPort() {
52+
return getMappedPort(TOXIPROXY_CONTROL_PORT);
53+
}
54+
}

modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java renamed to modules/toxiproxy/src/test/java/org/testcontainers/toxiproxy/ToxiproxyContainerTest.java

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
package org.testcontainers.containers;
1+
package org.testcontainers.toxiproxy;
22

33
import eu.rekawek.toxiproxy.Proxy;
44
import eu.rekawek.toxiproxy.ToxiproxyClient;
55
import eu.rekawek.toxiproxy.model.ToxicDirection;
66
import org.junit.jupiter.api.AutoClose;
77
import org.junit.jupiter.api.BeforeEach;
88
import org.junit.jupiter.api.Test;
9+
import org.testcontainers.containers.GenericContainer;
10+
import org.testcontainers.containers.Network;
911
import redis.clients.jedis.Jedis;
1012
import redis.clients.jedis.exceptions.JedisConnectionException;
1113

@@ -16,7 +18,7 @@
1618
import static org.assertj.core.api.Assertions.assertThat;
1719
import static org.assertj.core.api.Assertions.catchThrowable;
1820

19-
public class ToxiproxyTest {
21+
public class ToxiproxyContainerTest {
2022

2123
private static final Duration JEDIS_TIMEOUT = Duration.ofSeconds(10);
2224

@@ -157,33 +159,6 @@ public void testMultipleProxiesCanBeCreated() throws IOException {
157159
}
158160
}
159161

160-
@Test
161-
public void testOriginalAndMappedPorts() {
162-
final ToxiproxyContainer.ContainerProxy proxy = toxiproxy.getProxy("hostname", 7070);
163-
164-
final int portViaToxiproxy = proxy.getOriginalProxyPort();
165-
assertThat(portViaToxiproxy).as("original port is correct").isEqualTo(8666);
166-
167-
final ToxiproxyContainer.ContainerProxy proxy1 = toxiproxy.getProxy("hostname1", 8080);
168-
assertThat(proxy1.getOriginalProxyPort()).as("original port is correct").isEqualTo(8667);
169-
assertThat(proxy1.getProxyPort())
170-
.as("mapped port is correct")
171-
.isEqualTo(toxiproxy.getMappedPort(proxy1.getOriginalProxyPort()));
172-
173-
final ToxiproxyContainer.ContainerProxy proxy2 = toxiproxy.getProxy("hostname2", 9090);
174-
assertThat(proxy2.getOriginalProxyPort()).as("original port is correct").isEqualTo(8668);
175-
assertThat(proxy2.getProxyPort())
176-
.as("mapped port is correct")
177-
.isEqualTo(toxiproxy.getMappedPort(proxy2.getOriginalProxyPort()));
178-
}
179-
180-
@Test
181-
public void testProxyName() {
182-
final ToxiproxyContainer.ContainerProxy proxy = toxiproxy.getProxy("hostname", 7070);
183-
184-
assertThat(proxy.getName()).as("proxy name is hostname and port").isEqualTo("hostname:7070");
185-
}
186-
187162
private void checkCallWithLatency(
188163
Jedis jedis,
189164
final String description,

0 commit comments

Comments
 (0)