038d38ed98
- 新增 loft、双向切除、through-all/up-to-next 等 CADFS lowering 与 engine 支持 - 支持多种 reference plane、B-spline profile 和 circular pattern replay - 保留 transform 历史,并烘焙安全的单源平移/旋转变换 - 改进 selector 绑定、拓扑快照和 pattern 变换处理 - 建立 17 个代表样本的转换、重建与比较回归工具链 - 补充 schema、author guidance、运行时和几何回归测试
74 lines
3.6 KiB
Python
74 lines
3.6 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from cadfs_to_cdsl.regression import build_regression_manifest, regression_sample_ids
|
|
|
|
|
|
class RegressionSelectionTests(unittest.TestCase):
|
|
def _sample(
|
|
self,
|
|
root: Path,
|
|
sample_id: str,
|
|
*,
|
|
operation: str,
|
|
entity: str | None = None,
|
|
atomic: str | None = None,
|
|
capability: str | None = None,
|
|
rebuilt: bool = False,
|
|
) -> None:
|
|
directory = root / "samples" / sample_id
|
|
directory.mkdir(parents=True)
|
|
history = [{"operation": operation}]
|
|
if entity:
|
|
history[0]["entities"] = [{"operation": entity}]
|
|
(directory / "history.json").write_text(json.dumps(history), encoding="utf-8")
|
|
if atomic:
|
|
(directory / "candidate.cdsl.json").write_text(json.dumps({"features": [{"atomic_id": atomic}]}), encoding="utf-8")
|
|
diagnostics = [] if not capability else [{"code": "unsupported_engine_capability", "capability": capability}]
|
|
(directory / "diagnostics.json").write_text(json.dumps(diagnostics), encoding="utf-8")
|
|
status = {"status": "rebuilt_approximate" if rebuilt else "converted_partial"}
|
|
if rebuilt:
|
|
status["rebuild_status"] = "rebuilt"
|
|
(directory / "status.json").write_text(json.dumps(status), encoding="utf-8")
|
|
|
|
def test_manifest_covers_every_observed_signal_and_keeps_engine_pool_buildable(self) -> None:
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
output = Path(temporary)
|
|
self._sample(output, "00000001", operation="extrude", entity="skLineSegment", atomic="extrude_add_blind", rebuilt=True)
|
|
self._sample(output, "00000002", operation="loft", entity="skFitSpline", capability="loft")
|
|
self._sample(output, "00000003", operation="revolve", entity="skCircle", atomic="revolve_add", rebuilt=True)
|
|
|
|
manifest = build_regression_manifest(output)
|
|
|
|
self.assertEqual(manifest["selected_ids"], ["00000001", "00000002", "00000003"])
|
|
self.assertEqual(set(manifest["coverage"]), {
|
|
"engine_atomic:extrude_add_blind", "engine_atomic:revolve_add",
|
|
"sketch_entity:skCircle", "sketch_entity:skFitSpline", "sketch_entity:skLineSegment",
|
|
"source_operation:extrude", "source_operation:loft", "source_operation:revolve",
|
|
"unsupported_capability:loft",
|
|
})
|
|
self.assertEqual(regression_sample_ids_from_manifest(manifest, "engine"), ["00000001", "00000003"])
|
|
self.assertEqual(manifest["engine_baseline_atomic_ids"], ["extrude_add_blind", "revolve_add"])
|
|
self.assertEqual(manifest["engine_diagnostic_only_atomic_ids"], [])
|
|
|
|
def test_manifest_reader_rejects_unknown_tier(self) -> None:
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
root = Path(temporary)
|
|
self._sample(root, "00000001", operation="extrude", atomic="extrude_add_blind", rebuilt=True)
|
|
manifest_path = root / "manifest.json"
|
|
manifest_path.write_text(json.dumps(build_regression_manifest(root)), encoding="utf-8")
|
|
self.assertEqual(regression_sample_ids(manifest_path, "engine"), ["00000001"])
|
|
with self.assertRaisesRegex(ValueError, "Unknown regression tier"):
|
|
regression_sample_ids(manifest_path, "not-a-tier")
|
|
|
|
|
|
def regression_sample_ids_from_manifest(manifest: dict, tier: str) -> list[str]:
|
|
return sorted(
|
|
entry["sample_id"] for entry in manifest["entries"]
|
|
if tier == "all" or tier in entry["tiers"]
|
|
)
|