76 lines
4.4 KiB
Python
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()
|