from __future__ import annotations from dataclasses import replace import unittest from app.main import compile_system_xml_network from app.system_xml import validate_system_xml_document def physical_system_xml() -> str: return """ """ def issue_codes(xml: str) -> set[str]: return {issue.code for issue in validate_system_xml_document(xml).issues} class SystemXmlV3Tests(unittest.TestCase): def test_minimal_execution_model_is_valid(self) -> None: report = validate_system_xml_document(physical_system_xml()) self.assertTrue(report.valid) self.assertEqual(report.issues, ()) assert report.document is not None self.assertEqual(report.document.connections[0].id, "connection_1") model = report.document.as_model_data() self.assertEqual(model["name"], "untitled") self.assertEqual(model["simulation"]["sample_step"], 0.2) self.assertEqual(model["components"][0]["model_version"], "1.0.0") def test_editor_and_port_snapshot_fields_are_rejected(self) -> None: xml = physical_system_xml().replace( 'modelVersion="1.0.0">', 'modelVersion="1.0.0" x="10">\n ', 1, ) report = validate_system_xml_document(xml) self.assertFalse(report.valid) self.assertIsNone(report.document) self.assertTrue(all(issue.layer == "schema" for issue in report.issues)) def test_model_version_is_checked_against_registry(self) -> None: xml = physical_system_xml().replace( 'type="cylinder" modelVersion="1.0.0"', 'type="cylinder" modelVersion="9.9.9"', ) self.assertIn("COMPONENT_MODEL_VERSION_MISMATCH", issue_codes(xml)) def test_direct_compiler_defends_the_model_version_contract(self) -> None: report = validate_system_xml_document(physical_system_xml()) assert report.document is not None first = replace( report.document.components[0], model_version="9.9.9", ) document = replace( report.document, components=(first, *report.document.components[1:]), ) with self.assertRaisesRegex(ValueError, "expected '1.0.0'"): compile_system_xml_network(document) def test_component_cannot_connect_two_of_its_own_ports(self) -> None: xml = """ """ self.assertIn("CONNECTION_SELF_REFERENCE", issue_codes(xml)) def test_signal_direction_is_derived_from_registered_ports(self) -> None: xml = """ """ self.assertIn("SIGNAL_PORT_ROLES_INVALID", issue_codes(xml)) def test_signal_input_rejects_multiple_drivers_but_output_may_fan_out(self) -> None: components = """ """ def signal_xml(connections: str) -> str: return f""" {components} {connections} """ multiple_drivers = signal_xml(""" """) fan_out = signal_xml(""" """) self.assertIn( "SIGNAL_INPUT_MULTIPLE_DRIVERS", issue_codes(multiple_drivers), ) self.assertTrue(validate_system_xml_document(fan_out).valid) def test_v2_step_name_is_not_accepted(self) -> None: xml = physical_system_xml().replace('sampleStep="0.2"', 'step="0.2"') report = validate_system_xml_document(xml) self.assertFalse(report.valid) self.assertIsNone(report.document) self.assertIn("XSD_VALIDATION_ERROR", issue_codes(xml)) if __name__ == "__main__": unittest.main()