Files

3.7 KiB

Chaos Mode

Inject controlled failures into contract tests to validate resilience guarantees.

Chaos testing applies invariant-driven verification under adverse conditions: if a contract must hold, it should still hold when dependencies fail, responses are delayed, or payloads are corrupted.

Usage

const result = await fastify.apophis.contract({
  runs: 50,
  chaos: {
    delay: { probability: 0.1, minMs: 100, maxMs: 500 },
    error: { probability: 0.1, statusCode: 503 },
    dropout: { probability: 0.05 },
    corruption: { probability: 0.1 },
  },
});

Event Types

Delay

Adds artificial latency. Tests timeout contracts:

response_time(this) < 1000

Delay chaos strategies (inbound-delay, outbound-delay) are applied at the transport level between request execution and contract evaluation. The inline chaos handlers for these strategies are no-ops because sleep() handles delay application out-of-band. Delay contracts such as response_time(this) < 1000 will still work correctly with chaos injection.

Error

Forces HTTP status codes. Tests error-handling contracts:

// Behavioral: when the service is unavailable, the client receives a valid retry signal
if status:503 then response_headers(this).retry-after > 0

Dropout

Simulates network failure (status 0). Tests fallback contracts:

// Behavioral: partial failure must still return previously cached data
if status:0 then response_body(this).cached_data == previous(response_body(GET /cache/{request_params(this).key}))

Corruption

Mutates response bodies. Tests parsing robustness:

// Behavioral: corrupted requests maintain traceability for debugging
if status:400 then response_body(this).request_id == request_headers(this).x-request-id

Corruption Strategies

Built-in strategies are content-type agnostic:

Strategy Effect
truncate Cuts response body short
malformed Invalidates structural boundaries (e.g., unclosed JSON, bad headers)
field-corrupt Replaces a random field value with corrupted data

Extension strategies can add content-type-specific behavior if needed.

Note: Extension-defined corruption strategies are documented for future implementation. Currently, corruption strategies (truncate, malformed, field-corrupt) are hardcoded in the chaos engine.

Environment Guard

Low-level contract chaos APIs require NODE_ENV=test. For CLI qualification, environment policy controls whether chaos gates may run.

Error: chaos is only available in test environment. Set NODE_ENV=test to enable quality features.

Interpreting Results

Failed tests include chaos events in diagnostics:

{
  "statusCode": 503,
  "error": "Contract violation: if status:503 then response_headers(this).retry-after > 0",
  "chaosEvents": [
    {
      "type": "error",
      "injected": true,
      "details": {
        "statusCode": 503,
        "reason": "Chaos error: overridden 200 with 503"
      }
    }
  ]
}

Best Practices

  1. Start small: probability: 0.05 (5% of requests)
  2. Test one failure mode at a time: Comment out other chaos types
  3. Verify contracts handle chaos: if status:503 then response_code(GET /health) == 200
  4. Use seeds for reproducibility: seed: 42 makes chaos deterministic

Example: Testing Retry Logic

fastify.get('/data', {
  schema: {
    'x-ensures': [
      'if status:503 then response_headers(this).retry-after > 0',
      'redirect_count(this) <= 3',
    ],
  },
}, handler);

// Test
const result = await fastify.apophis.contract({
  chaos: {
    error: { probability: 0.2, statusCode: 503 },
  },
});