from __future__ import annotations import unittest from pathlib import Path import yaml from cognitive_agent.runtime.contracts import ContractValidator from seat_domain.generator import build_function_config from seat_domain.intent import parse_local_intent from seat_domain.matrix import SeatCanMatrix from seat_domain.source_matrix import read_source_signals ROOT = Path(__file__).resolve().parents[4] DOMAIN_ROOT = ROOT / "domains" / "seat" class SeatContractTests(unittest.TestCase): def setUp(self) -> None: self.validator = ContractValidator(ROOT) def test_generated_function_config_matches_both_schemas(self) -> None: parsed = parse_local_intent("打开副驾座椅加热") config = build_function_config(parsed, "req-contract-001", "local_rules") self.assertEqual(self.validator.validate(config), []) def test_inferred_level_function_config_matches_both_schemas(self) -> None: parsed = parse_local_intent("副驾有点热,有点闷") config = build_function_config(parsed, "req-contract-002", "local_rules") self.assertEqual(config["spec"]["operations"][0]["parameters"]["level"], 1) self.assertEqual(self.validator.validate(config), []) def test_motion_function_config_matches_both_schemas(self) -> None: parsed = { "detected_domains": ["seat"], "actions": [ { "action_type": "position", "target": "passenger", "axis": "legrest_extension", "position_pct": 70, } ], "deferred_requests": [], "ambiguities": [], "decision_summary": ["Extend passenger leg rest."], "confidence": 1.0, } config = build_function_config(parsed, "req-contract-motion", "test") self.assertEqual(config["spec"]["operations"][0]["parameters"], {"position_pct": 70}) self.assertEqual(self.validator.validate(config), []) def test_all_active_presets_match_both_schemas(self) -> None: for path in (DOMAIN_ROOT / "config" / "presets").glob("*.yaml"): with self.subTest(path=path.name): document = yaml.safe_load(path.read_text(encoding="utf-8")) self.assertEqual(self.validator.validate(document), []) def test_normalized_matrix_matches_source_scope(self) -> None: matrix = SeatCanMatrix(DOMAIN_ROOT / "can" / "seat-thermal-matrix.yaml") self.assertEqual(len(matrix.data["messages"]), 6) self.assertEqual(sum(len(item["signals"]) for item in matrix.data["messages"]), 23) self.assertFalse(matrix.hardware_execution_allowed) def test_synthetic_motion_matrix_is_explicitly_non_hardware(self) -> None: matrix = SeatCanMatrix(DOMAIN_ROOT / "can" / "seat-motion-virtual-matrix.yaml") self.assertTrue(matrix.data["synthetic"]) self.assertFalse(matrix.hardware_execution_allowed) self.assertEqual(len(matrix.data["messages"]), 4) self.assertEqual(sum(len(item["signals"]) for item in matrix.data["messages"]), 34) def test_normalized_signal_layout_matches_supplied_xlsx(self) -> None: source = { item["name"]: item for item in read_source_signals(ROOT / "座椅部分功能CAN矩阵表.xlsx") } matrix = SeatCanMatrix(DOMAIN_ROOT / "can" / "seat-thermal-matrix.yaml") normalized = { signal["name"]: { "frame_id": int(message["frame_id"]), "start_bit": int(signal["start_bit"]), "bit_length": int(signal["bit_length"]), } for message in matrix.data["messages"] for signal in message["signals"] } self.assertEqual(set(source), set(normalized)) for name, layout in normalized.items(): with self.subTest(signal=name): self.assertEqual(layout["frame_id"], source[name]["frame_id"]) self.assertEqual(layout["start_bit"], source[name]["start_bit"]) self.assertEqual(layout["bit_length"], source[name]["bit_length"]) if __name__ == "__main__": unittest.main()