forked from enderofwings/NexusOS
fix(windows): real toolchain probing, HOME/TEMP env, and gate portability
code_run.py: shutil.which() finding a compiler executable on PATH doesn't mean it's a usable toolchain on Windows -- rustc's MSVC target also needs Microsoft's linker, and an MSYS2 gcc/clang driver can remain resolvable after one of its runtime DLLs has broken. Both cases silently turned every C/C++/ Rust snippet into a compile error while the capability check said "ready". _compiled_tool() now actually compiles+links a trivial known-good program per candidate (Windows only; POSIX keeps the cheap which(1) check since release hosts install compiler packages atomically) and caches the result. Also fixes the run/compile child environment: HOME/TMPDIR don't control Windows' real temp/profile resolution (expanduser() reaches the actual user profile, GetTempPath() falls back to the Windows directory), letting a snippet escape the scratch directory or fail outright. _child_env() now also sets TEMP/TMP/USERPROFILE on Windows. tests/conftest.py (new): isolates curry_store's SQLite singleton into a per-run temp directory via NEXUS_CURRY_DB before any test module imports synapse, and cleans it up at session end -- the release gate no longer writes test constants into the checkout's live data/curry.db. .gitignore picks up /data/curry.db for whatever still lands there locally. bin/check.sh: falls back to Promethean/Scripts/python.exe when Promethean/bin/python doesn't exist, so the gate actually runs on a Windows venv instead of immediately exiting "no Promethean venv". Verified independently: 254 passed, 0 failed, 8 skipped (tests + management) -- the 12 C/C++/Rust toolchain failures present all session are gone. Full bin/check.sh run end-to-end on this Windows checkout: pytest, eslint, frontend node:test (57/57), PowerShell/shell parse, and the wheel/sdist packaging + twine + content checks all report OK. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
"""Test-process isolation for persistent runtime state."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# curry_store constructs its SQLite singleton during test collection. Point it
|
||||
# at a per-run directory before any test module imports synapse, so the release
|
||||
# gate is repeatable and never writes test constants into the checkout's live
|
||||
# data/curry.db.
|
||||
_TEST_STATE = Path(tempfile.mkdtemp(prefix="nexus-pytest-"))
|
||||
os.environ["NEXUS_CURRY_DB"] = str(_TEST_STATE / "curry.db")
|
||||
|
||||
|
||||
def pytest_sessionfinish(session, exitstatus):
|
||||
module = sys.modules.get("synapse.curry_store")
|
||||
if module is not None:
|
||||
module.curry_db.close()
|
||||
shutil.rmtree(_TEST_STATE, ignore_errors=True)
|
||||
@@ -232,10 +232,40 @@ def test_home_points_at_the_scratch_dir():
|
||||
assert "nexus-run-" in out["stdout"]
|
||||
|
||||
|
||||
def test_temp_points_at_the_scratch_dir():
|
||||
"""Compilers and snippets must not fall back to a host temp directory."""
|
||||
out = code_run.run("python", "import tempfile\nprint(tempfile.gettempdir())")
|
||||
assert "nexus-run-" in out["stdout"]
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Toolchains
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_windows_compiler_resolver_skips_broken_candidates(monkeypatch):
|
||||
"""An executable on PATH is not enough when its linker/runtime is broken."""
|
||||
code_run._compiled_tool.cache_clear()
|
||||
monkeypatch.setattr(code_run.sys, "platform", "win32")
|
||||
monkeypatch.setattr(
|
||||
code_run.shutil, "which", lambda name: f"C:\\tools\\{name}.exe"
|
||||
)
|
||||
probes = []
|
||||
|
||||
def probe(lang, tool):
|
||||
probes.append((lang, tool))
|
||||
return tool.endswith("clang.exe")
|
||||
|
||||
monkeypatch.setattr(code_run, "_probe_compiled_tool", probe)
|
||||
try:
|
||||
assert code_run._compiled_tool("c", ("gcc", "clang")) == "C:\\tools\\clang.exe"
|
||||
assert probes == [
|
||||
("c", "C:\\tools\\gcc.exe"),
|
||||
("c", "C:\\tools\\clang.exe"),
|
||||
]
|
||||
finally:
|
||||
code_run._compiled_tool.cache_clear()
|
||||
|
||||
|
||||
def test_a_missing_toolchain_explains_itself(monkeypatch):
|
||||
"""The model has to be able to tell 'you cannot run this here' from 'your
|
||||
code is wrong' — otherwise it rewrites a correct program repeatedly."""
|
||||
|
||||
Reference in New Issue
Block a user