import json import subprocess import unittest from pathlib import Path import generate_kinematics_runtime_report ROOT = Path(__file__).resolve().parents[1] class KinematicsRuntimeTests(unittest.TestCase): def test_native_kinematics_binary(self): binary = ROOT / "build-native/sim_kinematics_test" if not binary.is_file(): self.skipTest("native build has not been generated") result = subprocess.run([str(binary)], cwd=ROOT, check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.assertEqual(result.returncode, 0, result.stderr.decode(errors="replace")) def test_wasm_exports_kinematics_api(self): module = ROOT / "build-wasm/linuxcnc-sim-core.js" if not module.is_file(): self.skipTest("WASM build has not been generated") text = module.read_text(encoding="utf-8") for symbol in ("sim_kinematics_init", "sim_kinematics_forward_ex", "sim_kinematics_inverse_ex", "sim_kinematics_state_hash"): self.assertIn(symbol, text) def test_report_contract(self): report = json.loads((ROOT / "coverage/kinematics-runtime.report.json").read_text(encoding="utf-8")) self.assertEqual(report["schema"], "kinematics-runtime-report.v1") self.assertEqual(report["status"], "partial") self.assertTrue(report["registered_build_targets"]["native_ctest"]) self.assertFalse(report["closure"]["full_linuxcnc_kinematics"]) self.assertIn("linear-delta", report["supported_types"]) self.assertIn("rotary-delta", report["supported_types"]) self.assertIn("tripod", report["supported_types"]) def test_report_is_deterministic(self): first = ROOT / "coverage/.kinematics-runtime-one.json" second = ROOT / "coverage/.kinematics-runtime-two.json" try: report_one = generate_kinematics_runtime_report.generate(ROOT, first) report_two = generate_kinematics_runtime_report.generate(ROOT, second) self.assertEqual(report_one, report_two) finally: first.unlink(missing_ok=True) second.unlink(missing_ok=True) if __name__ == "__main__": unittest.main()