Skip to content

Commit a25da3d

Browse files
authored
Improve ToxiProxyContainer test and docs (#6065)
Current implementation exposed utilities to handle `ToxiProxyClient` and proxies. However, there are some issues which demonstrate that the container class is coupled to the client. Tests and docs have been updated in order to promote the usage of its own `ToxiProxyClient`. Also, a note about the number of ports reserved by Testcontainers is added.
1 parent 665ec1c commit a25da3d

File tree

3 files changed

+41
-47
lines changed

3 files changed

+41
-47
lines changed

docs/modules/toxiproxy.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,13 @@ We do this as follows:
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 for connections from the host machine](../../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/containers/ToxiproxyTest.java) inside_block:obtainProxiedHostAndPortForHostMachine
3636
<!--/codeinclude-->
3737

3838
Code under test should connect to this proxied host IP and port.
3939

40-
To establish a connection from a different container on the same network to the target container via Toxiproxy, we use **Toxiproxy's** network alias and original port:
41-
42-
<!--codeinclude-->
43-
[Obtaining proxied host and port for connections from a different container](../../modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java) inside_block:obtainProxiedHostAndPortForDifferentContainer
44-
<!--/codeinclude-->
40+
!!! note
41+
Currently, `ToxiProxyContainer` will reserve 31 ports, starting at 8666.
4542

4643
Other containers should connect to this proxied host and port.
4744

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ public int getControlPort() {
8585
* @param container target container
8686
* @param port port number on the target service that should be proxied
8787
* @return a {@link ContainerProxy} instance
88+
* @deprecated {@link ToxiproxyContainer} will not build the client. Proxies should be provided manually.
8889
*/
90+
@Deprecated
8991
public ContainerProxy getProxy(GenericContainer<?> container, int port) {
9092
return this.getProxy(container.getNetworkAliases().get(0), port);
9193
}
@@ -102,7 +104,9 @@ public ContainerProxy getProxy(GenericContainer<?> container, int port) {
102104
* @param hostname hostname of target server to be proxied
103105
* @param port port number on the target server that should be proxied
104106
* @return a {@link ContainerProxy} instance
107+
* @deprecated {@link ToxiproxyContainer} will not build the client. Proxies should be provided manually.
105108
*/
109+
@Deprecated
106110
public ContainerProxy getProxy(String hostname, int port) {
107111
String upstream = hostname + ":" + port;
108112

@@ -126,6 +130,7 @@ public ContainerProxy getProxy(String hostname, int port) {
126130
}
127131

128132
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
133+
@Deprecated
129134
public static class ContainerProxy {
130135

131136
private static final String CUT_CONNECTION_DOWNSTREAM = "CUT_CONNECTION_DOWNSTREAM";

modules/toxiproxy/src/test/java/org/testcontainers/containers/ToxiproxyTest.java

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package org.testcontainers.containers;
22

3+
import eu.rekawek.toxiproxy.Proxy;
4+
import eu.rekawek.toxiproxy.ToxiproxyClient;
35
import eu.rekawek.toxiproxy.model.ToxicDirection;
46
import org.junit.Rule;
57
import org.junit.Test;
6-
import org.testcontainers.utility.DockerImageName;
78
import redis.clients.jedis.Jedis;
89
import redis.clients.jedis.exceptions.JedisConnectionException;
910

@@ -19,30 +20,21 @@ public class ToxiproxyTest {
1920

2021
// spotless:off
2122
// creatingProxy {
22-
// An alias that can be used to resolve the Toxiproxy container by name in the network it is connected to.
23-
// It can be used as a hostname of the Toxiproxy container by other containers in the same network.
24-
private static final String TOXIPROXY_NETWORK_ALIAS = "toxiproxy";
25-
2623
// Create a common docker network so that containers can communicate
2724
@Rule
2825
public Network network = Network.newNetwork();
2926

30-
private static final DockerImageName REDIS_IMAGE = DockerImageName.parse("redis:5.0.4");
31-
3227
// The target container - this could be anything
3328
@Rule
34-
public GenericContainer<?> redis = new GenericContainer<>(REDIS_IMAGE)
29+
public GenericContainer<?> redis = new GenericContainer<>("redis:5.0.4")
3530
.withExposedPorts(6379)
36-
.withNetwork(network);
37-
38-
private static final DockerImageName TOXIPROXY_IMAGE = DockerImageName.parse("ghcr.io/shopify/toxiproxy:2.5.0");
31+
.withNetwork(network)
32+
.withNetworkAliases("redis");
3933

4034
// Toxiproxy container, which will be used as a TCP proxy
4135
@Rule
42-
public ToxiproxyContainer toxiproxy = new ToxiproxyContainer(TOXIPROXY_IMAGE)
43-
.withNetwork(network)
44-
.withNetworkAliases(TOXIPROXY_NETWORK_ALIAS);
45-
36+
public ToxiproxyContainer toxiproxy = new ToxiproxyContainer("ghcr.io/shopify/toxiproxy:2.5.0")
37+
.withNetwork(network);
4638
// }
4739
// spotless:on
4840

@@ -58,12 +50,13 @@ public void testDirect() {
5850
@Test
5951
public void testLatencyViaProxy() throws IOException {
6052
// obtainProxyObject {
61-
final ToxiproxyContainer.ContainerProxy proxy = toxiproxy.getProxy(redis, 6379);
53+
final ToxiproxyClient toxiproxyClient = new ToxiproxyClient(toxiproxy.getHost(), toxiproxy.getControlPort());
54+
final Proxy proxy = toxiproxyClient.createProxy("redis", "0.0.0.0:8666", "redis:6379");
6255
// }
6356

6457
// obtainProxiedHostAndPortForHostMachine {
65-
final String ipAddressViaToxiproxy = proxy.getContainerIpAddress();
66-
final int portViaToxiproxy = proxy.getProxyPort();
58+
final String ipAddressViaToxiproxy = toxiproxy.getHost();
59+
final int portViaToxiproxy = toxiproxy.getMappedPort(8666);
6760
// }
6861

6962
final Jedis jedis = createJedis(ipAddressViaToxiproxy, portViaToxiproxy);
@@ -84,17 +77,19 @@ public void testLatencyViaProxy() throws IOException {
8477
}
8578

8679
@Test
87-
public void testConnectionCut() {
88-
final ToxiproxyContainer.ContainerProxy proxy = toxiproxy.getProxy(redis, 6379);
89-
final Jedis jedis = createJedis(proxy.getContainerIpAddress(), proxy.getProxyPort());
80+
public void testConnectionCut() throws IOException {
81+
final ToxiproxyClient toxiproxyClient = new ToxiproxyClient(toxiproxy.getHost(), toxiproxy.getControlPort());
82+
final Proxy proxy = toxiproxyClient.createProxy("redis", "0.0.0.0:8666", "redis:6379");
83+
final Jedis jedis = createJedis(toxiproxy.getHost(), toxiproxy.getMappedPort(8666));
9084
jedis.set("somekey", "somevalue");
9185

9286
assertThat(jedis.get("somekey"))
9387
.as("access to the container works OK before cutting the connection")
9488
.isEqualTo("somevalue");
9589

9690
// disableProxy {
97-
proxy.setConnectionCut(true);
91+
proxy.toxics().bandwidth("CUT_CONNECTION_DOWNSTREAM", ToxicDirection.DOWNSTREAM, 0);
92+
proxy.toxics().bandwidth("CUT_CONNECTION_UPSTREAM", ToxicDirection.UPSTREAM, 0);
9893

9994
// for example, expect failure when the connection is cut
10095
assertThat(
@@ -105,7 +100,8 @@ public void testConnectionCut() {
105100
.as("calls fail when the connection is cut")
106101
.isInstanceOf(JedisConnectionException.class);
107102

108-
proxy.setConnectionCut(false);
103+
proxy.toxics().get("CUT_CONNECTION_DOWNSTREAM").remove();
104+
proxy.toxics().get("CUT_CONNECTION_UPSTREAM").remove();
109105

110106
// and with the connection re-established, expect success
111107
assertThat(jedis.get("somekey"))
@@ -115,24 +111,30 @@ public void testConnectionCut() {
115111
}
116112

117113
@Test
118-
public void testMultipleProxiesCanBeCreated() {
114+
public void testMultipleProxiesCanBeCreated() throws IOException {
119115
try (
120-
GenericContainer<?> secondRedis = new GenericContainer<>(REDIS_IMAGE)
116+
GenericContainer<?> secondRedis = new GenericContainer<>("redis:5.0.4")
121117
.withExposedPorts(6379)
122118
.withNetwork(network)
119+
.withNetworkAliases("redis2")
123120
) {
124121
secondRedis.start();
125122

126-
final ToxiproxyContainer.ContainerProxy firstProxy = toxiproxy.getProxy(redis, 6379);
127-
final ToxiproxyContainer.ContainerProxy secondProxy = toxiproxy.getProxy(secondRedis, 6379);
123+
final ToxiproxyClient toxiproxyClient = new ToxiproxyClient(
124+
toxiproxy.getHost(),
125+
toxiproxy.getControlPort()
126+
);
127+
final Proxy firstProxy = toxiproxyClient.createProxy("redis1", "0.0.0.0:8666", "redis:6379");
128+
toxiproxyClient.createProxy("redis2", "0.0.0.0:8667", "redis2:6379");
128129

129-
final Jedis firstJedis = createJedis(firstProxy.getContainerIpAddress(), firstProxy.getProxyPort());
130-
final Jedis secondJedis = createJedis(secondProxy.getContainerIpAddress(), secondProxy.getProxyPort());
130+
final Jedis firstJedis = createJedis(toxiproxy.getHost(), toxiproxy.getMappedPort(8666));
131+
final Jedis secondJedis = createJedis(toxiproxy.getHost(), toxiproxy.getMappedPort(8667));
131132

132133
firstJedis.set("somekey", "somevalue");
133134
secondJedis.set("somekey", "somevalue");
134135

135-
firstProxy.setConnectionCut(true);
136+
firstProxy.toxics().bandwidth("CUT_CONNECTION_DOWNSTREAM", ToxicDirection.DOWNSTREAM, 0);
137+
firstProxy.toxics().bandwidth("CUT_CONNECTION_UPSTREAM", ToxicDirection.UPSTREAM, 0);
136138

137139
assertThat(
138140
catchThrowable(() -> {
@@ -149,11 +151,8 @@ public void testMultipleProxiesCanBeCreated() {
149151
@Test
150152
public void testOriginalAndMappedPorts() {
151153
final ToxiproxyContainer.ContainerProxy proxy = toxiproxy.getProxy("hostname", 7070);
152-
// obtainProxiedHostAndPortForDifferentContainer {
153-
final String hostViaToxiproxy = TOXIPROXY_NETWORK_ALIAS;
154+
154155
final int portViaToxiproxy = proxy.getOriginalProxyPort();
155-
// }
156-
assertThat(hostViaToxiproxy).as("host is correct").isEqualTo(TOXIPROXY_NETWORK_ALIAS);
157156
assertThat(portViaToxiproxy).as("original port is correct").isEqualTo(8666);
158157

159158
final ToxiproxyContainer.ContainerProxy proxy1 = toxiproxy.getProxy("hostname1", 8080);
@@ -176,13 +175,6 @@ public void testProxyName() {
176175
assertThat(proxy.getName()).as("proxy name is hostname and port").isEqualTo("hostname:7070");
177176
}
178177

179-
@Test
180-
public void testControlPort() {
181-
final int controlPort = toxiproxy.getControlPort();
182-
183-
assertThat(controlPort).as("control port is mapped from port 8474").isEqualTo(toxiproxy.getMappedPort(8474));
184-
}
185-
186178
private void checkCallWithLatency(
187179
Jedis jedis,
188180
final String description,

0 commit comments

Comments
 (0)