|
6 | 6 | import json |
7 | 7 | import os |
8 | 8 | from pathlib import Path |
| 9 | +import shutil |
| 10 | +import subprocess |
9 | 11 | import sys |
10 | 12 | import tempfile |
11 | 13 | import time |
@@ -397,6 +399,32 @@ def test_packager_runs_audit_before_outer_signature(self): |
397 | 399 | "--maximum-audit-entries", "--maximum-audit-evidence-bytes"): |
398 | 400 | self.assertIn(option, source) |
399 | 401 |
|
| 402 | + def test_packager_import_does_not_mutate_installed_tools(self): |
| 403 | + with tempfile.TemporaryDirectory(prefix="webscene immutable tools ") as temporary: |
| 404 | + tools = Path(temporary) / "share/webscene/tools" |
| 405 | + tools.mkdir(parents=True) |
| 406 | + for name in ("package_macos.py", "audit_macos_bundle.py"): |
| 407 | + shutil.copy2(ROOT / "src/WebScene.Sdk/tools" / name, tools / name) |
| 408 | + before = { |
| 409 | + path.relative_to(tools).as_posix(): path.read_bytes() |
| 410 | + for path in tools.rglob("*") if path.is_file() |
| 411 | + } |
| 412 | + started = time.monotonic() |
| 413 | + for _ in range(100): |
| 414 | + completed = subprocess.run( |
| 415 | + [sys.executable, str(tools / "package_macos.py"), "--help"], |
| 416 | + stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, |
| 417 | + text=True, timeout=10) |
| 418 | + self.assertEqual(completed.returncode, 0, completed.stderr) |
| 419 | + elapsed = time.monotonic() - started |
| 420 | + after = { |
| 421 | + path.relative_to(tools).as_posix(): path.read_bytes() |
| 422 | + for path in tools.rglob("*") if path.is_file() |
| 423 | + } |
| 424 | + self.assertEqual(after, before) |
| 425 | + self.assertFalse(any(path.name == "__pycache__" for path in tools.rglob("*"))) |
| 426 | + self.assertLess(elapsed, 15.0) |
| 427 | + |
400 | 428 | def test_single_architecture_normalization_is_atomic_and_idempotent(self): |
401 | 429 | extension_relative = "Contents/PlugIns/sample.node" |
402 | 430 | self.fixture.extension.write_bytes(b"\xca\xfe\xba\xbf" + bytes(range(128))) |
|
0 commit comments