ai-internet-diagnostic-model / tests /test_synth_class_coverage.py
WolfDavid's picture
feat(01-03): wave 0 — model repo skeleton + 3 generator tests + Makefile
4de429d
"""FOUND-04 class coverage test.
Every one of the 10 disconnect classes has a registered generator emitting
>=1 frame whose dict matches the TelemetryFrame field names.
"""
from __future__ import annotations
from numpy.random import PCG64, Generator
from model.synth.state_machines import GENERATORS
EXPECTED_CLASSES: frozenset[str] = frozenset({
"auth_8021x_eap_fail",
"ap_roam_rekey_fail",
"radius_timeout",
"captive_portal_expiry",
"mac_randomization_reject",
"dhcp_lease_churn",
"dns_resolver_fail",
"driver_power_save_wake",
"rf_sticky_client",
"isp_upstream_fail",
})
CANONICAL_ORDER = [
"auth_8021x_eap_fail",
"ap_roam_rekey_fail",
"radius_timeout",
"captive_portal_expiry",
"mac_randomization_reject",
"dhcp_lease_churn",
"dns_resolver_fail",
"driver_power_save_wake",
"rf_sticky_client",
"isp_upstream_fail",
]
def test_all_ten_classes_registered():
assert set(GENERATORS.keys()) == EXPECTED_CLASSES, (
"GENERATORS must contain exactly the 10 canonical class slugs; "
f"got {sorted(GENERATORS.keys())}"
)
def test_generators_in_canonical_order():
"""Insertion order matters for byte-identicality (RESEARCH Pattern 4 Critical note)."""
assert list(GENERATORS.keys()) == CANONICAL_ORDER
def test_each_class_emits_valid_frame(expected_field_names):
rng = Generator(PCG64(42))
for cls, fn in GENERATORS.items():
frames = fn(rng)
assert len(frames) >= 1, f"Class {cls} emitted zero frames"
sample = frames[0]
extra = set(sample.keys()) - expected_field_names
missing = expected_field_names - set(sample.keys())
assert not extra, f"Class {cls} emitted unknown fields: {extra}"
assert not missing, f"Class {cls} missing required fields: {missing}"
def test_window_ms_per_class():
"""D-04: 30000 ms for fast events, 120000 ms for driver / sticky-client."""
rng = Generator(PCG64(42))
slow_classes = {"driver_power_save_wake", "rf_sticky_client"}
for cls, fn in GENERATORS.items():
sample = fn(rng)[0]
expected_window = 120000 if cls in slow_classes else 30000
assert sample["window_ms"] == expected_window, (
f"Class {cls} window_ms={sample['window_ms']}, expected {expected_window} (D-04)"
)