test: verify history rows link raw frames

This commit is contained in:
lingniu
2026-07-02 08:35:34 +08:00
parent 27f4ad3468
commit 1741aacaaa
4 changed files with 51 additions and 9 deletions

View File

@@ -26,6 +26,7 @@ class CheckSpec:
kind: str = "total"
max_age_minutes: float | None = None
require_parsed_json: bool = False
require_frame_id: bool = False
@dataclass(frozen=True)
@@ -68,6 +69,7 @@ def check_total(
max_age_minutes: float | None = None,
now: dt.datetime | None = None,
require_parsed_json: bool = False,
require_frame_id: bool = False,
) -> Check:
count = int(payload.get("total") or 0)
items = payload.get("items") or []
@@ -92,9 +94,16 @@ def check_total(
parsed_message = parsed_json_message(items)
if not parsed_message.startswith("parsed_json=ok"):
return Check(name, "fail", count, minimum, f"count={count}; {parsed_message}; sample={sample}")
frame_message = ""
if require_frame_id:
frame_message = frame_id_message(items)
if not frame_message.startswith("frame_id=ok"):
return Check(name, "fail", count, minimum, f"count={count}; {frame_message}; sample={sample}")
details = [f"count={count}", age_message]
if parsed_message:
details.append(parsed_message)
if frame_message:
details.append(frame_message)
return Check(name, "pass", count, minimum, "; ".join(details) + f"; sample={sample}")
return Check(name, "fail", count, minimum, f"count={count}; expected >= {minimum}; {age_message}; sample={sample}")
@@ -143,6 +152,15 @@ def parsed_json_message(items: list[Any]) -> str:
return "invalid parsed_json"
def frame_id_message(items: list[Any]) -> str:
if not items or not isinstance(items[0], dict):
return "missing frame_id"
frame_id = str(items[0].get("frame_id") or "").strip()
if frame_id:
return "frame_id=ok"
return "missing frame_id"
def check_realtime(name: str, payload: dict[str, Any]) -> Check:
if payload.get("online") is False:
return Check(name, "fail", 0, 1, "online=false")
@@ -237,12 +255,12 @@ def build_check_specs(
max_age_minutes=max_raw_age_minutes,
require_parsed_json=True,
),
CheckSpec("gb32960.locations", "/api/history/locations", gb32960_history_params, min_history),
CheckSpec("gb32960.mileage_points", "/api/history/mileage-points", gb32960_history_params, min_history),
CheckSpec("jt808.locations", "/api/history/locations", jt808_history_params, min_history),
CheckSpec("jt808.mileage_points", "/api/history/mileage-points", jt808_history_params, min_history),
CheckSpec("yutong_mqtt.locations", "/api/history/locations", yutong_mqtt_history_params, min_history),
CheckSpec("yutong_mqtt.mileage_points", "/api/history/mileage-points", yutong_mqtt_history_params, min_history),
CheckSpec("gb32960.locations", "/api/history/locations", gb32960_history_params, min_history, require_frame_id=True),
CheckSpec("gb32960.mileage_points", "/api/history/mileage-points", gb32960_history_params, min_history, require_frame_id=True),
CheckSpec("jt808.locations", "/api/history/locations", jt808_history_params, min_history, require_frame_id=True),
CheckSpec("jt808.mileage_points", "/api/history/mileage-points", jt808_history_params, min_history, require_frame_id=True),
CheckSpec("yutong_mqtt.locations", "/api/history/locations", yutong_mqtt_history_params, min_history, require_frame_id=True),
CheckSpec("yutong_mqtt.mileage_points", "/api/history/mileage-points", yutong_mqtt_history_params, min_history, require_frame_id=True),
CheckSpec(
"gb32960.daily_mileage",
"/api/stats/daily-metrics",
@@ -340,6 +358,7 @@ def run_checks(base_url: str, specs: list[CheckSpec], timeout: float) -> list[Ch
spec.minimum,
spec.max_age_minutes,
require_parsed_json=spec.require_parsed_json,
require_frame_id=spec.require_frame_id,
))
except Exception as exc: # pragma: no cover - exercised by live failures.
checks.append(Check(spec.name, "fail", 0, spec.minimum, f"request failed: {exc}"))
@@ -359,6 +378,7 @@ def query_payloads(base_url: str, specs: list[CheckSpec], timeout: float) -> tup
spec.minimum,
spec.max_age_minutes,
require_parsed_json=spec.require_parsed_json,
require_frame_id=spec.require_frame_id,
))
except Exception as exc:
checks.append(Check(spec.name, "fail", 0, spec.minimum, f"request failed: {exc}"))

View File

@@ -207,6 +207,28 @@ class GoNativeProdSmokeTest(unittest.TestCase):
self.assertEqual(check.status, "pass")
self.assertIn("parsed_json=ok", check.message)
def test_history_check_requires_frame_id_backlink(self):
check = smoke.check_total(
"jt808.locations",
{"total": 1, "items": [{"ts": "2026-07-01 17:45:00", "frame_id": ""}]},
minimum=1,
require_frame_id=True,
)
self.assertEqual(check.status, "fail")
self.assertIn("missing frame_id", check.message)
def test_history_check_accepts_frame_id_backlink(self):
check = smoke.check_total(
"jt808.mileage_points",
{"total": 1, "items": [{"ts": "2026-07-01 17:45:00", "frame_id": "go_abc"}]},
minimum=1,
require_frame_id=True,
)
self.assertEqual(check.status, "pass")
self.assertIn("frame_id=ok", check.message)
if __name__ == "__main__":
unittest.main()