Skip to content

Instantly share code, notes, and snippets.

@rnorth
Last active March 20, 2019 13:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rnorth/4c3666d62fa93bf0daa813b282e4ebff to your computer and use it in GitHub Desktop.
Save rnorth/4c3666d62fa93bf0daa813b282e4ebff to your computer and use it in GitHub Desktop.
import com.github.dockerjava.api.command.InspectContainerResponse;
import eu.rekawek.toxiproxy.Proxy;
import eu.rekawek.toxiproxy.ToxiproxyClient;
import eu.rekawek.toxiproxy.model.ToxicDirection;
import eu.rekawek.toxiproxy.model.ToxicList;
import org.junit.Rule;
import org.junit.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
import redis.clients.jedis.Jedis;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class ToxiProxyTest {
@Rule
public Network network = Network.newNetwork();
@Rule
public GenericContainer redis = new GenericContainer("redis:latest")
.withExposedPorts(6379)
.withNetwork(network);
@Rule
public ToxiproxyContainer toxiproxy = new ToxiproxyContainer()
.withNetwork(network);
@Test
public void testDirect() {
final Jedis jedis = new Jedis(redis.getContainerIpAddress(), redis.getFirstMappedPort());
jedis.set("Hello", "world");
final String s = jedis.get("Hello");
assertEquals("world", s);
}
@Test
public void testViaProxy() throws IOException {
final ToxiproxyContainer.ContainerProxy proxy = toxiproxy.getProxy(redis, 6379);
final Jedis jedis = new Jedis(proxy.getContainerIpAddress(), proxy.getProxyPort());
jedis.set("Hello", "world");
String s = jedis.get("Hello");
assertEquals("world", s);
proxy.toxics()
.latency("latency", ToxicDirection.DOWNSTREAM, 10_000)
.setJitter(10_000);
for (int i = 0; i < 10; i++) {
try {
s = jedis.get("Hello");
assertEquals("world", s);
return;
} catch (Exception e) {
}
}
fail();
}
public static class ToxiproxyContainer extends GenericContainer<ToxiproxyContainer> {
private ToxiproxyClient client;
private final Map<String, ContainerProxy> proxies = new HashMap<>();
private final AtomicInteger nextPort = new AtomicInteger(8666);
public ToxiproxyContainer() {
super("shopify/toxiproxy:2.1.0");
}
@Override
protected void configure() {
addExposedPorts(8474);
setWaitStrategy(new HttpWaitStrategy().forPath("/version").forPort(8474));
for (int i = 0; i < 32; i++) {
addExposedPort(8666 + i);
}
}
@Override
protected void containerIsStarted(InspectContainerResponse containerInfo) {
client = new ToxiproxyClient(getContainerIpAddress(), getMappedPort(8474));
}
public ContainerProxy getProxy(GenericContainer container, int port) {
String upstream = container.getNetworkAliases().get(0) + ":" + port;
return proxies.computeIfAbsent(upstream, __ -> {
try {
final int toxiPort = nextPort.getAndIncrement();
Proxy proxy = client.createProxy("name", "0.0.0.0:" + toxiPort, upstream);
return new ContainerProxy(proxy, getContainerIpAddress(), getMappedPort(toxiPort));
} catch (IOException e) {
throw new UnsupportedOperationException(); // TODO: Replace
}
});
}
public static class ContainerProxy {
private final Proxy toxi;
private final String ip;
private final int port;
public ContainerProxy(Proxy toxi, String ip, int port) {
this.toxi = toxi;
this.ip = ip;
this.port = port;
}
public ToxicList toxics() {
return toxi.toxics();
}
public String getContainerIpAddress() {
return ip;
}
public int getProxyPort() {
return port;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment