Files
satellite-provider/_docs/02_document/modules/tests_integration.md
T
Oleksandr Bezdieniezhnykh 080441db5d
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful
[AZ-492] Cycle 3 batch 4: perf harness PT-07 + PT-08 + JWT-attach
Drains all three deferred perf-harness items in one batch:
- PT-01..PT-06 now carry Authorization: Bearer minted via the canonical
  SatelliteProvider.TestSupport.JwtTokenFactory (AZ-491) — no third copy
  of JWT logic in the shell.
- PT-07 implemented as cold + warm dual-pass distribution (N=20 each),
  reports p50/p95 for both passes and fails if warm p95 >= cold p95.
- PT-08 implemented as 20-batch upload distribution with batch p95 gated
  at the AZ-488 2000 ms target; per-item gate cost reported as derived
  proxy (batch_p95 / batch_size).

New SatelliteProvider.IntegrationTests/PerfBootstrap.cs adds two CLI
short-circuit subcommands (--mint-only and --gen-uav-fixture <path>)
invoked by the shell so the perf script never inlines the JWT or
JPEG-fixture logic. The dispatch sits at the top of Program.cs Main
and runs before any HTTP / DB / readiness setup.

performance-tests.md PT-07 + PT-08 flip from Deferred to Implemented.
traceability-matrix.md PT-07 + PT-08 rows move from recorded to covered
(PT-08 partial due to per-item proxy — flagged Low in batch-4 review).
_docs/_process_leftovers/2026-05-11_perf-pt07-harness.md deleted; the
leftovers directory is now empty.

Closes cycle-2 retro Action 2; LESSONS.md [process] rule about Deferred
NFRs remains in force as a guardrail.

Also includes the previously-uncommitted cumulative review report for
cycle-3 batches 01-03 (generated at the end of batch 3 but not staged).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 01:52:25 +03:00

81 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Module: Tests/SatelliteProvider.IntegrationTests
## Purpose
Console application that runs end-to-end integration tests against a live API instance. Designed to run in Docker alongside the API and PostgreSQL containers.
## Public Interface
### Test Classes
- `TileTests` — tile download via lat/lon endpoint
- `RegionTests` — region request → polling → completion flow
- `BasicRouteTests` — route creation with intermediate points
- `ComplexRouteTests` — routes with geofencing
- `ExtendedRouteTests` — routes with `requestMaps: true` and tile ZIP creation
- `MigrationTests` — direct PostgreSQL schema/index validation (no HTTP). AZ-484 cycle added: `NewUniqueConstraintIncludesSourceColumn_AZ484_AC1`, `BackfillUpdateAssignsGoogleMapsAndCapturedAt_AZ484_AC4`, `MultiSourceInsertCoexistsUnderNewIndex_AZ484_AC1`, `MostRecentAcrossSourcesSelection_AZ484_AC2`, `SameSourceUpsertReplacesPreviousRow_AZ484_AC3` (latter four use temp tables to keep production data untouched).
- `JwtIntegrationTests` (added by AZ-487, cycle 2; helpers consolidated by AZ-491 cycle 3) — `AnonymousRequest_To_AnyEndpoint_Returns401`, `ExpiredToken_Returns401`, `InvalidSignature_Returns401`, `ValidToken_Returns200_OnHealthyEndpoint`, `SwaggerDocument_AdvertisesBearerSecurityScheme`. HS256 token minting lives in the shared `SatelliteProvider.TestSupport.JwtTokenFactory` (consumed via `ProjectReference`); runner-specific concerns (`JwtTestHelpers.ResolveSecretOrThrow`, `AttachDefaultAuthorization`, `DefaultSubject = "integration-tests"`) remain in this project. The test runner sets `JWT_SECRET` on the API container and attaches a Bearer token to every existing test's HTTP requests so the pre-cycle-2 suite continues to pass.
- `UavUploadTests` (added by AZ-488, cycle 2; coordinate-counter promoted to defense-in-depth by AZ-493 cycle 3) — `HappyPathSingleItem_PersistsRow`, `MixedBatch_ReturnsPerItemResults`, `MultiSourceCoexistence_AZ484_Cycle2`, `SameSourceUpsert_AZ484_Cycle2`, `NoToken_Returns401`, `ValidTokenWithoutGpsPermission_Returns403`, `OversizedBatch_Returns400`. The wall-clock-seeded `_coordinateCounter` is retained as a belt-and-suspenders safeguard alongside the AZ-493 startup DB-reset (below) — if a developer runs with `--keep-state`, or the DB-reset path is skipped for any reason, the wall-clock seed still spreads coordinates across runs so the per-source unique index does not collide.
- `StubAndErrorContractTests` (existing) — updated in cycle 2 to drop the legacy `StubUpload_Returns501` expectation since AZ-488 implemented the endpoint.
### Supporting Classes
- `Models.cs` — HTTP response DTOs for deserialization
- `RouteTestHelpers.cs` — shared utilities (wait-for-completion polling, geofence polygon builders, test data)
- `Program.cs` — test runner entry point (handles `--smoke` / `--full` mode selection, `--keep-state` opt-out flag, default-token issuance via `JwtTokenFactory`, the AZ-493 DB-reset hook, and the AZ-492 `--mint-only` / `--gen-uav-fixture` perf-bootstrap subcommands that short-circuit before any HTTP / DB setup)
- `JwtTestHelpers.cs` — runner-side JWT concerns (`ResolveSecretOrThrow` reads the `JWT_SECRET` env var with size validation; `AttachDefaultAuthorization` puts a Bearer token on the shared `HttpClient`; `DefaultSubject = "integration-tests"` is the canonical runner subject value). Token *minting* lives in the shared `SatelliteProvider.TestSupport.JwtTokenFactory` (AZ-491) — runner-side concerns deliberately stay here.
- `IntegrationTestDatabaseReset.cs` (AZ-493) — instance class with a single `EnsureCleanStateAsync()` method that truncates the integration-test target tables in FK-safe order. Guarded via `SatelliteProvider.TestSupport.IntegrationTestResetGuard` (env + Host allowlist) so it cannot run against a non-test database.
- `PerfBootstrap.cs` (AZ-492) — static helpers for the perf harness bootstrap subcommands. `MintToken()` mints a 4-hour HS256 token with subject `perf-tests` and a `permissions: GPS` claim via the canonical `SatelliteProvider.TestSupport.JwtTokenFactory.Create`; `GenerateUavFixture(args)` writes a 256×256 random-noise JPEG via `SixLabors.ImageSharp` to the path passed on the CLI. Invoked from `scripts/run-performance-tests.sh` via `dotnet <SatelliteProvider.IntegrationTests.dll> --mint-only` and `--gen-uav-fixture <path>`.
## Internal Logic
- Makes HTTP calls to the API at `API_URL` environment variable (default: `http://api:8080`)
- Tests are methods called sequentially from `Program.cs` (not xUnit — plain console app)
- Poll-based waiting for async operations (region/route completion)
- Validates response structure, status transitions, file creation
## Dependencies
- `ProjectReference` to `SatelliteProvider.TestSupport` (added by AZ-491; provides `JwtTokenFactory`. Added by AZ-493; provides `IntegrationTestResetGuard`).
- Communicates with the API exclusively via HTTP for end-to-end tests; communicates with PostgreSQL directly only via the dedicated DB-reset hook + the existing `MigrationTests` schema assertions.
- NuGet: `Npgsql` 9.0.2 (Postgres client for DB-reset + MigrationTests), `SixLabors.ImageSharp` 3.1.11 (UAV fixture image generation).
## Consumers
- `docker-compose.tests.yml` — runs as a container that depends on the API service
## Configuration
- `API_URL` environment variable (set in docker-compose.tests.yml to `http://api:8080`)
- `INTEGRATION_TESTS_MODE``smoke` or `full` (default `full`). Drives `TestRunMode.Smoke`.
- `INTEGRATION_KEEP_STATE` — set to `1` or `true` (or pass `--keep-state` to `Program.cs` / `scripts/run-tests.sh`) to skip the AZ-493 DB-reset hook. Useful for debugging a failed run.
- `ASPNETCORE_ENVIRONMENT=Testing` — guard for the DB-reset hook. The reset refuses to run unless this is set (see Reliability § Test isolation below).
- `JWT_SECRET` — shared HMAC secret with the API container; must be ≥ 32 bytes (UTF-8).
- `DB_CONNECTION_STRING` — Npgsql connection string; the reset hook additionally requires the Host to be in the allowed-host list (`postgres`, `localhost`, `127.0.0.1`).
## Reliability
### Test isolation (AZ-493)
`Program.cs` runs `IntegrationTestDatabaseReset.EnsureCleanStateAsync()` at startup, before any test class executes. The hook truncates `route_regions`, `route_points`, `routes`, `regions`, `tiles` (in that FK-safe order, with `RESTART IDENTITY CASCADE`) so each run starts from a known empty state. The Postgres named volume in `docker-compose.yml` is intentionally persisted across `docker-compose down` cycles for fast iteration; the AZ-493 reset hook is what gives back per-run isolation in spite of that.
Two guards protect against accidental truncate against a non-test database:
1. `ASPNETCORE_ENVIRONMENT` MUST equal `Testing` (case-insensitive). Set by `docker-compose.tests.yml`; absent in production / dev.
2. `DB_CONNECTION_STRING` Host MUST be one of `postgres`, `localhost`, `127.0.0.1`. Set by `docker-compose.tests.yml` and developer machines; a remote-host connection string is rejected even with the env guard satisfied.
Both guards are pure-string checks in `SatelliteProvider.TestSupport.IntegrationTestResetGuard` — unit-tested in `SatelliteProvider.Tests/TestSupport/IntegrationTestResetGuardTests.cs`. Failure of either guard surfaces a clear `InvalidOperationException` and exits the runner with code 1.
To debug leftover state from a failed run, opt out of the reset:
- CLI: `./scripts/run-tests.sh --full --keep-state`
- Direct: `INTEGRATION_KEEP_STATE=1 docker compose ... up`
- In the runner Main: `dotnet run --project SatelliteProvider.IntegrationTests -- --keep-state`
### Adding new tables
If a new task adds a table that integration tests insert into AND that table participates in foreign-key relationships with `tiles` / `regions` / `routes`, update `IntegrationTestDatabaseReset.TruncateOrder` to include the new table in FK-safe order. The current order assumes the AZ-484 + AZ-488 schema; future migrations that introduce new FK chains need a corresponding order revision. The `CASCADE` clause is a safety net but is not a substitute for an explicit order — the order is the audit trail for "what does an integration-test runner see at startup".
## External Integrations
- HTTP to the SatelliteProvider API
- Reads output files from mounted `./ready/` and `./tiles/` volumes
## Security
None.
## Tests
This IS the integration test suite.