mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-21 17:11:15 +00:00
bc04ba7f99
Step 12 (Test-Spec Sync): adds BT-27 for the AZ-796 9-rule validation surface and 12 cycle-7 AC rows + Coverage Summary update to traceability-matrix.md. Step 13 (Update Docs): module-layout + module docs for the new SatelliteProvider.Api/Validators namespace + GlobalExceptionHandler + updated TileInventory DTO; tests_unit + tests_integration document the new InventoryRequestValidatorTests (16 unit tests covering all 9 rules) + TileInventoryValidationTests (16 integration tests) + ProblemDetailsAssertions support; glossary entries for Validation Problem Details / FluentValidation / Unmapped Member Handling; system-flows F8 (Tile Inventory Bulk Lookup) expanded with deserializer + validator gates and a 13-row Validation Surface table; data_parameters § Tile Inventory documents the v2 input schema + constraints; ripple_log_cycle7 captures the doc-side ripple decisions. Step 14 (Security Audit): 5-phase audit ran; verdict PASS_WITH_WARNINGS (3 Low findings — D-AZ795-1 FluentValidation 12.0.0 -> 12.1.1 recommended bump, F-AZ795-1 JsonException.Message leak in 400 detail, F-AZ795-2 BadHttpRequestException.Message leak). No Critical / High; auth runs before validation (confirmed in Program.cs); two NuGet additions (FluentValidation 12.0.0 + .DependencyInjectionExtensions 12.0.0) both CVE-clean. Per-phase reports plus consolidated security_report_cycle7.md. Step 15 (Performance Test): docker compose stack used for perf run, scripts/run-performance-tests.sh exited 0 with 8/8 scenarios PASS (second consecutive clean exit-0); added PT-09 cycle-7 smoke probe (v2 z/x/y schema, 2500-tile all-miss batch) measuring min=27ms median=44ms p95=73ms max=86ms (13.7x under AZ-505 AC-4 1000ms budget). PT-07/08 improvements traced to the cycle-6 TLS handshake-overhead identification, not application-side change. Co-authored-by: Cursor <cursoragent@cursor.com>
45 lines
8.1 KiB
Markdown
45 lines
8.1 KiB
Markdown
# Module: Tests/SatelliteProvider.Tests
|
||
|
||
## Purpose
|
||
Unit test project for component-internal logic. Original AZ-2/AZ-3 era had only a placeholder dummy; the suite has since grown across the AZ-285..AZ-380 baseline + cycle 1 (AZ-484) + cycle 2 (AZ-487, AZ-488) tracks. The "dummy test only" note in older revisions of this file is obsolete — the project now hosts the full unit suite executed by `scripts/run-tests.sh --unit-only` and CI's `01-test.yml`.
|
||
|
||
## Public Interface (test classes)
|
||
|
||
Existing baseline (pre-cycle-2) test classes cover `TileService`, `RegionService`, `RouteService`, geo math, repositories, validators, idempotency, and migration helpers — not enumerated exhaustively here. Cycle-2 additions:
|
||
|
||
### AZ-487 + AZ-494 — JWT validation baseline + iss/aud
|
||
- `Authentication/AuthenticationServiceCollectionExtensionsTests` — covers `AddSatelliteJwt` registration + `TokenValidationParameters` shape across both AZs:
|
||
- AZ-487 baseline: `AddSatelliteJwt_RegistersJwtBearerScheme`, `AddSatelliteJwt_ThrowsOnMissingSecret`, `AddSatelliteJwt_ThrowsOnShortSecret`.
|
||
- AZ-494 extension: `AddSatelliteJwt_ThrowsOnMissingIssuer`, `_ThrowsOnEmptyIssuer`, `_ThrowsOnMissingAudience`, `_ThrowsOnEmptyAudience`, plus updated `_ConfiguresTokenValidationParameters_AsPerContract` and `_PrefersEnvironmentVariableOverConfiguration` asserting `ValidateIssuer = true` + `ValidIssuer` + `ValidateAudience = true` + `ValidAudience`.
|
||
- `Authentication/JwtTokenFactoryTests` — `Create_ProducesTokenValidatedByMatchingParameters`, `CreateExpired_TokenFailsValidationWithLifetimeException`, `Create_WithExtraClaims_PropagatesClaimsThroughValidation`, `TamperSignature_TokenFailsValidationWithSignatureException`. The factory itself lives in `SatelliteProvider.TestSupport` after AZ-491 (single source of truth); this project consumes it via `ProjectReference`.
|
||
|
||
### AZ-488 — UAV tile upload
|
||
- `UavTileQualityGateTests` — one happy path + ≥ 1 reject path per rule (Rule 1 INVALID_FORMAT × 2, Rule 2 SIZE_OUT_OF_BAND × 2, Rule 3 WRONG_DIMENSIONS × 1, Rule 4 CAPTURED_AT_FUTURE / _TOO_OLD × 2, Rule 5 IMAGE_TOO_UNIFORM × 1) + rule-ordering determinism. Uses a `FixedTimeProvider` for Rule-4 isolation and `UavTileImageFactory` for deterministic JPEG fixtures.
|
||
- `UavTileUploadHandlerTests` — end-to-end with a mocked `ITileRepository`. Cycle-2 baseline: 1-item happy path, 3-item mixed batch (file written + `InsertAsync` called only for accepted), per-source UPSERT pass-through. AZ-503 additions: `HandleAsync_TwoFlightsSameCell_ProduceDistinctIdsAndPathsButSameLocationHash` (multi-flight coexistence with shared `location_hash`); `HandleAsync_IdenticalUpload_ProducesIdenticalIdAndDeterministicContentSha` (idempotent re-insert preserves deterministic `id` + `content_sha256`).
|
||
- `Authentication/PermissionsRequirementTests` — `PermissionsAuthorizationHandler` correctly accepts a `permissions` claim shaped as a single string OR as a JSON array, rejects when the requested permission is absent, and short-circuits when the principal has no `permissions` claim at all.
|
||
- `TestUtilities/UavTileImageFactory` — programmatic JPEG factories used by the gate + handler tests: `CreateValidJpeg(width, height, seed)`, `CreateUniformJpeg`, `CreatePng` (for Rule 1 negative path).
|
||
|
||
### AZ-503 — Tile identity foundation
|
||
- `Uuidv5Tests` — pure-C# UUIDv5 generator parity tests. `Create_MatchesPythonReferenceVectors_AC1` pins 10 reference vectors generated by Python's `uuid.uuid5(TILE_NAMESPACE, name)`; `Create_IsDeterministic` asserts repeated runs return the same `Guid`; `Create_SetsVersionAndVariantBits` asserts the version nibble is `5` and the variant top-2-bits are `10` (RFC 9562 §5.5).
|
||
- `UavTileFilePathTests` (rewritten for AZ-503 from the cycle-2 placeholder) — covers `BuildUavTileFilePath(Guid? flightId, int z, int x, int y)` across three cases: `BuildUavTileFilePath_AnonymousFlight_UsesNoneSegment` (null `flightId` → literal `none` segment), `BuildUavTileFilePath_PerFlight_UsesFlightIdDirectory` (per-flight segment), `BuildUavTileFilePath_DifferentFlights_ProduceDifferentPaths` (path-distinctness across flights at the same cell). Integer-typed coordinates and the `Guid? flightId` parameter together still preclude string-injection path traversal.
|
||
|
||
### AZ-795 + AZ-796 — strict inventory validation (cycle 7)
|
||
- `Validators/InventoryRequestValidatorTests` (added cycle 7 — AZ-796) — 16 tests against `InventoryRequestValidator` + `TileCoordValidator` in isolation via FluentValidation's `TestValidate(...)` test helper. Covers every `RuleFor(...)`: `Validate_TilesPopulated_LocationHashesNull_Passes`, `Validate_LocationHashesPopulated_TilesNull_Passes`, `Validate_BothPopulated_FailsXorRule`, `Validate_NeitherPopulated_FailsXorRule`, `Validate_BothEmpty_FailsXorRule`, `Validate_TilesAtCap_Passes`, `Validate_TilesOverCap_FailsCapRule`, `Validate_LocationHashesOverCap_FailsCapRule`, `Validate_TileZoomOutOfRange_FailsRangeRule` (`[Theory]` with z ∈ {-1, 23, 100}), `Validate_TileZoomInRange_PassesRangeRule` (`[Theory]` with z ∈ {0, 18, 22}), `Validate_TileXNegative_FailsRangeRule`, `Validate_TileXAtUpperBound_FailsRangeRule`, `Validate_TileYNegative_FailsRangeRule`, `Validate_TileYAtUpperBound_FailsRangeRule`, `Validate_AxesAtMaxForZoom_Passes`.
|
||
- `TestSupport/ValidatorTestModuleInitializer.cs` (added cycle 7 — AZ-795) — `[ModuleInitializer]` that calls `GlobalValidatorConfig.ApplyOnce()` at test-assembly load time. Ensures unit tests see the same camelCase property-name resolution that `Program.cs` configures for the running API, so validator error keys (e.g., `tiles[0].z`) match the runtime contract per `error-shape.md` v1.0.0 Inv-4 without forcing every test to re-run the setup.
|
||
|
||
## Internal Logic
|
||
- Tests follow Arrange / Act / Assert. Time-dependent paths inject a `FixedTimeProvider` (cycle-2 addition) so Rule 4 has deterministic age windows.
|
||
- `JwtSecurityTokenHandler.MapInboundClaims = false` is set explicitly in JWT tests so claims read by their original names (`sub`, `permissions`, …) rather than the framework-remapped names.
|
||
- Cycle 7 also added validator-isolated assertions via FluentValidation's `TestValidate(...)` helper (no HTTP, no DI container) — the matching end-to-end assertions live in `SatelliteProvider.IntegrationTests/TileInventoryValidationTests.cs`.
|
||
|
||
## Dependencies
|
||
- Project references: `SatelliteProvider.Services.TileDownloader`, `SatelliteProvider.Services.RegionProcessing`, `SatelliteProvider.Services.RouteManagement`, `SatelliteProvider.Common`, `SatelliteProvider.DataAccess`, `SatelliteProvider.Api` (for the Authentication tests — added in AZ-487), `SatelliteProvider.TestSupport` (added by AZ-491; provides the canonical `JwtTokenFactory` consumed by both this project and `SatelliteProvider.IntegrationTests`).
|
||
- NuGet: xUnit (2.5.3), Moq (4.20.72), FluentAssertions (8.8.0), coverlet.collector (6.0.0), Microsoft.NET.Test.Sdk (17.8.0), Microsoft.Extensions.* (Caching.Memory, Configuration, DI, Logging, Options, Http — all bumped from 9.0.10 → 10.0.7 by AZ-500 as a coordinated cycle-4 move), `Microsoft.AspNetCore.Authentication.JwtBearer` 10.0.7 (consumed transitively via the `ProjectReference` to `SatelliteProvider.Api`; AZ-487 added the dependency at 8.0.21, AZ-496 bumped it to 8.0.25, AZ-500 bumped it to 10.0.7), `SixLabors.ImageSharp` 3.1.11 (added by AZ-488 for the gate tests), `FluentValidation` + `FluentValidation.TestHelper` 12.0.0 (added cycle 7 — AZ-795; the test helper drives the `TestValidate(...)` assertions used by `InventoryRequestValidatorTests`).
|
||
- `appsettings.json` copied to output (used by Authentication tests for the `Jwt` section binding scenario).
|
||
|
||
## Consumers
|
||
- CI pipeline (`01-test.yml`) and `scripts/run-tests.sh --unit-only` run `dotnet test` against this project.
|
||
|
||
## Tests
|
||
This IS the test module. Cycle-2 added ~25 unit tests on top of the existing baseline; cycle-5 (AZ-503) added 6 more (3 in `Uuidv5Tests`, 3 in `UavTileFilePathTests`) plus 2 new methods in `UavTileUploadHandlerTests`. Cycle 7 (AZ-795 + AZ-796) added 16 more in `InventoryRequestValidatorTests` covering every `RuleFor(...)` in the cycle's new validators. The full project executes in seconds (no external services required). Cycle 7 Step 11 reported the unit suite at 311 tests, all green.
|