# Batch 3 Implementation Report **Batch**: 3 of 3 (Implement Tests / Step 6) **Date**: 2026-05-10 **Tasks**: AZ-289 (Integration tests: route map processing + ZIP), AZ-290 (Non-functional tests: perf, resilience, security, limits) ## Tasks ### AZ-289 — Integration tests: route map processing + ZIP - **Spec**: `_docs/02_tasks/done/AZ-289_integration_route_maps.md` - **Outcome**: Acceptance criteria met by existing integration tests; one assertion added. - **Existing coverage**: - BT-08 (RequestMaps=true → mapsReady, stitchedImagePath, csvFilePath) — `BasicRouteTests.RunRouteWithRegionProcessingAndStitching`, `ExtendedRouteTests.RunExtendedRouteEast`, `ExtendedRouteTests.RunRouteWithTilesZipTest`. - BT-09 (ZIP entries == CSV count, directory structure preserved with `tiles/` prefix) — `ExtendedRouteTests.RunRouteWithTilesZipTest`. - AC-1 (180s timeout) — `WaitForRouteReady(routeId, 180, 3000)` in the same test. - AC-2 (ZIP structure) — entry-count + path-prefix assertions + directory depth check. - **New addition**: 50 MB ZIP cap assertion in `ExtendedRouteTests.RunRouteWithTilesZipTest` (also satisfies AZ-290 / RL-01). ### AZ-290 — Non-functional tests - **Spec**: `_docs/02_tasks/done/AZ-290_nonfunctional_tests.md` - **Outcome**: All three ACs covered by a mix of new unit tests, new integration tests, an extended performance script, and existing tests cross-referenced below. #### Performance (AC-1) `scripts/run-performance-tests.sh` extended: | Scenario | Threshold | Implementation | |----------|-----------|----------------| | PT-01 — Tile download (cold) | 30 000 ms | New: GET `/api/satellite/tiles/latlon` with offset coords | | PT-02 — Cached tile retrieval | 500 ms | Existing | | PT-03 — Region 200 m / z18 | 60 000 ms | New: POST `/api/satellite/request` + status poll | | PT-04 — Region 500 m / z18 + stitch | 120 000 ms | New: POST `/api/satellite/request` (stitchTiles=true) + status poll | | PT-05 — 5 concurrent regions | 300 000 ms | New: 5 parallel enqueues + wait-all loop | | PT-06 — Route interpolation | 5 000 ms | Existing | #### Resilience (AC-2) | Scenario | Coverage | |----------|----------| | RS-01 — API starts with DB ready | Structural (Docker Compose `depends_on`, healthcheck) | | RS-02 — Migrations run on fresh DB | Structural (DbUp on startup, `Program.cs`) | | RS-03 — Region processing handles tile failures | Unit: `RegionServiceTests.ProcessRegionAsync_DownloaderFailure_TransitionsToFailedAndWritesErrorSummary` (Batch 2) | | RS-04 — Queue capacity bounded behavior | Unit: `RegionRequestQueueTests.EnqueueAsync_BlocksWhenAtCapacity_UntilDequeue_RL02` and `EnqueueAsync_HonorsCancellation_WhenFull` (new). **Spec drift noted**: spec says "rejects overflow" but channel uses `BoundedChannelFullMode.Wait` → producer back-pressure. Tests assert actual behavior. To be reconciled in Step 12 (Test-Spec Sync). | | RS-05 — Max 4 concurrent downloads | Configuration: `appsettings.json` `ProcessingConfig.MaxConcurrentDownloads = 4`; semaphore enforced inside `GoogleMapsDownloaderV2` | | RS-06 — Route processing completes all regions | Existing: `ComplexRouteTests.RunComplexRouteWithStitching*`, `ExtendedRouteTests.RunExtendedRouteEast` | #### Security (AC-3) `SatelliteProvider.IntegrationTests/SecurityTests.cs` (new) wired into `Program.cs`: | Scenario | Test | |----------|------| | SEC-01 — SQL injection via coordinates | `Sec01_SqlInjectionViaCoordinates` — non-numeric `Latitude` rejected (400/422) | | SEC-02 — Path traversal in tile serving | `Sec02_PathTraversalInTileServing` — three traversal patterns all return non-200 | | SEC-03 — Oversized region request | `Sec03_OversizedRegionRequest` — `sizeMeters=1_000_000` rejected (400/422) | | SEC-04 — Malformed JSON | `Sec04_MalformedJson` — non-JSON body rejected (400/415/422) | #### Resource Limits | Scenario | Coverage | |----------|----------| | RL-01 — ZIP ≤ 50 MB | `ExtendedRouteTests.RunRouteWithTilesZipTest` new cap assertion | | RL-02 — Queue capacity 1000 | `appsettings.json` `QueueCapacity: 1000`; bounded behavior verified by `RegionRequestQueueTests` | | RL-03 — Concurrent download semaphore (4) | `appsettings.json` `MaxConcurrentDownloads: 4` | | RL-04 — Concurrent region processing (20) | `appsettings.json` `MaxConcurrentRegions: 20` | ## Files Changed ``` SatelliteProvider.IntegrationTests/ExtendedRouteTests.cs SatelliteProvider.IntegrationTests/SecurityTests.cs [new] SatelliteProvider.IntegrationTests/Program.cs SatelliteProvider.Tests/RegionRequestQueueTests.cs [new] scripts/run-performance-tests.sh _docs/02_tasks/todo/AZ-289_integration_route_maps.md → _docs/02_tasks/done/... _docs/02_tasks/todo/AZ-290_nonfunctional_tests.md → _docs/02_tasks/done/... _docs/03_implementation/reviews/batch_03_review.md [new] _docs/03_implementation/batch_03_report.md [new] ``` ## Test Results - Unit tests (Docker): **35 / 35 passed** (1.21 s). - Integration test project build: **0 errors, 0 warnings**. - Integration tests (full Compose runtime): deferred to Step 7 (Run Tests). - Performance script (live API): deferred to Step 15 (Performance) per autodev flow. ## Code Review `_docs/03_implementation/reviews/batch_03_review.md` — verdict: **PASS_WITH_WARNINGS**. - Findings: 2 Low (RS-04 spec wording drift, time-based test heuristic). No Critical or High. - Baseline delta: no new architecture findings; pre-existing High findings (F1, F2) remain resolved. ## Tracker Updates - AZ-289 → In Testing - AZ-290 → In Testing