from __future__ import annotations import json import os import tempfile import unittest from pathlib import Path from unittest.mock import patch from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService SUITE_PATH = REPOSITORY_ROOT / "tests" / "fixtures" / "seat_frontend_hil_suite.json" EXPECTED_CAPABILITIES = { "heating": "seat.set_heating", "ventilation": "seat.set_ventilation", "longitudinal": "seat.set_longitudinal_position", "cushion_tilt": "seat.set_cushion_tilt", "backrest_recline": "seat.set_backrest_recline", "legrest_height": "seat.set_legrest_height", } def expand_entries(entries: list[dict], group: str | None = None) -> list[dict]: expanded = [] for entry in entries: base = {key: value for key, value in entry.items() if key != "variants"} if group is not None: base["group"] = group variants = entry.get("variants") if not variants: expanded.append(base) continue expanded.extend({**base, **variant} for variant in variants) return expanded class SeatFrontendInputCoverageTests(unittest.TestCase): @classmethod def setUpClass(cls) -> None: cls.temporary_directory = tempfile.TemporaryDirectory() with patch.dict( os.environ, {"COGNITIVE_AGENT_HARDWARE_EXECUTION_ENABLED": "false"}, clear=False, ): cls.service = SeatDemoService(REPOSITORY_ROOT) cls.service.artifact_root = Path(cls.temporary_directory.name) cls.suite = json.loads(SUITE_PATH.read_text(encoding="utf-8")) cls.positive_cases = expand_entries(cls.suite["cases"]) + expand_entries( cls.suite["mode_cases"], "mode" ) cls.model_cases = expand_entries(cls.suite.get("model_cases", []), "model") cls.rejection_cases = expand_entries(cls.suite["rejection_cases"], "safety") @classmethod def tearDownClass(cls) -> None: cls.temporary_directory.cleanup() def test_suite_has_broad_equivalence_and_safety_coverage(self) -> None: self.assertGreaterEqual(len(self.positive_cases), 160) self.assertGreaterEqual(len(self.model_cases), 4) self.assertGreaterEqual(len(self.rejection_cases), 20) self.assertEqual( {case["group"] for case in self.positive_cases}, {"thermal", "motion", "combined", "mode"}, ) self.assertEqual( {case["mode_id"] for case in self.positive_cases if case["group"] == "mode"}, { "easy_entry_exit", "office", "queen_passenger_driving", "baby_nap", "cruise_sofa", "meditation_space", "leisure_lounger", "calf_decompression_float", "electric_beach_chair", "nap", "zero_gravity", }, ) def test_all_expanded_case_ids_and_utterances_are_unique(self) -> None: cases = [*self.positive_cases, *self.model_cases, *self.rejection_cases] self.assertEqual(len({case["id"] for case in cases}), len(cases)) self.assertEqual(len({case["utterance"] for case in cases}), len(cases)) def test_model_cases_require_gpt56_and_define_physical_targets(self) -> None: for case in self.model_cases: with self.subTest(case=case["id"]): self.assertEqual(case["provider"], "openai") self.assertEqual( case["expected_provider_prefix"], "openai:gpt-5.6-sol" ) self.assertEqual( set(case["expected"]), { "longitudinal", "cushion_tilt", "backrest_recline", "legrest_height", }, ) def test_every_positive_utterance_generates_the_expected_dry_run(self) -> None: for case in self.positive_cases: with self.subTest(case=case["id"], utterance=case["utterance"]): result = self.service.process( case["utterance"], provider=case.get("provider", "local"), conversation_id="conv-coverage-positive-sequence", execution_mode="dry_run", vehicle_id=self.suite["vehicle_id"], ) self.assertEqual(result["status"], "succeeded") if case.get("mode_id"): self.assertIn( case["mode_id"], {item["id"] for item in result["matched_modes"]}, ) seat_config = result["function_configs"].get("seat") or result[ "function_config" ] self.assertIsNotNone(seat_config) operations = seat_config["spec"]["operations"] by_capability = {item["capability"]: item for item in operations} passenger = result["actuator_state"]["passenger"] for field, expected in case["expected"].items(): capability = EXPECTED_CAPABILITIES[field] self.assertIn(capability, by_capability) operation = by_capability[capability] self.assertEqual(operation["target"]["instance"], "passenger") self.assertEqual(operation["target"]["zone"], "front_right") if field in {"heating", "ventilation"}: if expected == 0: self.assertEqual(operation["parameters"]["state"], "off") else: self.assertEqual(passenger[field]["level"], expected) else: self.assertEqual(operation["parameters"]["position_pct"], expected) self.assertEqual( passenger["position"][field]["position_pct"], expected ) expected_motion = case.get("expected_motion") if expected_motion: capability = EXPECTED_CAPABILITIES[expected_motion["axis"]] operation = by_capability[capability] self.assertIn("motion", operation) for field, expected in expected_motion.items(): if field != "axis": self.assertEqual(operation["motion"][field], expected) def test_every_rejection_utterance_stops_before_execution(self) -> None: for case in self.rejection_cases: with self.subTest(case=case["id"], utterance=case["utterance"]): result = self.service.process( case["utterance"], provider=case.get("provider", "local"), conversation_id=f"conv-coverage-{case['id'].lower()}", execution_mode="dry_run", vehicle_id=self.suite["vehicle_id"], ) self.assertEqual(result["status"], case["expected_status"]) self.assertIsNone(result["function_config"]) self.assertEqual(result["function_configs"], {}) self.assertIsNone(result["execution_report"]) if __name__ == "__main__": unittest.main()