Files
missions/_docs/02_document/tests/test-data.md
T
Oleksandr Bezdieniezhnykh 7025f4d075 refactor: enhance JWT authentication and CORS configuration
Updated JWT authentication to use configuration values instead of hardcoded secrets, improving security and flexibility. Enhanced CORS policy to conditionally allow origins based on configuration settings, with logging for permissive defaults. Updated README to reflect project renaming and clarify service context.
2026-05-14 19:48:25 +03:00

11 KiB
Raw Blame History

Test Data Management

Status: produced by autodev /test-spec Phase 2 (2026-05-14). Naming: post-rename target. Today's API surface is /aircrafts//flights; tests will be RED until B5B8 land. Fixture column names in expected_results/fixture_cascade_*.sql use post-rename names; pre-rename code path runs the same DDL via the Azaion.Flights.Database.DatabaseMigrator against the test DB before the fixture INSERT — the test orchestrator invokes the service container's startup, then runs fixture SQL via the side channel.

Seed Data Sets

Data Set Description Used by Tests How Loaded Cleanup
seed_empty Schema migrated, no rows in any table bootstrap, unauth, 404 scenarios docker compose down -v && docker compose up -d then wait for missions startup (which runs the migrator) down -v between scenarios
seed_one_default_vehicle Schema + 1 row in vehicles with is_default=true AC-1.2 (default-clear), AC-1.3 (TOCTOU race), AC-1.4 setDefault, AC-2.1 mission create side-channel SQL INSERT INTO vehicles ... after seed_empty Within scenario class via per-class IClassFixture<DbResetFixture>
seed_3_vehicles_2_default 3 rows in vehicles, 2 with is_default=true (illegal under AC-1.2) AC-1.5 list, AC-1.6 filter (with deterministic ordering) side-channel SQL per-class fixture
seed_25_missions 25 missions rows (5 in January 2026, 20 in February 2026) referencing one vehicle AC-2.3, AC-2.4, AC-2.5 pagination + date filter side-channel SQL with deterministic UUIDs per-class fixture
fixture_cascade_F3 One mission with full dependency chain: 1 mission → 2 waypoints → 2 media → 2 annotations → 2 detection rows + 3 map_objects AC-3.1, AC-3.3, AC-3.4, AC-10.2 expected_results/fixture_cascade_F3.sql (referenced from results_report.md) — applied via side-channel after seed_empty down -v after each scenario in this class
fixture_cascade_F4 One mission with one waypoint that has 1 media → 1 annotation → 1 detection chain; sibling waypoint with NO chain (must remain after delete) AC-4.5, AC-4.6 expected_results/fixture_cascade_F4.sql down -v after each scenario in this class
seed_5_waypoints_unordered 5 waypoints with order_num [3, 1, 2, 5, 4] under one mission AC-4.3 unpaginated ordering side-channel SQL per-class fixture
seed_legacy_gps_tables Pre-B7 schema: vehicles, missions, waypoints PLUS orthophotos and gps_corrections populated with 1 row each AC-3.5 (post-B7 absence), AC-6.5 (one-shot drop), AC-10.5 (legacy device migration) side-channel SQL CREATE TABLE + INSERT in a fresh seed_empty down -v between scenarios

Data Isolation Strategy

Three isolation tiers, by scenario type:

  • Class-scoped DB reset (IClassFixture<DbResetFixture>): for scenarios that share the same seed within a test class but must not leak to other classes. Used for AC-1, AC-2, AC-4 read paths.
  • Scenario-scoped container restart (docker compose down -v && up -d): for scenarios that assert startup-time behavior or migrator side-effects. Used for AC-6.3, AC-6.4 (idempotency), AC-6.5 (legacy drop), AC-6.6 (idempotent re-run), AC-6.7 (DB unreachable), AC-5.7 (JWT_SECRET rotation).
  • Per-test transaction roll-back is NOT used — the system under test is a separate process and its DataConnection is not in the test transaction.

Input Data Mapping

Input Data File Source Location Description Covers Scenarios
data_parameters.md § 7 (HTTP table) _docs/00_problem/input_data/data_parameters.md Documentation of every endpoint + DTO shape; the consumer constructs requests from these shapes every FT-* and NFT-* scenario
fixture_cascade_F3.sql _docs/00_problem/input_data/expected_results/fixture_cascade_F3.sql Cascade chain seed for AC-3 FT-P-12, FT-N-04, NFT-RES-01, NFT-PERF-01
fixture_cascade_F4.sql _docs/00_problem/input_data/expected_results/fixture_cascade_F4.sql Cascade chain seed for AC-4 FT-P-18, NFT-RES-02
cascade_F3_walk.json _docs/00_problem/input_data/expected_results/cascade_F3_walk.json Per-table delete-count expectations FT-P-12
cascade_F4_walk.json _docs/00_problem/input_data/expected_results/cascade_F4_walk.json Per-table delete-count expectations FT-P-18

Expected Results Mapping

Test Scenario ID Input Data Expected Result Comparison Method Tolerance Expected Result Source
FT-P-01 POST /vehicles body per data_parameters.md § 2.1 201 Created, Vehicle body, DB row exists exact + db_query N/A results_report.md AC-1 row 1.1
FT-P-02 POST /vehicles body with IsDefault:true against seed_one_default_vehicle 201; new row default; prior row not default; default count == 1 exact + db_query N/A AC-1 row 1.2
FT-P-03 POST /vehicles/{id}/setDefault {IsDefault:true} 200; default count == 1; only target row default exact + db_query N/A AC-1 row 1.4
FT-P-04 GET /vehicles against seed_3_vehicles_2_default 200; body length == 3; PascalCase keys exact + schema N/A AC-1 row 1.5
FT-P-05 GET /vehicles?name=BR&isDefault=true 200; body length == 1; body[0].Name == "BR-01" exact N/A AC-1 row 1.6
FT-N-01 GET /vehicles?name=br (case mismatch) 200; body length == 0 exact N/A AC-1 row 1.7
FT-N-02 GET /vehicles/{random uuid} 404; envelope { statusCode:404, message } exact + schema N/A AC-1 row 1.8
FT-N-03 DELETE /vehicles/{id} against vehicle referenced by ≥1 mission 409; row not deleted exact + db_query N/A AC-1 row 1.9
FT-P-06 DELETE /vehicles/{id} against vehicle with 0 missions 204; row deleted exact + db_query N/A AC-1 row 1.10
FT-P-07 POST /missions body per data_parameters.md § 2.2 201; CreatedDate ± 5s of now exact + numeric_tolerance ±5s AC-2 row 2.1
FT-N-04 POST /missions {VehicleId:<random>} 400 (today, divergent from spec's 404) exact N/A AC-2 row 2.2
FT-P-08 GET /missions against seed_25_missions 200; PaginatedResponse<Mission>; Page=1, PageSize=20, TotalCount=25, Items.length=20 exact + schema N/A AC-2 row 2.3
FT-P-09 GET /missions?page=2&pageSize=20 Page=2, Items.length=5 exact N/A AC-2 row 2.4
FT-P-10 GET /missions?fromDate=...&toDate=... TotalCount=3 against the 5-row seed exact N/A AC-2 row 2.5
FT-P-11 PUT /missions/{id} {Name, VehicleId:null} 200; Name updated, VehicleId preserved exact N/A AC-2 row 2.7
FT-N-05 GET /missions/{random} 404 exact N/A AC-2 row 2.6
FT-P-12 DELETE /missions/{id} against fixture_cascade_F3 204; per-table counts == 0 per cascade_F3_walk.json exact + db_query + file_reference N/A AC-3 row 3.1
FT-N-06 DELETE /missions/{random} 404; no DELETE issued against dependency tables (instrument SQL log) exact + log_assertion N/A AC-3 row 3.2
FT-P-13 GET /missions/{id}/waypoints against seed_5_waypoints_unordered 200; ordered OrderNum [1..5] ASC exact N/A AC-4 row 4.2
FT-N-07 GET /missions/{random}/waypoints 404 exact N/A AC-4 row 4.1
FT-P-14 POST /missions/{id}/waypoints body per data_parameters.md § 2.3 with non-null GeoPoint 201; Lat,Lon echoed; Mgrs == null (today, divergent — see §2.3 note) exact N/A AC-4 row 4.3
FT-P-15 PUT /missions/{id}/waypoints/{wpId} body resetting Height to 0 200; Height==0 (full overwrite) exact N/A AC-4 row 4.4
FT-P-18 DELETE /missions/{id}/waypoints/{wpId} against fixture_cascade_F4 204; only target waypoint's chain deleted; sibling chain intact exact + db_query + file_reference N/A AC-4 row 4.5
FT-P-16 GET /health no auth 200 { "status": "healthy" } exact N/A AC-7 row 7.1
FT-P-17 GET /health with PG stopped 200 { "status": "healthy" } (no DB ping) exact N/A AC-7 row 7.2

NFT-* mappings (perf, resilience, security, resource-limit) are inline in the respective test files.

External Dependency Mocks

External Service Mock/Stub How Provided Behavior
admin (JWT issuer) In-process token mint System.IdentityModel.Tokens.Jwt in the consumer using JWT_SECRET=test-secret-32-chars-min!!!!!!!!!, HS256 Mints valid / expired / wrong-secret / claim-missing / claim-typo tokens on demand for AC-5 + AC-9 scenarios
annotations table owner DB-only stub Side-channel CREATE TABLE annotations (id text PRIMARY KEY, media_id text) then INSERT Provides rows the cascade walk reads + deletes; no service running
detection table owner DB-only stub Side-channel CREATE TABLE detection (id uuid PRIMARY KEY, annotation_id text) + INSERT Same as above
media table owner DB-only stub Side-channel CREATE TABLE media (id text PRIMARY KEY, waypoint_id uuid) + INSERT Same
autopilot writer of map_objects DB-only stub + race injector Side-channel; for AC-3.4 race, a parallel goroutine-equivalent inserts a map_objects row immediately after the service's first SELECT (instrumented via test-only proxy) One scenario only
flight-gate, Watchtower, suite reverse proxy, suite UI NOT mocked n/a Out of scope for service-level e2e

Data Validation Rules

Data Type Validation today (per AC-* notes) Invalid Examples Expected System Behavior
Vehicle.Name NONE (per data_parameters.md § 2.1 note) "" (empty) accepted; row created; tests assert this is the current state, not the desirable one (carry-forward)
Vehicle.BatteryCapacity NONE -1 accepted; carry-forward
Vehicle.Type NONE (any int accepted) 99 accepted; carry-forward
Mission.Page / PageSize NONE -1, 999999 accepted by binding; carry-forward
Waypoint.GeoPoint NONE; all-null accepted {Lat:null, Lon:null, Mgrs:null} accepted (OrderNum + Height still required-by-shape)
JWT lifetime ValidateLifetime=true with 1-min skew exp = now-2min 401
JWT signature HS256 + shared secret wrong secret / tampered payload 401
JWT claim permissions exact string match "FL" "fl", "ADMIN", missing 403
Authorization header required on all /vehicles/*, /missions/* absent 401
DATABASE_URL shape postgresql://... URL OR raw Npgsql connection string unparseable process exits with error before HTTP server binds