Files
cdsl-cad/cadfs_to_cdsl/tests/test_lowering.py
T

76 lines
4.4 KiB
Python

from __future__ import annotations
import json, tempfile, unittest
from pathlib import Path
from cadfs_to_cdsl.featurescript_parser import parse_featurescript
from cadfs_to_cdsl.lowering import lower_model
from cadfs_to_cdsl.pipeline import convert_one
from cadfs_to_cdsl.dataset import Sample
from cadfs_to_cdsl.dataset import scan_dataset
from cadfs_to_cdsl.tests.test_parser import SOURCE
class LoweringTests(unittest.TestCase):
def test_missing_dataset_fails_explicitly(self):
with tempfile.TemporaryDirectory() as tmp:
with self.assertRaises(FileNotFoundError): scan_dataset(Path(tmp) / "missing")
def test_circle_extrude_is_valid_cdsl_11(self):
result = lower_model(parse_featurescript(SOURCE, "00000173"), {})
self.assertEqual(result.status, "converted_complete")
self.assertEqual(result.cdsl["schema_version"], "1.1.0")
self.assertEqual(result.cdsl["geometry"]["sketches"][0]["profile"]["radius_mm"], 9.53)
from engine.cdsl_engine.semantic_validation import validate_semantic_cdsl
self.assertTrue(validate_semantic_cdsl(result.cdsl)["future_rebuild_ready"])
def test_unsupported_operation_is_audited_not_invented(self):
source = SOURCE.replace('extrude(context, id + "F1",', 'shell(context, id + "F1",')
result = lower_model(parse_featurescript(source, "00000173"), {})
self.assertEqual(result.status, "deferred_no_executable_feature")
self.assertIsNone(result.cdsl)
self.assertEqual(result.diagnostics[0]["code"], "unsupported_operation")
def test_symmetric_cut_is_not_disguised_as_blind_cut(self):
source = SOURCE.replace('"depth":120 * mm', '"operationType":NewBodyOperationType.REMOVE, "depth":120 * mm, "symmetric":true')
result = lower_model(parse_featurescript(source, "symmetric-cut"), {})
self.assertIsNone(result.cdsl)
self.assertEqual(result.diagnostics[0]["code"], "unsupported_engine_capability")
self.assertEqual(result.diagnostics[0]["capability"], "extrude_cut_two_sided")
def test_open_nonconstruction_geometry_is_not_silently_dropped(self):
source = SOURCE.replace('skSolve(sketch);', 'skLineSegment(sketch, "open", {"start":v(0, 0) * mm, "end":v(20, 0) * mm}); skSolve(sketch);', 1)
result = lower_model(parse_featurescript(source, "open-profile"), {})
self.assertIsNone(result.cdsl)
self.assertEqual(result.diagnostics[0]["code"], "sketch_deferred")
self.assertIn("open non-construction", result.diagnostics[0]["message"])
def test_surface_revolve_is_not_disguised_as_solid_revolve(self):
root = Path(__file__).parents[2] / "data/cadfs-sample/CADFS_test"
feature = root / "featurescript_rp/0095/00957738.txt"
if not feature.exists(): self.skipTest("CADFS sample is not installed")
result = lower_model(parse_featurescript(feature.read_text(), "00957738"), {})
gap = next(item for item in result.diagnostics if item.get("feature_id") == "F2")
self.assertEqual(gap["capability"], "revolve_surface")
self.assertIsNone(result.cdsl)
def test_feature_face_profile_is_not_reused_as_original_sketch(self):
source = SOURCE.replace('qSketchRegion(id + "F0", true)', 'makeQuery(id+"F1.opExtrude","CAP_FACE",FACE,{"isStart":false})')
result = lower_model(parse_featurescript(source, "face-profile"), {})
self.assertIsNone(result.cdsl)
self.assertEqual(result.diagnostics[0]["code"], "unsupported_engine_capability")
self.assertIn("extrude_profile_topology:cap_face", result.diagnostics[0]["capability"])
def test_conversion_writes_status_and_sidecars(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp); source = root / "00000173.txt"; source.write_text(SOURCE)
sample = Sample("00000173", {"featurescript": str(source)}, {"featurescript": "x"})
status = convert_one(sample, root / "out", force=True)
directory = root / "out/samples/00000173"
self.assertEqual(status["conversion_status"], "converted_complete")
for name in ("candidate.cdsl.json", "history.json", "diagnostics.json", "status.json"):
self.assertTrue((directory / name).exists(), name)
self.assertEqual(json.loads((directory / "candidate.cdsl.json").read_text())["part_id"], "00000173")
if __name__ == "__main__": unittest.main()