88 lines
2.6 KiB
Python
88 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
import copy
|
|
import importlib.util
|
|
import json
|
|
from pathlib import Path
|
|
|
|
|
|
REPO = Path(__file__).resolve().parents[2]
|
|
MODEL_DIR = REPO / "models" / "lcd25-reducer" / "semantic-assembly"
|
|
SCHEMA_PATH = (
|
|
REPO
|
|
/ "designir-pipeline"
|
|
/ "contracts"
|
|
/ "assembly-designir-1.0.schema.json"
|
|
)
|
|
VALIDATOR_PATH = MODEL_DIR / "validate_assembly_design.py"
|
|
|
|
|
|
def load_validator():
|
|
spec = importlib.util.spec_from_file_location(
|
|
"assembly_design_validator", VALIDATOR_PATH
|
|
)
|
|
assert spec and spec.loader
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def load_json(path: Path):
|
|
return json.loads(path.read_text(encoding="utf-8"))
|
|
|
|
|
|
def test_lcd25_coordinate_free_base_model_is_valid():
|
|
validator = load_validator()
|
|
schema = load_json(SCHEMA_PATH)
|
|
payload = load_json(
|
|
MODEL_DIR / "lcd25-harmonic-reducer.assembly-designir.json"
|
|
)
|
|
report = validator.validate(payload, schema)
|
|
assert report["status"] == "pass"
|
|
assert report["coordinate_free"] is True
|
|
assert report["component_count"] == 10
|
|
assert report["relation_count"] == 15
|
|
|
|
|
|
def test_output_shaft_patch_preserves_coordinate_free_contract():
|
|
validator = load_validator()
|
|
schema = load_json(SCHEMA_PATH)
|
|
payload = load_json(
|
|
MODEL_DIR / "lcd25-harmonic-reducer.assembly-designir.json"
|
|
)
|
|
patch = load_json(MODEL_DIR / "variants" / "add-output-shaft.patch.json")
|
|
resolved = validator.apply_patch(payload, patch)
|
|
report = validator.validate(resolved, schema)
|
|
assert report["status"] == "pass"
|
|
assert report["coordinate_free"] is True
|
|
assert report["component_count"] == 11
|
|
assert "output_shaft" in {
|
|
component["id"] for component in resolved["components"]
|
|
}
|
|
assert "output_shaft" in next(
|
|
group["members"]
|
|
for group in resolved["kinematics"]["rigid_groups"]
|
|
if group["id"] == "output_group"
|
|
)
|
|
|
|
|
|
def test_authored_transform_is_rejected():
|
|
validator = load_validator()
|
|
schema = load_json(SCHEMA_PATH)
|
|
payload = load_json(
|
|
MODEL_DIR / "lcd25-harmonic-reducer.assembly-designir.json"
|
|
)
|
|
invalid = copy.deepcopy(payload)
|
|
invalid["components"][0]["transform"] = [
|
|
[1, 0, 0, 0],
|
|
[0, 1, 0, 0],
|
|
[0, 0, 1, 0],
|
|
]
|
|
report = validator.validate(invalid, schema)
|
|
assert report["status"] == "fail"
|
|
assert report["coordinate_free"] is False
|
|
assert any(
|
|
"coordinate placement key is forbidden" in failure
|
|
for failure in report["failures"]
|
|
)
|