Skip to main content

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.inbound events → 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.v1 events 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_verified event.

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 by regulator-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

LayerLineBranch
Domain≥ 90%≥ 80%
Application≥ 80%≥ 75%
Infrastructure≥ 60%≥ 60%
Value Objects100%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.