Skip to main content

Testing

:::info Source Sourced from services/sync-service/TESTING_STRATEGY.md in the documentation repo. :::

1. Coverage

Domain 95% / 98% branch / 80% mutation. Integration 85%.

2. Unit Tests

  • VectorClock merge (max per device; tie-break).
  • Cursor advancement (monotonic; no regression).
  • Conflict detection per policy (lww, server_authoritative, append_only, crdt_yjs).
  • Delta projection from event → delta row.
  • Mutation validation (device binding, tenant match, schema validation).
  • Full-resync trigger (cursor too old).

3. Integration Tests (Testcontainers)

  • Postgres + NATS.
  • Push 100 mutations → route to mock owning services → verify outcomes.
  • Pull with various cursor ages → verify delta correctness.
  • Conflict detection + auto-resolution for lww + server_authoritative.
  • Yjs merge (M5): concurrent edits → CRDT merge.
  • Full-resync flow.
  • Device unbinding → sync refused.

4. Property Tests

  • VectorClock: any ordering of events produces correct merge.
  • LWW: concurrent writers → deterministic winner.
  • Cursor: no delta missed between two consecutive cursors.
  • Append-only: no conflicts regardless of push order.

5. Contract Tests

  • Pact: sync ← every replicable service's event schemas.
  • Pact: sync → every owning service's push handler.
  • Sync protocol API contract verified across client SDKs (web, iOS, Android).

6. E2E Tests

  • J-12: Airplane-mode E2E — learner plays offline → reconnects → statements synced → progress updated.
  • J-20: Multi-device sync — learner on laptop + tablet; progress consistent across both.
  • J-21: Offline authoring (M5) — author edits offline → reconnects → Yjs merge → no data loss.

7. Chaos Tests

  • Drop 10% of NATS messages for 2 min → verify delta projector catches up on retry.
  • Kill sync-service pod mid-push → client retries; server dedup on clientMutationId.
  • Corrupt a delta row → pull detects inconsistency → force-resync.
  • Device clock jump +48h → server-time reconciliation.
  • Network partition: client → server for 30 min → verify all mutations delivered after reconnect.

8. Multi-Device Sync Tests

  • Two devices push mutations for same user concurrently.
  • Both pull → cursors advance independently.
  • Conflicting lww update → deterministic resolution.

9. Offline Tests

  • Client offline 7 days → push all accumulated mutations → server processes.
  • Client offline 14 days → client enters read-only mode → prompt to sync.
  • Client offline > 30 days (cursor expired) → full-resync.
  • Tampered mutation payload → HMAC fails → rejected.

10. Yjs CRDT Tests (M5)

  • Two authors edit same draft block concurrently → merge without loss.
  • One author offline, other online → merge on reconnect.
  • Three-way merge scenario → no data loss.
  • Schema divergence (rare) → escalate to manual conflict.

11. Security Tests

  • Cross-tenant push attempt → 403.
  • Cross-user delta pull → 403.
  • Unbound device → 403.
  • Replay clientMutationId → idempotent return.
  • Forged HMAC → rejected.
  • Oversized payload → 413.

12. Load Tests

  • 10k concurrent push batches (100 mutations each) → p95 < 500ms.
  • 10k concurrent pulls → p95 < 300ms.
  • Delta projection: 100k events/sec from domain events → lag < 30s.

13. Replay Tests

  • Rebuild deltas table from domain event log → byte-exact match.

14. CI Gates

  • Unit + integration + property + chaos green.
  • Pact contracts verified.
  • Two-tenant iso green.
  • VectorClock property tests pass.
  • Mutation ≥ 80%.