import json import sys import unittest from pathlib import Path from tempfile import TemporaryDirectory sys.path.insert(0, str(Path(__file__).resolve().parent)) from generate_kinematics_closure_report import generate class KinematicsClosureReportTests(unittest.TestCase): def make_tree(self): directory = TemporaryDirectory() root = Path(directory.name) (root / "context-lock.json").write_text('{"context_id":"test-context"}\n', encoding="utf-8") source = root / "linuxcnc/src/emc/kinematics" source.mkdir(parents=True) (source / "trivkins.c").write_text("int kinematicsForward(void) { return 0; }\n", encoding="utf-8") (source / "kinematics.h").write_text("typedef int KINEMATICS_TYPE;\n", encoding="utf-8") config = root / "linuxcnc/configs/sim/demo" config.mkdir(parents=True) (config / "demo.ini").write_text("[KINS]\nKINEMATICS = trivkins coordinates=XYZ\n", encoding="utf-8") (config / "demo.hal").write_text("loadrt trivkins\n", encoding="utf-8") (root / "linuxcnc/tests/matrixkins").mkdir(parents=True) (root / "linuxcnc/tests/matrixkins/test.ini").write_text("[KINS]\nKINEMATICS = matrixkins\n", encoding="utf-8") return directory, root def test_report_is_deterministic_and_retains_missing_required_root(self): directory, root = self.make_tree() self.addCleanup(directory.cleanup) first = root / "one.json" second = root / "two.json" report_one = generate(root, first) report_two = generate(root, second) self.assertEqual(report_one["status"], "blocked") self.assertIn("linuxcnc/unit_tests/kinematics", report_one["missing_required_test_roots"]) self.assertEqual(first.read_bytes(), second.read_bytes()) self.assertEqual(report_one["source"]["file_count"], 2) self.assertEqual(report_one["configuration"]["entry_count"], 2) self.assertEqual(report_one["hal"]["entry_count"], 1) self.assertTrue(report_one["configuration"]["entries"][0]["config_id"].startswith("config:")) self.assertEqual(report_one["source"]["files"][0]["source_id"], "source:linuxcnc/src/emc/kinematics/kinematics.h") self.assertTrue(all(row["oracle"]["status"] == "blocked" for row in report_one["families"])) self.assertEqual(json.loads(first.read_text(encoding="utf-8")), report_two) def test_hal_transform_and_switchkins_entries_are_registered(self): directory, root = self.make_tree() self.addCleanup(directory.cleanup) hal = root / "linuxcnc/configs/sim/demo/demo.hal" hal.write_text("loadrt corexy_by_hal names=corexy\nnet select => motion.switchkins-type\n", encoding="utf-8") report = generate(root, root / "report.json") kinds = {row["kind"] for row in report["hal"]["entries"]} self.assertIn("loadrt", kinds) self.assertIn("hal_transform", kinds) self.assertIn("switchkins", kinds) if __name__ == "__main__": unittest.main()