feat: introduce device plugin runtime boundary
This commit is contained in:
@@ -60,9 +60,7 @@ def test_legacy_points_and_pose_are_logged_to_rerun() -> None:
|
||||
point_payload = struct.pack("<III", 16, 0, 0) + struct.pack(
|
||||
"<fffBBBB", 1.0, -2.0, 3.0, 10, 20, 30, 40
|
||||
)
|
||||
pose_payload = struct.pack(
|
||||
"<ffffffff", 1.0, 2.0, 3.0, 99.0, 0.9, 0.1, 0.2, 0.3
|
||||
)
|
||||
pose_payload = struct.pack("<ffffffff", 1.0, 2.0, 3.0, 99.0, 0.9, 0.1, 0.2, 0.3)
|
||||
bridge.process(_message("RealtimePointcloud", point_payload))
|
||||
bridge.process(_message("RealtimePath", pose_payload, sequence=8))
|
||||
|
||||
@@ -155,9 +153,7 @@ def test_runtime_exposes_rerun_url_and_stops_cleanly(tmp_path: Path) -> None:
|
||||
point_payload = struct.pack("<III", 16, 0, 0) + struct.pack(
|
||||
"<fffBBBB", 1.0, -2.0, 3.0, 10, 20, 30, 40
|
||||
)
|
||||
pose_payload = struct.pack(
|
||||
"<ffffffff", 1.0, 2.0, 3.0, 99.0, 0.9, 0.1, 0.2, 0.3
|
||||
)
|
||||
pose_payload = struct.pack("<ffffffff", 1.0, 2.0, 3.0, 99.0, 0.9, 0.1, 0.2, 0.3)
|
||||
frames = bytearray(RAW_MAGIC)
|
||||
for topic, payload in ((point_topic, point_payload), (pose_topic, pose_payload)):
|
||||
topic_raw = topic.encode()
|
||||
@@ -236,9 +232,7 @@ def test_close_during_blocked_factory_closes_the_late_bridge(tmp_path: Path) ->
|
||||
payload = struct.pack("<III", 16, 0, 0) + struct.pack(
|
||||
"<fffBBBB", 1.0, -2.0, 3.0, 10, 20, 30, 40
|
||||
)
|
||||
capture.write_bytes(
|
||||
RAW_MAGIC + FRAME_HEADER.pack(len(topic), len(payload)) + topic + payload
|
||||
)
|
||||
capture.write_bytes(RAW_MAGIC + FRAME_HEADER.pack(len(topic), len(payload)) + topic + payload)
|
||||
(tmp_path / "mqtt.metadata.jsonl").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
@@ -279,3 +273,48 @@ def test_close_during_blocked_factory_closes_the_late_bridge(tmp_path: Path) ->
|
||||
assert runtime.snapshot()["rerun_grpc_url"] is None
|
||||
with pytest.raises(RuntimeError, match="runtime завершён"):
|
||||
runtime.start_replay(capture, speed=0.0)
|
||||
|
||||
|
||||
def test_stop_fails_closed_when_runtime_thread_misses_deadline(tmp_path: Path) -> None:
|
||||
capture = tmp_path / "mqtt.raw.k1mqtt"
|
||||
topic = b"RealtimePointcloud"
|
||||
payload = struct.pack("<III", 16, 0, 0) + struct.pack(
|
||||
"<fffBBBB", 1.0, -2.0, 3.0, 10, 20, 30, 40
|
||||
)
|
||||
capture.write_bytes(RAW_MAGIC + FRAME_HEADER.pack(len(topic), len(payload)) + topic + payload)
|
||||
(tmp_path / "mqtt.metadata.jsonl").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"record_type": "message",
|
||||
"sequence": 1,
|
||||
"received_at_epoch_ns": 1_000_000_000,
|
||||
"received_monotonic_ns": 1_000_000_000,
|
||||
}
|
||||
)
|
||||
+ "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
factory_entered = threading.Event()
|
||||
release_factory = threading.Event()
|
||||
|
||||
def blocked_factory(**kwargs: object) -> RerunBridge:
|
||||
factory_entered.set()
|
||||
assert release_factory.wait(timeout=5.0)
|
||||
return RerunBridge(
|
||||
recording_factory=lambda _: FakeRecording(), # type: ignore[arg-type]
|
||||
**kwargs, # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
runtime = VisualizationRuntime(bridge_factory=blocked_factory)
|
||||
runtime.start_replay(capture, speed=0.0)
|
||||
assert factory_entered.wait(timeout=2.0)
|
||||
|
||||
with pytest.raises(RuntimeError, match="не завершился"):
|
||||
runtime.stop(wait_seconds=0.01)
|
||||
assert runtime.snapshot()["phase"] == "stopping"
|
||||
|
||||
release_factory.set()
|
||||
runtime.stop(wait_seconds=2.0)
|
||||
assert runtime.snapshot()["source_mode"] == "idle"
|
||||
runtime.close()
|
||||
|
||||
Reference in New Issue
Block a user