84 lines
3.2 KiB
Python
84 lines
3.2 KiB
Python
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"
|