Skip to main content

MEMO-038: Proxy Integration Testing Strategy

Context

PR #29 introduced transparent proxying for KeyValue operations (prism-proxy → keyvalue-runner → memstore). Initial unit tests failed because they expected the proxy to work without a backend connection. We needed both proper unit tests and true integration tests.

Problem

  1. Unit tests were testing the wrong thing - expecting success when backend unavailable
  2. No integration tests to verify end-to-end transparent proxying works
  3. E2E tests require manual setup (prismctl local start) - not suitable for CI

Solution

1. Fixed Unit Tests

Updated tests in prism-proxy/src/server/keyvalue.rs to verify correct error handling:

// Unit tests now expect Unavailable status when backend not connected
let response = service.set(request).await;
assert!(response.is_err(), "Set request should fail without backend");

let err = response.unwrap_err();
assert_eq!(err.code(), tonic::Code::Unavailable);
assert!(err.message().contains("not connected"));

Result: All 17 unit tests pass ✅

2. Created Integration Test Runner

New binary: proxy-integration-runner (prism-proxy/src/bin/proxy_integration_runner.rs)

What it does:

  1. Builds prism-proxy and keyvalue-runner binaries
  2. Spawns keyvalue-runner with memstore on port 9095
  3. Spawns prism-proxy on port 9090 (connects to keyvalue-runner)
  4. Runs 6 gRPC client tests against prism-proxy
  5. Auto-cleanup on completion/failure

Test coverage:

  • Set → Get → Verify value matches
  • Exists check
  • Delete → Verify deleted
  • Non-existent key handling

Architecture:

Test Client → prism-proxy:9090 → keyvalue-runner:9095 → memstore

3. Usage

# From project root
./prism-proxy/target/debug/proxy-integration-runner

# Or build first
cd prism-proxy && cargo build --bin proxy-integration-runner

Output:

✅ All integration tests passed!

Test 1: Set key - ✅ Set operation succeeded
Test 2: Get key - ✅ Get operation succeeded, value matches
Test 3: Check key exists - ✅ Exists operation succeeded
Test 4: Delete key - ✅ Delete operation succeeded
Test 5: Verify key deleted - ✅ Key no longer exists
Test 6: Get non-existent key - ✅ Non-existent key returns not found

Testing Pyramid

E2E Tests (manual)     →  tests/e2e/transparent_proxy_test.go
│ (requires `prismctl local start`)

Integration Tests → proxy-integration-runner
│ (spawns real processes, automated)

Unit Tests → cargo test --lib
(mocked/no backend, fast)

CI Integration

Add to GitHub Actions:

- name: Run Proxy Integration Tests
run: |
cd prism-proxy
cargo build --bin prism-proxy --bin proxy-integration-runner
cd ..
./prism-proxy/target/debug/proxy-integration-runner

Key Insights

  1. Unit tests test component behavior (error handling, logic)
  2. Integration tests test component interaction (proxy → runner → backend)
  3. E2E tests test full system (launcher, admin, proxy, runners)
  4. Use real processes for integration tests, not mocks (catches protocol/connection issues)
  5. Auto-cleanup via Drop trait ensures ports don't stay occupied

Files Changed

  • prism-proxy/src/server/keyvalue.rs - Fixed unit tests
  • prism-proxy/src/bin/proxy_integration_runner.rs - New integration runner (320 lines)
  • prism-proxy/Cargo.toml - Added binary target

Results

  • ✅ All unit tests pass (17/17)
  • ✅ All integration tests pass (6/6)
  • ✅ PR #29 CI passes
  • ✅ Verifies transparent proxying works end-to-end
  • PR #29: Transparent proxy of KeyValueTTL and launcher callback integration
  • RFC-035: Pattern Process Launcher
  • MEMO-037: Launcher Callback Protocol