ifcurl/tests/test_sandbox.py
Bruno Postle 65a62ffc8b sandbox.py: subprocess isolation for ifcopenshell parse + render
All ifcopenshell calls (from_string, filter_elements, geom.iterator) now
run inside a short-lived child process via run_sandboxed().  A SIGSEGV or
SIGABRT in the child returns HTTP 422 instead of killing the service worker.
Configurable timeout (IFCURL_SANDBOX_TIMEOUT, default 120s) and optional
resource limits (IFCURL_SANDBOX_MEMORY_MB, IFCURL_SANDBOX_CPU_SECS).

The T3 GUID cache still works: the sandboxed pipeline returns resolved
GUIDs on selector miss so the parent can populate the cache; on hit the
parent passes cached GUIDs and the child converts them to step IDs.

Tests use a sync_sandbox fixture that runs run_sandboxed synchronously so
mock patches remain visible; four dedicated sandbox tests cover normal
return, exception propagation, segfault detection, and timeout.

Closes ifcurl-vm5.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 17:38:07 +01:00

50 lines
1.1 KiB
Python

"""Tests for ifcurl.sandbox — subprocess isolation for ifcopenshell calls."""
from __future__ import annotations
import ctypes
import os
import sys
import pytest
from ifcurl.sandbox import (
SandboxCrashError,
SandboxTimeoutError,
run_sandboxed,
)
def _return_value(x):
return x
def _raise_value_error(msg):
raise ValueError(msg)
def _segfault():
ctypes.string_at(0) # dereference NULL → SIGSEGV
def _sleep_forever():
import time
time.sleep(9999)
class TestRunSandboxed:
def test_returns_value(self):
assert run_sandboxed(_return_value, 42) == 42
def test_propagates_exception(self):
with pytest.raises(ValueError, match="bad input"):
run_sandboxed(_raise_value_error, "bad input")
@pytest.mark.skipif(sys.platform == "win32", reason="SIGSEGV test requires Unix")
def test_crash_raises_sandbox_crash_error(self):
with pytest.raises(SandboxCrashError):
run_sandboxed(_segfault)
def test_timeout_raises_sandbox_timeout_error(self):
with pytest.raises(SandboxTimeoutError):
run_sandboxed(_sleep_forever, timeout=1)