Testing
Meridian requires every component to have all test layers: unit tests, integration tests, and benchmarks for hot-path code.
Running Tests
# All tests
cargo test --workspace
# Core library only
cargo test -p meridian-core
# Proxy unit + integration tests
cargo test -p meridian-proxy
# Integration tests only
cargo test -p meridian-proxy --test integration
# Single test
cargo test -p meridian-core -- chunked_single_chunk
Test Structure
Unit Tests (97 total)
In-module #[cfg(test)] blocks testing individual functions:
| Module | Tests | What’s Covered |
|---|---|---|
| buffer | 5 | Slab acquire/release, BufChain operations, watermarks |
| codec | 22 | HTTP parsing, body framing, smuggling rejection, chunked encoding |
| config | 2 | Config store load/swap, route lookup |
| filter | 16 | Chain execution order, short-circuit, metadata, error propagation |
| health | 8 | Threshold logic, TCP/HTTP checks |
| load_balancing | 4 | Round-robin, Maglev consistency/disruption |
| observability | 4 | Counters, gauges, histograms, snapshots |
| pool | 6 | Checkout/checkin, max idle, expiry eviction |
| resilience | 4 | Circuit breaker RAII, token bucket, retry, outlier detection |
| tls | 4 | Cert loading, error display |
| conn_limit | 4 | Per-IP limits, RAII guards |
| connection | 7 | Path normalization |
Integration Tests (15 total)
End-to-end tests in meridian-proxy/tests/integration.rs that spin up mock backends and proxy instances:
| Test | What’s Verified |
|---|---|
| Round-robin distribution | 4 requests alternate between 2 backends |
| Circuit breaker rejection | Requests rejected when CB limit reached |
| Connect timeout | 504 returned on unreachable backend |
| HTTP path routing | Prefix matching routes to correct cluster |
| Path traversal prevention | /../ normalized before routing |
| Opaque error responses | No cluster names or IPs in error bodies |
| Filter chain header inject | Response filter adds header |
| Filter chain request reject | Request filter returns 403 |
| Health check failover | Unhealthy endpoint skipped by LB |
| Connection pool reuse | 4 requests, 1 upstream TCP connection |
| Chunked response | Dechunked upstream response forwarded |
| Chunked request body | Chunked request body forwarded |
| TLS termination | Full HTTPS flow with self-signed cert |
| Admin API | /stats, /clusters, /config, /ready endpoints |
| HTTP/2 proxy | h2 client → proxy → h1 upstream → h2 response |
Test Patterns
- Mock backends use
TcpListener::bind("127.0.0.1:0")for OS-assigned ports - Integration tests sleep 50ms after spawning servers to ensure they’re listening
- TLS tests use
rcgenfor runtime-generated self-signed certificates - Tests use
Connection: closeto avoid keep-alive interactions