Newer
Older
navi-1 / mcp-servers / navi-3d / tests / unit / test_model_compile.py
"""Unit tests for model_compile."""

import asyncio
import shutil

import pytest

from app.config import Settings
from app.model_compile import _collect_diagnostics, compile_scad

HAS_OPENSCAD = shutil.which("openscad") is not None


def test_collect_diagnostics_keeps_actionable_lines():
    stderr = (
        "Geometries in cache: 1\n"
        "Geometry cache size in bytes: 728\n"
        "ECHO: \"bbox_x\", 52\n"
        "WARNING: Object may not be a valid 2-manifold and may need repair!\n"
        "CGAL Polyhedrons in cache: 0\n"
        "CGAL cache size in bytes: 0\n"
        "CGAL Cache insert: difference(){cube(size=[40,20,4],center= (46928 bytes)\n"
        "CGAL Cache hit: difference(){cube(size=[40,20,4],center= (46928 bytes)\n"
        "Total rendering time: 0:00:00.123\n"
        "   Top level object is a 3D object:\n"
        "   Facets:          6\n"
    )
    text = _collect_diagnostics(stderr)

    assert 'ECHO: "bbox_x", 52' in text
    assert "WARNING" in text
    assert "Top level object is a 3D object" in text
    assert "Facets:" in text
    for noise in (
        "Geometries in cache",
        "cache size in bytes",
        "CGAL Cache insert",
        "CGAL Cache hit",
        "Total rendering time",
    ):
        assert noise not in text


def test_collect_diagnostics_truncates():
    text = _collect_diagnostics("ECHO: \"x\", 1\n" * 1000, limit=100)

    assert len(text) <= 100 + len("\n… (diagnostics truncated)")
    assert text.endswith("(diagnostics truncated)")


@pytest.mark.skipif(not HAS_OPENSCAD, reason="openscad is not installed")
def test_compile_surfaces_echo_and_facets(tmp_path, monkeypatch):
    monkeypatch.setenv("SESSION_FILES_DIR", str(tmp_path))
    session = tmp_path / "s"
    session.mkdir()
    (session / "part.scad").write_text(
        'echo("bbox_x", 12);\ncube([12, 8, 4]);\n',
        encoding="utf-8",
    )

    result = asyncio.run(compile_scad(Settings(), "s", "part.scad", "part.stl"))

    assert result["success"] is True
    assert 'ECHO: "bbox_x", 12' in result["output"]
    assert "Facets:" in result["output"]
    assert "ECHO" in result["metadata"]["diagnostics"]


@pytest.mark.skipif(not HAS_OPENSCAD, reason="openscad is not installed")
def test_failed_assert_stops_compile_with_its_message(tmp_path, monkeypatch):
    monkeypatch.setenv("SESSION_FILES_DIR", str(tmp_path))
    session = tmp_path / "s"
    session.mkdir()
    (session / "part.scad").write_text(
        "assert(52 <= 50, \"interface does not fit: 52 > 50\");\ncube([10, 10, 10]);\n",
        encoding="utf-8",
    )

    result = asyncio.run(compile_scad(Settings(), "s", "part.scad", "part.stl"))

    assert result["success"] is False
    assert result["error"] == "openscad_compile_error"
    assert "interface does not fit: 52 > 50" in result["output"]
    assert not (session / "part.stl").exists()