Files
Oleksandr Bezdieniezhnykh c3a1ebc754
ci/woodpecker/push/02-build-push Pipeline failed
[AZ-838] SatelliteProviderRouteClient + seed_route.py CLI (E-AZ-835 C2)
Operator-side HTTP client + CLI that takes a RouteSpec from AZ-836
and onboards it via satellite-provider's POST /api/satellite/route:
pre-emptive AZ-809 validation, request submission, polling until
mapsReady, and POST /api/satellite/tiles/inventory verify.

Lives in c11_tile_manager (shared parent-suite HTTP/JWT plumbing,
shared BUILD_C11_TILE_MANAGER gate); error hierarchy split off
SatelliteProviderRouteError to keep the tile path and route path
independent. 30 unit tests + 1 RUN_E2E-gated integration test.

Pre-emptive validator tracks the actual AZ-809 server bounds
(points [2,500], zoom [0,22]) instead of the AZ-838 spec's narrower
client-only bounds; flagged as F1 in batch_107_cycle3_report.md
for user decision (accept-and-update-spec / revert-to-spec).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 13:29:45 +03:00

69 lines
2.3 KiB
Python

"""AZ-838 Route client integration test (AC-8, AC-10).
Gated on ``RUN_E2E=1`` AND ``SATELLITE_PROVIDER_URL`` AND
``SATELLITE_PROVIDER_API_KEY`` AND ``DERKACHI_TLOG`` per the AZ-838
spec. Without those, the test SKIPs with an explicit reason — same
pattern as AZ-404's ``RUN_REPLAY_E2E`` gate. The intent is that AC-8
and AC-10 have a concrete pytest entry point so they can be exercised
on the Jetson harness without re-discovering wiring.
The test is intentionally minimal: it verifies that when a real
``satellite-provider`` is reachable, a Derkachi tlog round-trips
through :class:`SatelliteProviderRouteClient.seed_route` and reports
``maps_ready=True`` with a non-zero ``tile_count``.
"""
from __future__ import annotations
import os
from pathlib import Path
import pytest
from gps_denied_onboard.components.c11_tile_manager.route_client import (
SatelliteProviderRouteClient,
)
from gps_denied_onboard.replay_input.tlog_route import extract_route_from_tlog
_RUN_E2E = os.getenv("RUN_E2E") == "1"
_SP_URL = os.getenv("SATELLITE_PROVIDER_URL")
_SP_JWT = os.getenv("SATELLITE_PROVIDER_API_KEY")
_TLS_INSECURE = os.getenv("SATELLITE_PROVIDER_TLS_INSECURE") == "1"
_DERKACHI_TLOG = os.getenv("DERKACHI_TLOG")
@pytest.mark.skipif(
not (_RUN_E2E and _SP_URL and _SP_JWT and _DERKACHI_TLOG),
reason=(
"AZ-838 AC-8/AC-10 require RUN_E2E=1 + SATELLITE_PROVIDER_URL + "
"SATELLITE_PROVIDER_API_KEY + DERKACHI_TLOG (path to derkachi.tlog) "
"— typically run on the Jetson e2e harness."
),
)
def test_seed_route_against_live_sp_with_derkachi_tlog() -> None:
# Arrange
tlog_path = Path(_DERKACHI_TLOG) # type: ignore[arg-type]
assert tlog_path.is_file(), f"derkachi tlog not found: {tlog_path}"
spec = extract_route_from_tlog(tlog_path, max_waypoints=10)
client = SatelliteProviderRouteClient(
base_url=_SP_URL, # type: ignore[arg-type]
jwt=_SP_JWT, # type: ignore[arg-type]
tls_insecure=_TLS_INSECURE,
poll_interval_s=5.0,
poll_max_attempts=24,
)
# Act
result = client.seed_route(
spec,
name=f"az838-derkachi-{tlog_path.stem}",
region_size_meters=500.0,
zoom_level=18,
)
# Assert
assert result.maps_ready is True
assert result.terminal_status == "completed"
assert result.tile_count > 0