"""Small synthetic checks only; model/real-source runs belong on Worker 006.""" import importlib import io import json import threading import zipfile from pathlib import Path from types import SimpleNamespace import numpy as np import pytest @pytest.fixture def pilot(monkeypatch): root = Path(__file__).resolve().parents[1] monkeypatch.syspath_prepend( str(root / "experiments/perception/worker/streaming_profile_stage1") ) return lambda name: importlib.import_module(name) def test_full_graph_reset_replaces_temporal_state_not_models(pilot): module = pilot("pilot_graph") root = Path(__file__).resolve().parents[1] / "config/perception" graph = module.JointGraph.__new__(module.JointGraph) graph.surface = module.K1LocalSurfaceShadowEstimator() graph.store = module.CurrentStore( module.load_geometry_profile(root / "m4-geometry-association-v1.json") ) profile = module.load_temporal_motion_profile(root / "m4-temporal-motion-v1.json") graph.temporal = module.BoundedSpatialTemporalProvider( point_resolver=graph.store, profile=profile ) graph.motion = module.ClassIndependentMotionEstimator(profile=profile) graph.rolling = module.RollingLocalObstacleMapProvider( pose_resolver=graph.store, profile=module.load_rolling_map_profile(root / "m4-rolling-local-map-v1.json"), ) graph.threat = module.DualEvidenceReplayThreatProvider( body_frame_resolver=graph.store, profile=module.load_replay_threat_profile(root / "m4-replay-threat-v3.json"), ) graph.temporal_resets = 0 graph.backend = graph.detector = graph.tgs = model = object() for cache in ( graph.surface._cache, graph.store.body_history, graph.temporal._components, graph.rolling._cells, ): cache["old"] = object() graph.surface._previous_surface = (1, 2, 3, 4) graph.temporal._previous_sequence = graph.rolling._previous_sequence = 32 old_store = graph.store state = graph.reset_temporal() assert set(state["previous"].values()) == {1} assert set(state["current"].values()) == {0} assert graph.temporal._previous_sequence is graph.rolling._previous_sequence is None assert graph.surface._previous_surface is None and graph.temporal_resets == 1 assert graph.store is not old_store assert ( graph.temporal.point_resolver is graph.rolling.pose_resolver is graph.threat.body_frame_resolver is graph.store ) assert graph.backend is graph.detector is graph.tgs is model assert graph.temporal.profile is graph.motion.profile is profile @pytest.mark.parametrize( "values", [["0:1"], ["10:0"], ["10:5001"], ["a:1"], ["10:1", "9:1"], ["1:1"] * 5] ) def test_source_gap_plan_is_bounded(pilot, values): with pytest.raises(ValueError): pilot("pilot_binary_source").input_gaps(values) def test_source_gap_plan_preserves_explicit_sequence_and_duration(pilot): assert pilot("pilot_binary_source").input_gaps(["16:150", "72:2200"]) == [(16, 150), (72, 2200)] def test_pending_overflow_is_explicit_and_does_not_evict_active(pilot): queue = pilot("pilot_queue").Mailbox(capacity=2, byte_limit=100) def make(sequence): return {"sequence": sequence, "payload_bytes": 10} queue.put(make(0)) active = queue.take() for sequence in (1, 2, 3): queue.put(make(sequence)) assert queue.dropped == [{"sequence": 1, "reason": "pending-overflow"}] assert queue.bytes == 30 assert queue.peak_pending == 2 queue.release(active) assert queue.take()["sequence"] == 2 assert queue.take()["sequence"] == 3 def test_active_bytes_count_towards_memory_limit(pilot): queue = pilot("pilot_queue").Mailbox(byte_limit=20) queue.put({"sequence": 0, "payload_bytes": 20}) active = queue.take() queue.put({"sequence": 1, "payload_bytes": 1}) assert queue.dropped == [{"sequence": 1, "reason": "byte-budget"}] assert queue.peak_bytes == 20 queue.release(active) queue.finish() assert queue.take() is None def test_interrupted_decode_accounts_for_released_but_not_admitted_camera(pilot, monkeypatch): module = pilot("run_joint_pilot") event = SimpleNamespace(time_ns=1_000_000_000, channel="camera", sequence=0, value={}) archive = SimpleNamespace(counters=lambda: {}, close=lambda: None) monkeypatch.setattr(module, "SensorArchive", lambda _path: archive) monkeypatch.setattr(module, "camera_events", lambda *args: iter([event])) monkeypatch.setattr(module, "merged_events", lambda *args: iter([event])) def interrupted(*args): raise EOFError("decoder stopped by supervisor") monkeypatch.setattr(module, "send", interrupted) queue = pilot("pilot_queue").Mailbox() report = {} stop = SimpleNamespace(is_set=lambda: False, wait=lambda _seconds: False) args = SimpleNamespace(sensor_archive="unused", camera_index="unused", frames=1) module.produce(args, SimpleNamespace(stdin=None), queue, stop, report) assert report["arrivals"]["camera"] == 1 assert report["failed_camera_sequences"] == [0] assert "decoder stopped" in queue.error and queue.dropped_count == 0 assert queue.quiescent def test_numpy_member_is_read_incrementally_and_bounded(pilot): data = io.BytesIO() np.savez_compressed(data, points=np.arange(300, dtype="