87 lines
3.5 KiB
Python
87 lines
3.5 KiB
Python
"""Tests for scripts/audit_test_sandbox_violations.py (Phase 2, FR4)."""
|
|
from __future__ import annotations
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def test_audit_runs_without_error() -> None:
|
|
"""The audit script runs and exits cleanly."""
|
|
result = subprocess.run(
|
|
[sys.executable, "scripts/audit_test_sandbox_violations.py"],
|
|
capture_output=True, text=True, cwd=str(Path(__file__).resolve().parent.parent)
|
|
)
|
|
assert result.returncode in (0, 1), f"Unexpected exit code: {result.returncode}"
|
|
|
|
|
|
def test_audit_flags_toml_basename_pattern() -> None:
|
|
"""A test source line with Path('manual_slop.toml') is flagged by the pattern."""
|
|
pattern = re.compile(r'Path\(["\'](?:manual_slop|config|credentials|presets|personas|tool_presets|workspace_profiles|project|manualslop_layout|manual_slop_history)\.toml["\']')
|
|
assert pattern.search('Path("manual_slop.toml").write_text("x")'), "Pattern should match"
|
|
|
|
|
|
def test_audit_flags_project_root_path() -> None:
|
|
"""A test source line with Path('C:/projects/...') is flagged."""
|
|
pattern = re.compile(r'Path\(["\']C:[/\\]+projects')
|
|
assert pattern.search('base_dir = Path("C:/projects/test")'), "Pattern should match"
|
|
|
|
|
|
def test_audit_flags_tempfile_mkdtemp() -> None:
|
|
"""A test source line with bare tempfile.mkdtemp() is flagged."""
|
|
pattern = re.compile(r"tempfile\.mk(?:dt|st)emp\(")
|
|
assert pattern.search('tmp = tempfile.mkdtemp()'), "Pattern should match"
|
|
assert pattern.search('tmp = tempfile.mkstemp()'), "Pattern should match"
|
|
|
|
|
|
def test_audit_flags_tests_artifacts_literal() -> None:
|
|
"""A test source line with Path('tests/artifacts/...') literal is flagged."""
|
|
pattern = re.compile(r'Path\(["\']tests/artifacts/')
|
|
assert pattern.search('p = Path("tests/artifacts/some_file.txt")'), "Pattern should match"
|
|
|
|
|
|
def test_audit_passes_clean_file() -> None:
|
|
"""A test source line using tmp_path passes the audit patterns."""
|
|
content = 'tmp_path.joinpath("foo.txt").write_text("x")\n'
|
|
patterns = [
|
|
re.compile(r'Path\(["\'](?:manual_slop|config)\.toml["\']'),
|
|
re.compile(r'Path\(["\']C:[/\\]+projects'),
|
|
re.compile(r'Path\(["\']tests/artifacts/'),
|
|
re.compile(r"tempfile\.mk(?:dt|st)emp\("),
|
|
]
|
|
for p in patterns:
|
|
assert not p.search(content), f"Pattern {p.pattern} should not match clean content"
|
|
|
|
|
|
def test_audit_subprocess_clean_dir_exits_zero() -> None:
|
|
"""The audit returns 0 on a clean test directory."""
|
|
tmp_dir = Path("tests/artifacts/_audit_subprocess_clean")
|
|
tmp_dir.mkdir(parents=True, exist_ok=True)
|
|
good = tmp_dir / "test_good.py"
|
|
good.write_text("def test_x(tmp_path): tmp_path.joinpath('f').write_text('x')\n", encoding="utf-8")
|
|
try:
|
|
result = subprocess.run(
|
|
[sys.executable, "scripts/audit_test_sandbox_violations.py", "--tests-dir", str(tmp_dir), "--strict"],
|
|
capture_output=True, text=True,
|
|
)
|
|
assert result.returncode == 0, f"Expected exit 0, got {result.returncode}: {result.stdout}"
|
|
finally:
|
|
good.unlink(missing_ok=True)
|
|
tmp_dir.rmdir()
|
|
|
|
|
|
def test_audit_subprocess_bad_dir_exits_one() -> None:
|
|
"""The audit returns 1 on a directory with a bad pattern."""
|
|
tmp_dir = Path("tests/artifacts/_audit_subprocess_bad")
|
|
tmp_dir.mkdir(parents=True, exist_ok=True)
|
|
bad = tmp_dir / "test_bad.py"
|
|
bad.write_text('Path("manual_slop.toml").write_text("x")\n', encoding="utf-8")
|
|
try:
|
|
result = subprocess.run(
|
|
[sys.executable, "scripts/audit_test_sandbox_violations.py", "--tests-dir", str(tmp_dir), "--strict"],
|
|
capture_output=True, text=True,
|
|
)
|
|
assert result.returncode == 1, f"Expected exit 1, got {result.returncode}"
|
|
finally:
|
|
bad.unlink(missing_ok=True)
|
|
tmp_dir.rmdir() |