feat(simulation): qualify real S1B provider lifecycle

This commit is contained in:
DCCONSTRUCTIONS
2026-07-24 18:26:43 +03:00
parent e1809ac9e1
commit 01ec12263a
7 changed files with 813 additions and 6 deletions
+114
View File
@@ -22,12 +22,16 @@ from k1link.simulation import (
RunState,
S0WorkerGuard,
SimulationApplicationService,
StockRoverTargetPaths,
WorkerAdmissionError,
WorkerStartResult,
WorkerStopResult,
load_stock_rover_lifecycle_profile,
stock_rover_process_specs,
)
PROFILE = Path(__file__).resolve().parents[1] / "simulation/s0/qualification-profile.yaml"
S1B_PROFILE = Path(__file__).resolve().parents[1] / "simulation/s1/stock-rover-lifecycle.yaml"
SHA_A = "a" * 64
SHA_B = "b" * 64
@@ -336,6 +340,116 @@ def test_process_supervisor_rolls_back_partial_start(tmp_path: Path) -> None:
assert supervisor.residue() == ()
@pytest.mark.skipif(os.name != "posix", reason="target supervisor is POSIX-only")
def test_process_supervisor_waits_for_all_declared_ready_markers(tmp_path: Path) -> None:
child = (
"import signal,time;"
"signal.signal(signal.SIGINT,lambda *_:exit(0));"
"print('provider booting',flush=True);"
"time.sleep(0.05);"
"print('transport connected',flush=True);"
"time.sleep(60)"
)
supervisor = PosixProcessSupervisor(tmp_path / "runtime")
records = supervisor.start(
"run-ready-001",
(
ProcessSpec(
process_id="ready-provider",
argv=(sys.executable, "-c", child),
start_order=1,
shutdown_order=1,
ready_log_patterns=("provider booting", "transport connected"),
health_timeout_seconds=1,
health_poll_interval_seconds=0.01,
),
),
)
assert tuple(record.process_id for record in records) == ("ready-provider",)
assert supervisor.stop().residue_process_ids == ()
@pytest.mark.skipif(os.name != "posix", reason="target supervisor is POSIX-only")
def test_process_supervisor_readiness_timeout_rolls_back_without_residue(
tmp_path: Path,
) -> None:
supervisor = PosixProcessSupervisor(tmp_path / "runtime")
with pytest.raises(ProcessSupervisorError, match="missing markers: never-ready"):
supervisor.start(
"run-ready-timeout-001",
(
ProcessSpec(
process_id="not-ready",
argv=(sys.executable, "-c", "import time;time.sleep(60)"),
start_order=1,
shutdown_order=1,
ready_log_patterns=("never-ready",),
health_timeout_seconds=0.05,
health_poll_interval_seconds=0.01,
),
),
)
assert supervisor.residue() == ()
@pytest.mark.skipif(os.name != "posix", reason="target supervisor is POSIX-only")
def test_process_supervisor_rejects_exit_before_readiness(tmp_path: Path) -> None:
supervisor = PosixProcessSupervisor(tmp_path / "runtime")
with pytest.raises(ProcessSupervisorError, match="exited before readiness"):
supervisor.start(
"run-ready-exit-001",
(
ProcessSpec(
process_id="early-exit",
argv=(sys.executable, "-c", "raise SystemExit(7)"),
start_order=1,
shutdown_order=1,
ready_log_patterns=("never-ready",),
health_timeout_seconds=1,
health_poll_interval_seconds=0.01,
),
),
)
assert supervisor.residue() == ()
def test_stock_rover_profile_builds_exact_reviewed_provider_graph() -> None:
profile = load_stock_rover_lifecycle_profile(S1B_PROFILE)
paths = StockRoverTargetPaths.from_d_root(Path("/mnt/d/NDC_MISSIONCORE/simulation"))
specs = stock_rover_process_specs(paths, profile)
assert profile.profile_id == "s1b-stock-rover-lifecycle-v1"
assert tuple(spec.process_id for spec in specs) == (
"micro-xrce-dds-agent",
"px4-gazebo-stock-rover",
)
assert specs[0].ready_log_patterns == ("running...",)
assert specs[1].argv[-2:] == ("px4_sitl", "gz_rover_ackermann")
assert specs[1].ready_log_patterns[-1] == "Running, connected"
assert dict(specs[1].environment) == {
"HEADLESS": "1",
"PX4_SIM_SPEED_FACTOR": "1",
}
def test_ready_patterns_require_a_positive_timeout() -> None:
with pytest.raises(ValueError, match="positive health timeout"):
ProcessSpec(
process_id="unsafe-readiness",
argv=(sys.executable, "-c", "pass"),
start_order=1,
shutdown_order=1,
ready_log_patterns=("ready",),
)
def test_s0_worker_guard_binds_exact_digest_and_d_only_run_path() -> None:
guard = S0WorkerGuard(PROFILE)
run = _run(host_profile_sha256=hashlib.sha256(PROFILE.read_bytes()).hexdigest())