Testing & Validation
Ferrum Edge ships its test tooling in the gateway itself: config validation, backend mocking, chaos fault injection, shadow traffic mirroring, and on-demand load testing — plus reproducible benchmark suites in the repository.
Validate Configuration Before You Deploy
The validate subcommand checks a config without starting the gateway — perfect as a CI gate.
# Validate a file-mode spec
ferrum-edge validate --spec resources.yaml
# Validate settings + spec together
ferrum-edge validate --settings /etc/ferrum/ferrum.conf --spec /etc/ferrum/resources.yaml
# Use as a CI gate — nonzero exit on any error
ferrum-edge validate --spec resources.yaml || exit 1
Validation catches duplicate listen paths, malformed plugin configs, unknown plugin names, invalid credential shapes, and schema mismatches — the same checks the gateway performs at startup.
Smoke-Test a Running Gateway
# Liveness — no auth, always {"status":"ok"} while the process runs
curl http://localhost:9000/live
# Readiness — no auth returns status+ready; full diagnostics require a JWT
curl http://localhost:9000/health
# Authenticated deep health + runtime metrics snapshot
curl -H "Authorization: Bearer $TOKEN" http://localhost:9000/health
curl -H "Authorization: Bearer $TOKEN" http://localhost:9000/metrics/runtime
# Send a request through a configured proxy
curl -i http://localhost:8000/api/v1/hello
# On errors, X-Gateway-Error and X-Gateway-Upstream-Status headers explain why
transaction_debugger plugin in development —
it prints every plugin decision, timing, and routing outcome per request with sensitive headers redacted.
Mock Backends with response_mock
Develop and contract-test against APIs that don't exist yet — rules are scoped to the proxy's listen path, and unmatched requests can pass through to the real backend.
plugin_configs:
- id: "orders-mock"
plugin_name: "response_mock"
scope: proxy
enabled: true
config:
passthrough_on_no_match: true # unmatched requests hit the real backend
rules:
- method: GET
path: "/orders/~\\d+" # regex paths use the ~ prefix
status: 200
headers:
content-type: application/json
body: '{"id": 1, "status": "shipped"}'
delay_ms: 150 # simulate realistic latency
- method: POST
path: "/orders"
status: 201
body: '{"id": 2, "status": "created"}'
Chaos-Test Clients with fault_injection
Prove your clients handle failure before production does it for you. Works on HTTP, gRPC, TCP, and UDP.
plugin_configs:
- id: "chaos-http"
plugin_name: "fault_injection"
scope: proxy
enabled: true
config:
abort:
percentage: 5.0 # 5% of requests
http_status: 503
delay:
percentage: 20.0 # 20% of requests
duration_ms: 500
plugin_configs:
- id: "chaos-stream"
plugin_name: "fault_injection"
scope: proxy
enabled: true
config:
stream:
connect_reject_percentage: 2.0
connect_delay_ms: 200
datagram:
abort_percentage: 1.0
delay_ms: 50
Per-instance counters keep proxy- and group-scoped experiments independent, so you can chaos-test one route without touching the rest of the gateway.
Shadow-Test with request_mirror
Duplicate a sample of live traffic to a new service version. Fire-and-forget — the mirror can be slow or down without affecting a single client response.
plugin_configs:
- id: "shadow-v2"
plugin_name: "request_mirror"
scope: proxy
enabled: true
config:
mirror_scheme: https
mirror_host: "orders-v2.internal"
mirror_port: 443
sample_percentage: 10.0 # deterministic, evenly spaced sampling
forward_body: true # include bodies (bounded budgets apply)
Mirror outcomes flow into transaction logs and Prometheus counters
(ferrum_request_mirror_*), so you can compare the shadow service's behavior against
production before cutting over. Origin-bound credentials are stripped from mirrored requests by default.
On-Demand Load Tests with load_testing
Trigger a load test with a single header — the gateway spawns virtual clients that send requests back through its own proxy listener, exercising the full pipeline: routing, auth, rate limiting, backend dispatch, and logging.
plugin_configs:
- id: "loadtest"
plugin_name: "load_testing"
scope: proxy
enabled: true
config:
trigger_key: "${LOADTEST_KEY}" # required in X-Loadtesting-Key
virtual_clients: 200
duration_seconds: 30
ramp_up_seconds: 5
# Fan out to remote gateway instances for multi-node tests:
# gateway_addresses: ["https://gw-2:8443", "https://gw-3:8443"]
curl -H "X-Loadtesting-Key: $LOADTEST_KEY" http://localhost:8000/api/v1/hello
# Watch results in your metrics: latency histograms, status windows, pool stats
curl -H "Authorization: Bearer $TOKEN" http://localhost:9000/metrics/runtime
Run the Repository Test & Benchmark Suites
Building from source? The repo includes the full test pyramid and the reproducible benchmark harnesses behind our published numbers.
git clone https://github.com/ferrum-edge/ferrum-edge.git
cd ferrum-edge
# Unit + integration + E2E tests (same gate as CI)
cargo test --all-features
# Lint at CI strictness
cargo clippy --all-targets --all-features -- -D warnings
cargo fmt --check
# Multi-protocol performance suite (HTTP/1.1/2/3, gRPC, WS, TCP, UDP)
# See tests/performance/multi_protocol/README.md for options
cd tests/performance && ./run_all.sh
# Docker gateway comparison harness (Ferrum vs Envoy, Kong, Tyk)
cd comparison && ./run_comparison.sh
# Gateway API / Istio conformance matrix
cargo test --test conformance_tests