or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/maven-org-testcontainers--toxiproxy

Testcontainers module for Shopify's Toxiproxy TCP proxy that simulates network failure conditions for resilience testing

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/org.testcontainers/toxiproxy@1.21.x

To install, run

npx @tessl/cli install tessl/maven-org-testcontainers--toxiproxy@1.21.0

0

# Testcontainers Toxiproxy

1

2

Testcontainers module for Shopify's Toxiproxy TCP proxy that simulates network failure conditions for resilience testing. This module enables developers to test application resilience by introducing network toxics (failures) between containers or between test code and containers in isolated test environments.

3

4

## Package Information

5

6

- **Package Name**: org.testcontainers:toxiproxy

7

- **Package Type**: Maven

8

- **Language**: Java

9

- **Installation**:

10

```xml

11

<dependency>

12

<groupId>org.testcontainers</groupId>

13

<artifactId>toxiproxy</artifactId>

14

<version>1.21.3</version>

15

<scope>test</scope>

16

</dependency>

17

```

18

19

Gradle:

20

```groovy

21

testImplementation 'org.testcontainers:toxiproxy:1.21.3'

22

```

23

24

## Core Imports

25

26

```java

27

import org.testcontainers.containers.ToxiproxyContainer;

28

import eu.rekawek.toxiproxy.ToxiproxyClient;

29

import eu.rekawek.toxiproxy.Proxy;

30

import eu.rekawek.toxiproxy.model.ToxicDirection;

31

```

32

33

## Basic Usage

34

35

```java

36

import org.testcontainers.containers.ToxiproxyContainer;

37

import org.testcontainers.containers.GenericContainer;

38

import org.testcontainers.containers.Network;

39

import eu.rekawek.toxiproxy.ToxiproxyClient;

40

import eu.rekawek.toxiproxy.Proxy;

41

import eu.rekawek.toxiproxy.model.ToxicDirection;

42

43

// Create a common docker network

44

Network network = Network.newNetwork();

45

46

// Target container (could be any service)

47

GenericContainer<?> redis = new GenericContainer<>("redis:6-alpine")

48

.withExposedPorts(6379)

49

.withNetwork(network)

50

.withNetworkAliases("redis");

51

52

// Toxiproxy container on same network

53

ToxiproxyContainer toxiproxy = new ToxiproxyContainer("ghcr.io/shopify/toxiproxy:2.5.0")

54

.withNetwork(network);

55

56

// Start containers

57

redis.start();

58

toxiproxy.start();

59

60

// Create Toxiproxy client and proxy

61

ToxiproxyClient client = new ToxiproxyClient(

62

toxiproxy.getHost(),

63

toxiproxy.getControlPort()

64

);

65

Proxy proxy = client.createProxy("redis", "0.0.0.0:8666", "redis:6379");

66

67

// Connect to service via proxy

68

String proxyHost = toxiproxy.getHost();

69

int proxyPort = toxiproxy.getMappedPort(8666);

70

71

// Apply network toxics for testing

72

proxy.toxics().latency("latency", ToxicDirection.DOWNSTREAM, 1000);

73

proxy.toxics().bandwidth("slow_connection", ToxicDirection.UPSTREAM, 100);

74

```

75

76

## Architecture

77

78

The Toxiproxy module is built around these key components:

79

80

- **ToxiproxyContainer**: Main container wrapper that manages the Toxiproxy Docker container lifecycle

81

- **ToxiproxyClient**: Client from toxiproxy-java library for creating and managing proxies via HTTP API

82

- **Proxy**: Represents individual proxy connections with toxic management capabilities

83

- **ContainerProxy**: Deprecated wrapper class providing convenience methods for proxy management

84

- **Network Integration**: Requires containers to be on same Docker network for inter-container communication

85

86

## Capabilities

87

88

### Container Management

89

90

Create and manage the Toxiproxy Docker container with automatic port exposure and lifecycle management.

91

92

```java { .api }

93

/**

94

* Testcontainers implementation for Toxiproxy.

95

* Supported images: ghcr.io/shopify/toxiproxy, shopify/toxiproxy

96

* Exposed ports: HTTP: 8474, Proxied Ports: 8666-8697

97

*/

98

public class ToxiproxyContainer extends GenericContainer<ToxiproxyContainer> {

99

100

/**

101

* @deprecated use ToxiproxyContainer(DockerImageName) instead

102

*/

103

@Deprecated

104

public ToxiproxyContainer();

105

106

public ToxiproxyContainer(String dockerImageName);

107

108

public ToxiproxyContainer(DockerImageName dockerImageName);

109

110

/**

111

* @return Publicly exposed Toxiproxy HTTP API control port

112

*/

113

public int getControlPort();

114

}

115

```

116

117

**Usage Examples:**

118

119

```java

120

// Using default image

121

ToxiproxyContainer toxiproxy = new ToxiproxyContainer();

122

123

// Using specific image version

124

ToxiproxyContainer toxiproxy = new ToxiproxyContainer("ghcr.io/shopify/toxiproxy:2.5.0");

125

126

// Using DockerImageName

127

DockerImageName imageName = DockerImageName.parse("shopify/toxiproxy:2.1.0");

128

ToxiproxyContainer toxiproxy = new ToxiproxyContainer(imageName);

129

130

// Get control port for client creation

131

int controlPort = toxiproxy.getControlPort();

132

```

133

134

### Proxy Creation and Management

135

136

Create TCP proxies between services and apply network failure conditions using the ToxiproxyClient.

137

138

```java { .api }

139

/**

140

* Client for managing Toxiproxy proxies via HTTP API

141

*/

142

public class ToxiproxyClient {

143

public ToxiproxyClient(String host, int port);

144

145

/**

146

* Create a new proxy

147

* @param name proxy name (must be unique)

148

* @param listen listen address in format "host:port"

149

* @param upstream upstream address in format "host:port"

150

* @return Proxy instance for managing toxics

151

*/

152

public Proxy createProxy(String name, String listen, String upstream) throws IOException;

153

}

154

155

/**

156

* Represents a single proxy connection

157

*/

158

public class Proxy {

159

/**

160

* @return proxy name

161

*/

162

public String getName();

163

164

/**

165

* @return ToxicList for managing network failure conditions

166

*/

167

public ToxicList toxics();

168

}

169

```

170

171

**Usage Examples:**

172

173

```java

174

// Create client

175

ToxiproxyClient client = new ToxiproxyClient(toxiproxy.getHost(), toxiproxy.getControlPort());

176

177

// Create proxy for Redis container

178

Proxy redisProxy = client.createProxy("redis", "0.0.0.0:8666", "redis:6379");

179

180

// Create proxy for external service

181

Proxy apiProxy = client.createProxy("api", "0.0.0.0:8667", "api.example.com:80");

182

183

// Get proxy details

184

String proxyName = redisProxy.getName(); // "redis"

185

```

186

187

### Network Toxic Management

188

189

Apply various network failure conditions to test application resilience.

190

191

```java { .api }

192

/**

193

* Interface for managing toxic conditions on a proxy

194

*/

195

public interface ToxicList {

196

/**

197

* Limit connection bandwidth

198

* @param name toxic name

199

* @param direction traffic direction (UPSTREAM/DOWNSTREAM)

200

* @param rate maximum kilobytes per second

201

* @return Toxic instance

202

*/

203

Toxic bandwidth(String name, ToxicDirection direction, long rate);

204

205

/**

206

* Add latency with optional jitter

207

* @param name toxic name

208

* @param direction traffic direction

209

* @param latency latency in milliseconds

210

* @return Toxic instance for further configuration

211

*/

212

Toxic latency(String name, ToxicDirection direction, long latency);

213

214

/**

215

* Slice TCP data into small packets

216

* @param name toxic name

217

* @param direction traffic direction

218

* @param averageSize average packet size in bytes

219

* @param sizeVariation size variation in bytes

220

* @param delay delay between packets in microseconds

221

* @return Toxic instance

222

*/

223

Toxic slicer(String name, ToxicDirection direction, int averageSize, int sizeVariation, int delay);

224

225

/**

226

* Delay socket closing

227

* @param name toxic name

228

* @param direction traffic direction

229

* @param delay delay in milliseconds

230

* @return Toxic instance

231

*/

232

Toxic slowClose(String name, ToxicDirection direction, long delay);

233

234

/**

235

* Stop data transmission and close connection after timeout

236

* @param name toxic name

237

* @param direction traffic direction

238

* @param timeout timeout in milliseconds (0 = never close)

239

* @return Toxic instance

240

*/

241

Toxic timeout(String name, ToxicDirection direction, long timeout);

242

243

/**

244

* Close connection when data limit exceeded

245

* @param name toxic name

246

* @param direction traffic direction

247

* @param bytes data limit in bytes

248

* @return Toxic instance

249

*/

250

Toxic limitData(String name, ToxicDirection direction, long bytes);

251

252

/**

253

* Get existing toxic by name

254

* @param name toxic name

255

* @return Toxic instance

256

*/

257

Toxic get(String name);

258

}

259

260

/**

261

* Represents an individual toxic condition

262

*/

263

public interface Toxic {

264

/**

265

* Remove this toxic

266

*/

267

void remove() throws IOException;

268

269

/**

270

* Set jitter for latency toxics

271

* @param jitter jitter in milliseconds

272

* @return this toxic for chaining

273

*/

274

Toxic setJitter(int jitter);

275

}

276

277

/**

278

* Traffic direction for toxic application

279

*/

280

public enum ToxicDirection {

281

UPSTREAM, // Client to server

282

DOWNSTREAM // Server to client

283

}

284

```

285

286

**Usage Examples:**

287

288

```java

289

// Add 1 second latency with 100ms jitter to downstream traffic

290

proxy.toxics()

291

.latency("latency", ToxicDirection.DOWNSTREAM, 1000)

292

.setJitter(100);

293

294

// Limit bandwidth to 100 KB/s upstream

295

proxy.toxics().bandwidth("slow_upload", ToxicDirection.UPSTREAM, 100);

296

297

// Completely cut connection (0 bandwidth both directions)

298

proxy.toxics().bandwidth("cut_down", ToxicDirection.DOWNSTREAM, 0);

299

proxy.toxics().bandwidth("cut_up", ToxicDirection.UPSTREAM, 0);

300

301

// Add connection timeout after 5 seconds

302

proxy.toxics().timeout("connection_timeout", ToxicDirection.DOWNSTREAM, 5000);

303

304

// Slice packets into 32-byte chunks with 10ms delay

305

proxy.toxics().slicer("packet_slicer", ToxicDirection.DOWNSTREAM, 32, 8, 10000);

306

307

// Remove a toxic

308

proxy.toxics().get("latency").remove();

309

```

310

311

### Legacy Proxy Management (Deprecated)

312

313

Legacy convenience methods for proxy creation and management. These methods are deprecated and will be removed in future versions.

314

315

```java { .api }

316

public class ToxiproxyContainer extends GenericContainer<ToxiproxyContainer> {

317

318

/**

319

* @deprecated ToxiproxyContainer will not build the client. Proxies should be provided manually.

320

*/

321

@Deprecated

322

public ContainerProxy getProxy(GenericContainer<?> container, int port);

323

324

/**

325

* @deprecated ToxiproxyContainer will not build the client. Proxies should be provided manually.

326

*/

327

@Deprecated

328

public ContainerProxy getProxy(String hostname, int port);

329

330

/**

331

* @deprecated Legacy proxy wrapper class

332

*/

333

@Deprecated

334

public static class ContainerProxy {

335

336

/**

337

* The IP address that this proxy container may be reached on from the host machine

338

*/

339

public String getContainerIpAddress();

340

341

/**

342

* The mapped port of this proxy. This is a port of the host machine

343

*/

344

public int getProxyPort();

345

346

/**

347

* The original (exposed) port of this proxy. This is a port of the Toxiproxy Docker container

348

*/

349

public int getOriginalProxyPort();

350

351

public String getName();

352

353

public ToxicList toxics();

354

355

/**

356

* Cuts the connection by setting bandwidth in both directions to zero

357

* @param shouldCutConnection true to cut connection, false to restore

358

*/

359

public void setConnectionCut(boolean shouldCutConnection);

360

}

361

}

362

```

363

364

## Error Handling

365

366

The module may throw these exceptions during operation:

367

368

```java { .api }

369

/**

370

* Common exceptions

371

*/

372

IOException // Thrown during proxy creation or toxic manipulation

373

IllegalStateException // Thrown when maximum proxy limit (32) exceeded

374

RuntimeException // Wrapper for IOException in proxy operations

375

```

376

377

**Error Handling Examples:**

378

379

```java

380

try {

381

Proxy proxy = client.createProxy("service", "0.0.0.0:8666", "service:8080");

382

proxy.toxics().latency("test_latency", ToxicDirection.DOWNSTREAM, 1000);

383

} catch (IOException e) {

384

// Handle proxy creation or toxic application failure

385

System.err.println("Failed to configure proxy: " + e.getMessage());

386

}

387

388

try {

389

// This will fail if more than 32 proxies are created

390

ToxiproxyContainer.ContainerProxy proxy = toxiproxy.getProxy("host", 8080);

391

} catch (IllegalStateException e) {

392

System.err.println("Maximum number of proxies exceeded");

393

}

394

```