# Test Specification — C3 Cross-Domain Matcher Component-scoped. Suite-level coverage in `_docs/02_document/tests/*.md`. ## Acceptance Criteria Traceability | AC ID | Acceptance Criterion (one-line) | Test IDs | Coverage | |-------|---------------------------------|----------|----------| | AC-1.1 | Frame-center GPS within 50 m for ≥80% of normal-flight photos | FT-P-01, **C3-IT-01** (inlier-budget partition) | Covered | | AC-2.1b | Satellite-anchor registration | FT-P-05, **C3-IT-02** | Covered | | AC-2.2 (cross-domain portion) | MRE <2.5 px cross-domain | FT-P-06, **C3-IT-03** | Covered | | AC-3.1 | Tolerate up to 350 m outliers, tilt ±20° | FT-N-01, **C3-IT-04** | Covered | | AC-4.1 | E2E latency <400 ms p95 | NFT-PERF-01, **C3-PT-01** | Covered | --- ## Component-Internal Tests ### C3-IT-01: per-candidate inlier-count floor on Derkachi **Summary**: on the Derkachi normal segment, the best candidate's RANSAC inlier count is at least the configured floor (default ≥ 80 inliers per frame). **Traces to**: AC-1.1 (component-level partition feeding AC-1.1's accuracy budget) **Description**: for the Derkachi normal-segment fixture, run C3 with the production-default DISK+LightGlue backbone; record `MatchResult.per_candidate[best_candidate_idx].inlier_count`; assert p5 ≥ 80 (i.e., ≥95% of frames clear the floor). **Input data**: `flight_derkachi/normal_segment_60_stills/` + C10-built tile descriptors (read-only). **Expected result**: p5 inlier count ≥ 80 for DISK+LightGlue. **Max execution time**: 4 min on Tier-1 (CPU fallback) / 90 s on Tier-2. --- ### C3-IT-02: best-candidate selection determinism **Summary**: `best_candidate_idx == argmax(inlier_count)` for every emitted `MatchResult`. **Traces to**: AC-2.1b **Description**: 100 frames through `match`; assert (a) `best_candidate_idx` equals the index of the largest `inlier_count` in `per_candidate`, (b) ties are broken deterministically (lowest tile_id wins; check against a known-tie synthetic fixture). **Input data**: `synthetic_matcher/known_tie_10f/` (synthetic frames where two candidates have identical inlier counts). **Expected result**: deterministic tie-breaking; no `best_candidate_idx` mismatch in 100/100 frames. **Max execution time**: 60 s. --- ### C3-IT-03: cross-domain MRE bound **Summary**: median per-frame reprojection residual stays under 2.5 px for the production-default matcher on the Derkachi normal segment. **Traces to**: AC-2.2 **Description**: same Derkachi fixture; record `MatchResult.reprojection_residual_px`; assert p95 < 2.5 px. **Input data**: as C3-IT-01. **Expected result**: p95 < 2.5 px for DISK+LightGlue. ALIKED+LightGlue (secondary) and XFeat (alternate) tested on a smoke subset only — comparative-study verdict belongs to IT-12. **Max execution time**: 4 min. --- ### C3-IT-04: tilt + outlier robustness **Summary**: under ±20° tilt and synthetic 350 m outliers, the matcher still produces a usable inlier set (≥40 inliers). **Traces to**: AC-3.1 **Description**: synthetically tilt the Derkachi frames by {−20°, −10°, 0°, +10°, +20°}; inject 350 m position outliers into the candidate tile metadata for 5% of frames; assert C3 emits a `MatchResult` with `best_candidate.inlier_count ≥ 40` for ≥90% of frames in each tilt bucket. **Input data**: `flight_derkachi/tilted_±20°/` (deterministic synthetic tilt). **Expected result**: per-bucket inlier-count p10 ≥ 40 for DISK+LightGlue. **Max execution time**: 6 min. --- ### C3-IT-05: `InsufficientInliersError` propagation **Summary**: when all N=3 candidates fall below the inlier floor, C3 raises `InsufficientInliersError` and emits no `MatchResult`. **Traces to**: AC-3.5 (defensive — keeps the spoof-fallback path clean) **Description**: synthetic frames with deliberately mismatched candidate tiles (cross-region pulls); assert `match` raises `InsufficientInliersError` for every frame and the downstream consumer (C3.5 / C4) receives no `MatchResult`. **Input data**: `synthetic_matcher/cross_region_mismatch_20f/`. **Expected result**: 20/20 frames raise the error. **Max execution time**: 60 s. --- ## Performance Tests ### C3-PT-01: per-frame match latency on Tier-2 (dominant cost) **Traces to**: AC-4.1 (C3 owns the largest single partition of the budget) **Load scenario**: 3 Hz, N=3 candidates, 10 min replay; concurrent C2 backbone + C5 iSAM2 update on the same Jetson. **Expected results**: | Metric | Target | Failure Threshold | |--------|--------|-------------------| | `match` p95 | ≤ 180 ms (DISK+LightGlue) | 280 ms | | Per-candidate p95 | ≤ 60 ms | 95 ms | | Throughput | ≥ 3 Hz sustained | < 2.5 Hz | **Resource limits**: - GPU memory: ≤ 800 MB for backbone + matcher engines combined. --- ## Security Tests C3 has no externally-reachable surface; defensive coverage at the cache-poisoning level (NFT-SEC-01) and via shared-runtime invariants (C2.5-IT-03). --- ## Acceptance Tests Covered transitively via FT-P-01, FT-P-05, FT-P-06. --- ## Test Data Management | Data Set | Source | Size | |----------|--------|------| | `flight_derkachi/normal_segment_60_stills/` | shared | shared | | `flight_derkachi/tilted_±20°/` | generated | ~150 MB | | `synthetic_matcher/known_tie_10f/` | generated | ~5 MB | | `synthetic_matcher/cross_region_mismatch_20f/` | generated | ~10 MB | | C10-built tile descriptors | C10 artifact | shared | **Setup**: C10 must have built tile descriptors; matchers' TRT engines must be compiled (consumes ~5 min on Tier-2 first run; cached after). **Teardown**: read-only. **Data isolation**: per-test temp dirs.