cdr-mediation-service — Testing Strategy
Version: 1.0 Status: Draft Owner: Commerce + QA + SRE Last Updated: 2026-04-21 References: SERVICE_OVERVIEW.md, SECURITY_MODEL.md, FAILURE_MODES.md, docs/standards/DEFINITION_OF_DONE.md
Testing strategy for cdr-mediation-service. The testing bar is elevated on: TAP 3.12 / RAP encoder correctness, hash-chain integrity, export idempotency, adjustment semantics (voids/corrections must never mutate originals), and ATRA-schema compatibility.
1. Test Pyramid
┌────────────────────────┐
│ Regulator exchange │ ← monthly ATRA dry-run in staging
├────────────────────────┤
│ E2E tests │ ← DLR → CDR → daily export → mock ATRA ACK
├────────────────────────┤
│ Contract tests │ ← upstream (dlr, compliance, billing)
├────────────────────────┤
│ Integration │ ← Postgres, NATS, S3, HSM, SFTP
├────────────────────────┤
│ Unit tests │ ← dominant (encoders, formulas, chain)
└────────────────────────┘
Distribution: ~70% unit, ~18% integration, ~7% contract, ~4% E2E, ~1% regulator exchange.
2. Unit Tests
Framework: Vitest. No I/O.
2.1 CDR canonical-schema encoder
- Per direction (MT/MO): required field mapping.
- Per severity class (OTP/P1/P2/P3): billing-indicator correct.
- MSISDN hashing: SHA-256 deterministic; no raw MSISDN in output.
- Operator-ID normalisation.
- Timestamp canonical format (RFC 3339 UTC, millisecond precision).
- ≥ 30 tests covering boundary conditions.
2.2 TAP 3.12 encoder
- Called party address (international, national, unknown-NPI).
- Calling party address (alphanumeric sender-ID, E.164, short-code).
- Recording entity = Ghasi operator ID (per GSMA).
- Charging point date/time.
- BER/ASN.1 correctness per TAP 3.12 spec.
- ≥ 25 tests including extreme-length addresses and null fields.
2.3 RAP encoder
- RAP error + return record formatting.
- RAP header + batch structure.
- ≥ 10 tests.
2.4 Hash-chain
record_hash = sha256(canonical(payload) || prev_hash).- RFC 8785 JCS canonicalisation.
- Genesis prev_hash = 32 zero bytes.
- Tamper detection: single-bit flip caught.
- Concurrent-append: sequence numbers ensure ordering.
2.5 Adjustment semantics
- VOID adjustment creates new row referencing original; original unchanged.
- CORRECT adjustment creates new row with new values + reference; original unchanged.
- Chain of adjustments: latest-adjustment wins semantically but history preserved.
- Adjustment cannot mutate original CDR fields.
- Rejection: VOID after export ACK requires regulator-notification workflow.
- ≥ 20 tests.
2.6 Rollup aggregation
- Per (tenantId, operatorId, direction, hour) aggregates.
- Sum = count of CDRs.
- Value aggregation (if billing indicator present).
- Partition boundaries (hour edges).
- Late-arriving CDRs: rollup idempotency (re-run produces same result).
- ≥ 15 tests.
2.7 Property-based tests
fast-check:
- Chain monotonicity under N random appends.
- CDR canonicalisation invariant under object-key reordering.
- Adjustment chain preserves original.
- Rollup idempotency for random insert orderings.
- At least 10 properties, 500+ runs.
Coverage targets: ≥ 90% line on domain; ≥ 80% branch.
3. Integration Tests
Vitest + Testcontainers. Real Postgres, NATS, Redis, MinIO (S3), softhsm2; mock ATRA SFTP + HTTPS.
3.1 NATS → Postgres ingestion
- Publish
sms.dlr.inboundevents → CDR rows persist within 10 s. - Duplicate event → deduplicated via correlation ID.
- Invalid event → rejected + logged, not persisted.
- Lag recovery: stopped consumer resumes from JetStream cursor.
3.2 Hourly rollup
- Insert 1 000 CDRs spanning an hour → rollup produces expected aggregates.
- Rollup idempotency: re-run produces same result.
- Partial rollup (worker fails mid-way) → restart completes.
- Distributed lock prevents concurrent rollup.
3.3 Daily export pipeline
- Build export: selects last 24 h of rollups per destination schema.
- TAP 3.12 / RAP variant correct.
- File uploaded to S3 (MinIO in dev); integrity-checked.
- HSM signs file (softhsm2 in test).
- SFTP delivery to mock ATRA; ATRA ACK received.
cdr.exported.v1+cdr.export.acked.v1events published.
3.4 Export retry + timeout
- Mock ATRA returns 500 → exponential backoff retry (3 attempts).
- Mock ATRA unreachable → file retained in S3; manual retry path.
- Timeout → marked TIMEOUT; alert fires.
3.5 Adjustment creation
- Create VOID adjustment → new row; original intact; audit appended.
- Create CORRECT adjustment → new row with new values; original intact.
- Attempt UPDATE on original (via direct SQL) → Postgres trigger rejects.
3.6 Chain verifier
- Run verifier over 10 000 rows → OK in < 30 s.
- Manually corrupt one row → break detected at specific row.
- Verifier writes
cdr.audit.chain_verifiedevent.
3.7 Cold-tier archive
- Rollup older than 13 m → archived to MinIO (immutable bucket).
- Retrieve archived partition → restore to hot tier within SLA.
- Hot-tier purge after archive verified.
3.8 ClickHouse integration
- CDR rows mirror to ClickHouse within 60 s.
- ClickHouse query returns correct aggregate.
- Lag alert fires when ClickHouse insert > 10 min behind Postgres.
4. Contract Tests
4.1 Consumer contracts (Pact)
cdr-mediation-service consumes:
sms.dlr.inbound(schema from dlr-processor).compliance.audit.v1(schema from compliance-engine).billing.events.v1(schema from billing-service).
Pact tests ensure schema compatibility.
4.2 Provider contracts
cdr-mediation-service provides:
cdr.generated.v1,cdr.exported.v1,cdr.export.acked.v1,cdr.adjustment.created.v1,cdr.audit.v1— consumed byregulator-portal-service,billing-service(revenue assurance per EP-BILL-09),analytics-service.
JSON Schema registry enforces additive-only evolution.
4.3 Regulator-schema contract
Per-regulator schema adapter (ATRA TAP 3.12, ATRA HTTPS variant, etc.) — each has a golden-file contract test: canonical input → expected output.
5. End-to-End Tests
Env: dedicated cdr-e2e namespace.
5.1 Full DLR → ACK pipeline
Publish 10 000 DLR events over an hour → CDRs generated → rollup → daily export built → HSM signed → SFTP delivered to mock ATRA → ATRA ACK received → audit chain verified.
5.2 Adjustment workflow
Create CDR → VOID adjustment → verify CDR persists + new adjustment row + audit.
5.3 Export retry under backoff
Mock ATRA returns 500 for first 2 attempts, 200 on 3rd → export eventually delivered + ACKed.
5.4 Schema-version switch
Mid-test, switch regulator adapter from v1 to v2 → new exports use v2 schema; in-flight v1 exports complete.
5.5 13-month retention
Insert CDRs dated 14 months old → archive worker moves to S3 + purges hot tier → query via restore works.
6. Regulator Exchange (Staging)
Monthly dry-run with ATRA staging endpoint:
- Export file delivered to ATRA staging SFTP.
- ATRA team verifies schema + row counts.
- Feedback loop: any issue logged as adapter ticket.
- Quarterly: full end-to-end including production-like signed files.
7. Load Tests
7.1 Peak DLR ingest
Publish 500 k DLRs/hour sustained for 1 h → ingest lag stays < 30 s P99.
7.2 Export size
Build export file from 10 M rows → HSM sign + SFTP deliver within 30 min.
7.3 Adjustment burst
1 000 concurrent adjustment creations → all append correctly; chain intact.
8. Security Tests
8.1 Chain tamper
Single-bit flip via direct SQL → detected at next verifier run.
8.2 UPDATE/DELETE on CDR
Attempt direct SQL UPDATE on cdr.records → Postgres trigger rejects.
8.3 Signed-file tamper
Mock attacker modifies signed file after HSM sign → signature verification fails at ATRA; rejection captured in audit.
8.4 SFTP credential leak simulation
Rotate credentials mid-export → in-flight exports complete; next export uses new credentials.
8.5 Schema injection
Craft a CDR row with injected SQL in optional field → encoded safely; no SQL execution in downstream.
9. Coverage Targets
| Layer | Line | Branch |
|---|---|---|
| Domain | ≥ 90% | ≥ 80% |
| Application | ≥ 80% | ≥ 75% |
| Infrastructure | ≥ 60% | ≥ 60% |
| Value Objects | 100% | 95% |
Mutation testing (stryker-js): ≥ 75% aggregates, ≥ 85% VOs.
10. CI Gates
All tests run on PR. Additional:
- TypeScript strict + ESLint domain-isolation.
- Pact broker verification.
- Event schema registry conformance.
- TAP 3.12 golden-file regression (0 diffs).
- Chain-verifier integration test (no breaks).
- Security tests (chain tamper, UPDATE/DELETE rejection, signed-file tamper) all pass.
Failing any gate blocks merge.