mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-21 12:31:12 +00:00
702a0c0ff3
AZ-408 (3pt) — Replace AZ-406 injector scaffolds with concrete generators: - outlier.py: deterministic stride + far-away tile replacement; AC-2 ≥350m offset - blackout_spoof.py: paired video blackout + FC GPS spoof with ≤40ms alignment; AC-4 realistic fix_type/hdop; AC-NEW-8 200-500m inter-spoof deltas - multi_segment.py: ≥3 disjoint windows, ≥30s gaps, ≤25% coverage - fc_proxy.py: timed-splice runtime proxy with pre-activate RuntimeError guard - _common.py: derive_rng + tile-manifest reader + tmpfs helpers - injector_fixtures.py: pytest fixtures wired via runner conftest AZ-410 (3pt) — FT-P-02 cumulative drift between satellite anchors: - anchor_pair_detector.py: AC-1 detection, AC-2/3 pass-fraction, AC-4 monotonicity check, CSV evidence - test_ft_p_02_derkachi_drift.py: scenario gated on upstream helper NotImplementedError (frame_source_replay / fdr_reader / imu_replay) AZ-411 (2pt) — FT-P-03 + FT-P-14 schema + WGS84: - estimate_schema.py: AC-1 schema completeness, AC-2 source-label set containment, AC-3 WGS84 range + int32 1e-7 decode - test_ft_p_03_14_schema_wgs84.py: shared single-image-push scenario Tests: 248 unit tests pass (+91 vs batch 68). Reports: batch_69_report.md, batch_69_review.md (PASS), cumulative_review_batches_67-69_cycle1_report.md (PASS). Co-authored-by: Cursor <cursoragent@cursor.com>
115 lines
4.4 KiB
Python
115 lines
4.4 KiB
Python
"""Asserts the AZ-406 directory layout is present.
|
|
|
|
Every blackbox / fixture / Jetson task added later relies on these paths.
|
|
Catching a missing directory here is much faster than failing inside the
|
|
e2e-runner image build.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
E2E_ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"relative_path",
|
|
[
|
|
"README.md",
|
|
".gitignore",
|
|
"docker/docker-compose.test.yml",
|
|
"docker/docker-compose.tier2-bridge.yml",
|
|
"docker/secrets/mavlink_passkey",
|
|
"docker/run-tier1.sh",
|
|
"jetson/run-tier2.sh",
|
|
"jetson/tier2-on-jetson.sh",
|
|
"jetson/tier2.service",
|
|
"jetson/tegrastats_parser.py",
|
|
"jetson/jtop_parser.py",
|
|
"runner/Dockerfile",
|
|
"runner/requirements.txt",
|
|
"runner/pytest.ini",
|
|
"runner/conftest.py",
|
|
"runner/reporting/csv_reporter.py",
|
|
"runner/reporting/evidence_bundler.py",
|
|
"runner/reporting/nfr_recorder.py",
|
|
"runner/helpers/frame_source_replay.py",
|
|
"runner/helpers/imu_replay.py",
|
|
"runner/helpers/sitl_observer.py",
|
|
"runner/helpers/mavproxy_tlog_reader.py",
|
|
"runner/helpers/fdr_reader.py",
|
|
"runner/helpers/geo.py",
|
|
"runner/helpers/anchor_pair_detector.py",
|
|
"runner/helpers/estimate_schema.py",
|
|
"fixtures/mock-suite-sat/Dockerfile",
|
|
"fixtures/mock-suite-sat/app.py",
|
|
"fixtures/mock-suite-sat/requirements.txt",
|
|
"fixtures/tile-cache-builder/README.md",
|
|
"fixtures/tile-cache-builder/builder.py",
|
|
"fixtures/tile-cache-builder/Dockerfile",
|
|
"fixtures/tile-cache-builder/build.sh",
|
|
"fixtures/age-injector/README.md",
|
|
"fixtures/age-injector/age_injector.py",
|
|
"fixtures/age-injector/inject.sh",
|
|
"fixtures/injectors/outlier.py",
|
|
"fixtures/injectors/blackout_spoof.py",
|
|
"fixtures/injectors/multi_segment.py",
|
|
"fixtures/injectors/cold_boot.py",
|
|
"fixtures/injectors/_common.py",
|
|
"fixtures/injectors/fc_proxy.py",
|
|
"runner/helpers/injector_fixtures.py",
|
|
"fixtures/cold-boot/README.md",
|
|
"fixtures/cold-boot/cold_boot_fixture.json",
|
|
"fixtures/secrets/mavlink-test-passkey.txt",
|
|
"fixtures/security/generate_cve_jpeg.py",
|
|
"fixtures/security/cve-2025-53644.jpg",
|
|
"fixtures/security/README.md",
|
|
"tests/__init__.py",
|
|
"tests/conftest.py",
|
|
"tests/positive/__init__.py",
|
|
"tests/negative/__init__.py",
|
|
"tests/performance/__init__.py",
|
|
"tests/resilience/__init__.py",
|
|
"tests/security/__init__.py",
|
|
"tests/resource_limit/__init__.py",
|
|
"tests/positive/test_smoke.py",
|
|
"tests/positive/test_ft_p_02_derkachi_drift.py",
|
|
"tests/positive/test_ft_p_03_14_schema_wgs84.py",
|
|
],
|
|
)
|
|
def test_required_path_exists(relative_path: str) -> None:
|
|
"""Each path AZ-406 + AZ-407 + AZ-444 + AZ-445 commit to must exist on disk."""
|
|
assert (E2E_ROOT / relative_path).exists(), (
|
|
f"layout invariant broken: e2e/{relative_path} is missing"
|
|
)
|
|
|
|
|
|
def test_passkey_files_match() -> None:
|
|
"""Docker secret and runner-side passkey fixture must encode the same secret.
|
|
|
|
The docker-secret file is consumed by mavproxy as a raw 64-hex passkey
|
|
(no comments allowed in its body). The runner-side fixture file is the
|
|
AZ-407 AC-5 deliverable and ships with a ``# TEST ONLY...`` header
|
|
line so it self-documents during code review.
|
|
|
|
We therefore compare the FIRST 64-hex line of each file rather than
|
|
the raw bytes. The two files MUST encode the same 32-byte secret;
|
|
drift between them would mean a mavproxy run uses a different key
|
|
than the runner fixture states.
|
|
"""
|
|
|
|
# Arrange
|
|
docker_pk = (E2E_ROOT / "docker/secrets/mavlink_passkey").read_text().strip().splitlines()
|
|
runner_pk_lines = (E2E_ROOT / "fixtures/secrets/mavlink-test-passkey.txt").read_text().strip().splitlines()
|
|
runner_pk = [line for line in runner_pk_lines if not line.lstrip().startswith("#")]
|
|
|
|
# Assert
|
|
assert docker_pk and runner_pk, "passkey files must contain at least one non-comment line"
|
|
assert docker_pk[0] == runner_pk[0], (
|
|
"MAVLink test passkey secrets differ between docker secret and runner "
|
|
"fixture. They MUST encode the same 32-byte secret — see "
|
|
"e2e/fixtures/secrets/README.md."
|
|
)
|