from __future__ import annotations import importlib.util import os from pathlib import Path import shutil import subprocess import sys import pytest PROJECT_ROOT = Path(__file__).resolve().parents[2] HARNESS_RELATIVE = Path("测试相关资料/如何测试/本机测试环境/local_test.py") @pytest.fixture def relocated_harness(tmp_path): original = PROJECT_ROOT / HARNESS_RELATIVE if not original.is_file() and os.environ.get("MATRIX_SOURCE_ONLY_UPDATE_TESTS") == "1": pytest.skip("source-only update payload intentionally omits the workstation harness") root = tmp_path / "独立 工作区" script = root / HARNESS_RELATIVE script.parent.mkdir(parents=True) shutil.copyfile(original, script) source = root / "核桃派软件源代码" (source / "app").mkdir(parents=True) for name in ("requirements.txt", "requirements-dev.txt"): (source / name).write_text("", encoding="utf-8") spec = importlib.util.spec_from_file_location("relocated_local_test", script) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return root, module def test_harness_locates_relocated_source_from_unrelated_cwd(relocated_harness, tmp_path): root, harness = relocated_harness probe = ( "import runpy, sys; from pathlib import Path; " "h = runpy.run_path(sys.argv[1]); h['_validate_layout'](); " "assert h['WORKSPACE_ROOT'] == Path(sys.argv[2]); " "assert h['SOURCE_DIR'] == Path(sys.argv[2]) / '核桃派软件源代码'" ) subprocess.run( [sys.executable, "-c", probe, str(root / HARNESS_RELATIVE), str(root)], cwd=tmp_path, check=True, ) def test_clean_keeps_environment_and_manual_data_in_relocated_workspace(relocated_harness): root, harness = relocated_harness keep = { harness.VENV_PYTHON: b"interpreter sentinel", harness.REQUIREMENTS_STAMP: b"requirements sentinel", harness.DATA_DIR / "config.json": b"manual config sentinel", harness.DATA_DIR / "templates" / "example.json": b"manual template sentinel", } for path, content in keep.items(): path.parent.mkdir(parents=True, exist_ok=True) path.write_bytes(content) for directory in (harness.WORK_DIR, harness.DATA_DIR / "runtime", harness.SOURCE_DIR / "app/__pycache__"): directory.mkdir(parents=True) (directory / "temporary").write_bytes(b"temporary") harness.clean() assert all(path.read_bytes() == content for path, content in keep.items()) assert not harness.WORK_DIR.exists() assert not (harness.DATA_DIR / "runtime").exists() assert not (harness.SOURCE_DIR / "app/__pycache__").exists() with pytest.raises(harness.HarnessError): harness._assert_within(root.parent / "outside", root) def test_clean_rejects_outside_target_before_deleting(relocated_harness, tmp_path, monkeypatch): _, harness = relocated_harness outside = tmp_path / "outside" outside.mkdir() marker = outside / "preserve" marker.write_bytes(b"unchanged") monkeypatch.setattr(harness, "WORK_DIR", outside) with pytest.raises(harness.HarnessError): harness.clean() assert marker.read_bytes() == b"unchanged"