feat(e2e): add kind discriminator + direct/recorder scenario definitions
This commit is contained in:
@@ -135,6 +135,18 @@ def _sig(name, type, elements=1, time_mode="PacketTime", time_signal=None,
|
|||||||
def validate_scenario(s):
|
def validate_scenario(s):
|
||||||
"""Return a list of validity error strings (empty == valid)."""
|
"""Return a list of validity error strings (empty == valid)."""
|
||||||
errs = []
|
errs = []
|
||||||
|
kind = s.get("kind", "chain")
|
||||||
|
if kind == "direct":
|
||||||
|
if "cfg" not in s:
|
||||||
|
errs.append(f"direct scenario {s.get('id')} missing cfg")
|
||||||
|
return errs
|
||||||
|
if kind == "recorder":
|
||||||
|
if "hub_cfg" not in s or "marte_cfg" not in s:
|
||||||
|
errs.append(f"recorder scenario {s.get('id')} missing hub_cfg/marte_cfg")
|
||||||
|
return errs
|
||||||
|
if kind != "chain":
|
||||||
|
errs.append(f"unknown scenario kind: {kind}")
|
||||||
|
return errs
|
||||||
row_dt, num_rows, _producer_hz, loop_hz = geometry(s)
|
row_dt, num_rows, _producer_hz, loop_hz = geometry(s)
|
||||||
if s.get("network") not in ("unicast", "multicast"):
|
if s.get("network") not in ("unicast", "multicast"):
|
||||||
errs.append("network must be unicast|multicast")
|
errs.append("network must be unicast|multicast")
|
||||||
@@ -565,6 +577,47 @@ SCENARIOS = (_STARTERS + _TYPES + _ARRAYS + _TIMEMODES + _QUANT + _PUBLISH +
|
|||||||
_PAYLOAD + _MCAST + _MULTISRC + _INTERACT + _TRIGGER + _MISC +
|
_PAYLOAD + _MCAST + _MULTISRC + _INTERACT + _TRIGGER + _MISC +
|
||||||
_HIGHRATE)
|
_HIGHRATE)
|
||||||
|
|
||||||
|
for _s in SCENARIOS:
|
||||||
|
_s.setdefault("kind", "chain")
|
||||||
|
|
||||||
|
# ── Non-chain scenario kinds ──────────────────────────────────────────────────
|
||||||
|
# "direct" and "recorder" scenarios exercise the other two data paths described
|
||||||
|
# in ARCHITECTURE.md (direct UDPStreamer<->UDPStreamerClient, and StreamHub's
|
||||||
|
# BinaryRecorder disk sink) and intentionally do not carry the chain-only keys
|
||||||
|
# (sources/network/oracle/...): they have their own orchestration in run_e2e.sh.
|
||||||
|
_DIRECT = [
|
||||||
|
{
|
||||||
|
"id": "s52_direct_unicast",
|
||||||
|
"desc": "Direct UDPStreamer->UDPStreamerClient round-trip, unicast",
|
||||||
|
"kind": "direct",
|
||||||
|
"cfg": "Test/E2E/datasources/E2ETest.cfg",
|
||||||
|
"client_checks": [],
|
||||||
|
"known_issue": None,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "s53_direct_multicast",
|
||||||
|
"desc": "Direct UDPStreamer->UDPStreamerClient round-trip, multicast",
|
||||||
|
"kind": "direct",
|
||||||
|
"cfg": "Test/E2E/datasources/E2EMulticastTest.cfg",
|
||||||
|
"client_checks": [],
|
||||||
|
"known_issue": None,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
_RECORDER = [
|
||||||
|
{
|
||||||
|
"id": "s54_recorder",
|
||||||
|
"desc": "StreamHub BinaryRecorder disk-output round-trip",
|
||||||
|
"kind": "recorder",
|
||||||
|
"hub_cfg": "Test/E2E/recorder/StreamHubRec.cfg",
|
||||||
|
"marte_cfg": "Test/E2E/recorder/RecorderStreamer.cfg",
|
||||||
|
"client_checks": [],
|
||||||
|
"known_issue": None,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
SCENARIOS = SCENARIOS + _DIRECT + _RECORDER
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
@@ -576,6 +629,7 @@ if __name__ == "__main__":
|
|||||||
if s["id"] in seen_ids:
|
if s["id"] in seen_ids:
|
||||||
errs.append("duplicate id")
|
errs.append("duplicate id")
|
||||||
seen_ids.add(s["id"])
|
seen_ids.add(s["id"])
|
||||||
|
if s["kind"] == "chain":
|
||||||
if s["ws_port"] in seen_ws:
|
if s["ws_port"] in seen_ws:
|
||||||
errs.append(f"duplicate ws_port {s['ws_port']}")
|
errs.append(f"duplicate ws_port {s['ws_port']}")
|
||||||
seen_ws.add(s["ws_port"])
|
seen_ws.add(s["ws_port"])
|
||||||
|
|||||||
@@ -58,6 +58,24 @@ class TestScenarios(unittest.TestCase):
|
|||||||
errs = S.validate_scenario(s)
|
errs = S.validate_scenario(s)
|
||||||
self.assertTrue(any("quant only on float" in e for e in errs), errs)
|
self.assertTrue(any("quant only on float" in e for e in errs), errs)
|
||||||
|
|
||||||
|
def test_all_scenarios_have_kind(self):
|
||||||
|
for s in S.SCENARIOS:
|
||||||
|
self.assertIn("kind", s, f"{s['id']} missing kind")
|
||||||
|
self.assertIn(s["kind"], ("chain", "direct", "recorder", "debug", "tcplogger"))
|
||||||
|
|
||||||
|
def test_direct_and_recorder_scenarios_present(self):
|
||||||
|
kinds = {s["kind"] for s in S.SCENARIOS}
|
||||||
|
self.assertIn("direct", kinds)
|
||||||
|
self.assertIn("recorder", kinds)
|
||||||
|
direct_ids = {s["id"] for s in S.SCENARIOS if s["kind"] == "direct"}
|
||||||
|
self.assertEqual(direct_ids, {"s52_direct_unicast", "s53_direct_multicast"})
|
||||||
|
recorder_ids = {s["id"] for s in S.SCENARIOS if s["kind"] == "recorder"}
|
||||||
|
self.assertEqual(recorder_ids, {"s54_recorder"})
|
||||||
|
|
||||||
|
def test_validate_scenario_accepts_all_kinds(self):
|
||||||
|
for s in S.SCENARIOS:
|
||||||
|
S.validate_scenario(s) # must not raise
|
||||||
|
|
||||||
|
|
||||||
class TestGenData(unittest.TestCase):
|
class TestGenData(unittest.TestCase):
|
||||||
def test_ground_truth_shapes(self):
|
def test_ground_truth_shapes(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user