Skip to main content

crashtest.behavior

Differential execution on the real HashLink runtime, never an emulated fallback.

Fixtures must expose return values, mutations and caught exceptions through output. Only terminating, repeatable observations can pass; unhandled errors, missing tools, output floods and timeouts fail closed. This is a corpus oracle, not equivalence proof for unexecuted branches or nondeterministic/interactive programs.

class BehavioralComparison

passed: bool

original: Execution

recompiled: Execution

error: str | None

error = None

runtime: str

runtime = 'HashLink'

exemption_reason: str | None

exemption_reason = None

to_json

def to_json() -> dict

from_json

classmethod

@classmethod
def from_json(data: dict) -> BehavioralComparison

init

def __init__(passed: bool, original: Execution, recompiled: Execution, error: str | None = None, runtime: str = 'HashLink', exemption_reason: str | None = None) -> None

class Execution

stdout: str

stdout = ''

stderr: str

stderr = ''

returncode: int | None

returncode = None

error: str | None

error = None

init

def __init__(stdout: str = '', stderr: str = '', returncode: int | None = None, error: str | None = None) -> None

compare_programs

def compare_programs(original: Path, recompiled: Path, class_name: str, timeout: float = 5.0) -> BehavioralComparison

compile_haxe

def compile_haxe(source: str, class_name: str, directory: Path) -> tuple[Path, str | None]

Compile one self-contained Haxe module for HashLink, retaining its artifact.

execute

def execute(command: list[str], cwd: str, timeout: float = 5.0) -> Execution

Run with no input, isolated cwd, bounded output, and a hard deadline.

normalize_positions

def normalize_positions(text: str, class_name: str) -> str

Strip source positions that only encode the module's own layout.

The fixture is compiled from tests/haxe/<Class>.hx and the decompiled program from <Class>.hx in a sandbox, and the decompiled source has its own line numbering, so neither trace prefixes (<Class>.hx:12: ) nor stack frames (Called from $C.main(<Class>.hx:12)) are comparable. Everything else — values, messages, frame order, function names — is.

resolve_hl_runtime

def resolve_hl_runtime() -> str | None

Find the HashLink runtime to execute against.

HL_RUNTIME (an absolute path) always wins when set, e.g. for CI or a non-standard install. Otherwise, hl on PATH is used directly - no env var required for the common case of a normal local HashLink install.