trikona / tests /test_kernel_assembly.py
disssid's picture
Assembly · Phase J2: expose asm in the kernel sandbox
2ce2625
Raw
History Blame Contribute Delete
2.19 kB
"""Phase J2 — kernel exposure of the assembly API (SPEC_ASSEMBLY.md §6, §8).
A generator may use the injected `asm` helpers; it still cannot import anything
outside the allowlist (asm is injected, not imported).
"""
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parent.parent
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from geometry import kernel, metrics, repair # noqa: E402
GEN_ASM = '''
def build(p):
cyl = asm.cylinder(r=1.0, h=2.0, name="cylinder")
cone = asm.cone(r=1.0, h=1.5, name="cone")
asm.attach(cone, "base", cyl, "top")
return asm.combine([cyl, cone])
'''
# A generator that tries to reach the assembly module by IMPORT (not the injected
# asm) must still be rejected by the allowlist.
GEN_IMPORT_GEOMETRY = '''
import geometry
def build(p):
return [[0,0,0],[1,0,0],[0,1,0]], [[0,1,2,"x"]]
'''
def test_asm_generator_runs_through_kernel():
V, F = kernel.run(GEN_ASM)
assert len(V) > 8 and len(F) > 8
cids = {f[3] for f in F}
assert "cylinder" in cids and "cone" in cids # two joined components
v, f = repair.repair(V, F, "composite")
assert metrics.passes(v, f, "composite")[0]
def test_asm_parts_are_joined():
# After mating, the cone base ring sits on the cylinder top — i.e. the meshes
# actually connect (not two disjoint blobs floating apart).
V, F = kernel.run(GEN_ASM)
ys = sorted(v[1] for v in V)
# cylinder spans y∈[-1,1]; cone sits above with apex highest, contiguous.
assert min(ys) < -0.9 and max(ys) > 1.0
def test_generator_cannot_import_geometry():
with pytest.raises(kernel.KernelError) as e:
kernel.run(GEN_IMPORT_GEOMETRY)
assert "disallowed import" in str(e.value)
def test_plain_generator_still_works():
# asm injection must not break a generator that doesn't use it.
code = ("def build(p):\n"
" v=[[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]]\n"
" return v,[[4,0,2,'f'],[4,2,1,'f'],[4,1,3,'f'],[4,3,0,'f'],"
"[5,2,0,'f'],[5,1,2,'f'],[5,3,1,'f'],[5,0,3,'f']]\n")
V, F = kernel.run(code)
assert len(V) == 6 and len(F) == 8