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"