Files
cdsl-cad/backend/tests/test_authoring_contract.py

82 lines
3.6 KiB
Python

import math
import pytest
from app.cad_agent.application.authoring_contract import AuthoringDocument
from app.cad_agent.application.authoring_compiler import AuthoringCompiler, AuthoringCompileError
def test_model_cannot_submit_runtime_identity():
with pytest.raises(ValueError, match="AUTHOR_FORBIDDEN_FIELD"):
AuthoringDocument.model_validate({"feature_id": "feature_001", "bodies": []})
@pytest.mark.parametrize("field", ["task_id", "revision_id", "stable_id", "selector_tokens", "selector token", "host_face", "mirror_plane"])
def test_model_cannot_submit_any_internal_identity_variant(field):
with pytest.raises(ValueError, match="AUTHOR_FORBIDDEN_FIELD"):
AuthoringDocument.model_validate({field: "internal", "bodies": []})
def test_authoring_rejects_non_mm_and_non_finite_values():
with pytest.raises(ValueError):
AuthoringDocument.model_validate({"units": "in", "bodies": []})
with pytest.raises(ValueError, match="non-finite"):
AuthoringDocument.model_validate({"bodies": [{"name": "main", "features": [{"name": "base", "operation": "box_add", "params": {"length_mm": math.nan}}]}]})
@pytest.mark.parametrize("sketch", [
{
"workplane": {"origin_mm": [0, 0, 0], "x_dir": [1, 0, 0], "normal": [0, 0, 1]},
"profiles": [{"type": "circle", "diameter_mm": 20}],
},
{
"workplane": {"origin_mm": [0, 0, 0], "x_dir": [1, 0, 0], "normal": [0, 0, 1]},
"profile": {"type": "circle", "radius_mm": 10},
},
])
def test_authoring_rejects_runtime_or_ambiguous_sketch_shapes(sketch):
with pytest.raises(ValueError):
AuthoringDocument.model_validate({
"bodies": [{"name": "main", "features": [{
"name": "base", "operation": "extrude_add_blind", "params": {"distance_mm": 8}, "sketch": sketch,
}]}],
})
def test_authoring_rejects_selector_fields_that_are_not_declarative_source_intent():
with pytest.raises(ValueError):
AuthoringDocument.model_validate({
"bodies": [{"name": "main", "features": [{
"name": "base", "operation": "cylinder_add", "params": {},
"selectors": [{"kind": "face", "source": "other.top_planar_face", "role": "host_face"}],
}]}],
})
def test_compiler_assigns_deterministic_ids_and_orders_dependencies():
document = {"bodies": [{"name": "main", "features": [
{"name": "hole", "operation": "hole_blind", "depends_on": ["base"]},
{"name": "base", "operation": "extrude_add_blind"},
]}]}
runtime, audit = AuthoringCompiler(lambda operation: {"atomic_id": operation}).compile(document)
assert [item["id"] for item in runtime["features"]] == ["feature_002", "feature_001"]
assert runtime["features"][1]["depends_on"] == ["feature_002"]
assert audit["feature_ids"] == {"hole": "feature_001", "base": "feature_002"}
def test_compiler_rejects_unknown_operation():
with pytest.raises(AuthoringCompileError) as error:
AuthoringCompiler(lambda _: (_ for _ in ()).throw(ValueError("unknown"))).compile({
"bodies": [{"name": "main", "features": [{"name": "base", "operation": "bad"}]}]
})
assert error.value.code == "OPERATION_UNSUPPORTED"
def test_compiler_preserves_the_forbidden_field_error_code():
with pytest.raises(AuthoringCompileError) as error:
AuthoringCompiler(lambda operation: {"atomic_id": operation}).compile({
"bodies": [{"name": "main", "features": [{"name": "base", "operation": "box_add", "params": {}}]}],
"feature_id": "feature_001",
})
assert error.value.code == "AUTHOR_FORBIDDEN_FIELD"