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()