from __future__ import annotations import tempfile import unittest from pathlib import Path from cognitive_agent.application.seat_service import REPOSITORY_ROOT, SeatDemoService from cognitive_agent.infrastructure.can.hardware import HardwareSafetyError class SimulatedHardwareIntegrationTests(unittest.TestCase): def setUp(self) -> None: self.service = SeatDemoService(REPOSITORY_ROOT) self.service.simulated_hardware_enabled = True self.temporary_directory = tempfile.TemporaryDirectory() self.addCleanup(self.temporary_directory.cleanup) self.service.artifact_root = Path(self.temporary_directory.name) def test_normal_simulated_hardware_is_explicit_and_isolated(self) -> None: result = self.service.process( "副驾靠背调到50%", provider="local", execution_mode="simulated_hardware", ) self.assertEqual(result["status"], "succeeded") report = result["execution_report"] self.assertEqual(report["spec"]["mode"], "hil") self.assertEqual(report["metadata"]["labels"]["simulation"], "true") self.assertEqual( report["metadata"]["labels"]["seat_feedback"], "simulated_hardware", ) telemetry = report["spec"]["results"][0]["telemetry"] self.assertTrue(telemetry["simulation"]) self.assertFalse(telemetry["physical_can_opened"]) def test_each_fault_scenario_produces_a_failed_simulated_report(self) -> None: expected_errors = { "feedback_timeout": "FeedbackTimeout", "adapter_disconnect": "CanAdapterDisconnected", "motor_stall": "MotorStall", "firmware_mismatch": "FirmwareMismatch", "partial_feedback": "PartialFeedback", } for scenario, error_type in expected_errors.items(): with self.subTest(scenario=scenario): result = self.service.process( "副驾靠背调到50%", provider="local", execution_mode="simulated_hardware", simulation_fault=scenario, ) self.assertEqual(result["status"], "execution_failed") report = result["execution_report"] self.assertEqual( report["metadata"]["labels"]["fault_scenario"], scenario ) telemetry = report["spec"]["results"][0]["telemetry"] self.assertEqual(telemetry["error_type"], error_type) self.assertFalse(telemetry["physical_can_opened"]) def test_simulated_hardware_requires_server_side_enablement(self) -> None: self.service.simulated_hardware_enabled = False with self.assertRaises(HardwareSafetyError): self.service.process( "副驾靠背调到50%", provider="local", execution_mode="simulated_hardware", ) def test_runtime_publishes_fault_catalog_without_enabling_real_hardware(self) -> None: runtime = self.service.runtime_info() self.assertTrue(runtime["simulated_hardware"]["enabled"]) self.assertFalse(runtime["simulated_hardware"]["physical_can_opened"]) self.assertIn("motor_stall", runtime["simulated_hardware"]["fault_scenarios"]) if __name__ == "__main__": unittest.main()