189 lines
7.4 KiB
Python
189 lines
7.4 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
|
|
MODULE_PATH = Path(__file__).with_name("pi-sbx-profile.py")
|
|
SPEC = importlib.util.spec_from_file_location("pi_sbx_profile", MODULE_PATH)
|
|
if SPEC is None or SPEC.loader is None:
|
|
raise RuntimeError(f"Could not load profile resolver from {MODULE_PATH}")
|
|
MODULE = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(MODULE)
|
|
|
|
|
|
class PiSbxProfileTests(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.config = {
|
|
"defaultProfile": "pi-local",
|
|
"directories": {
|
|
"/srv/work": "pi-work",
|
|
"/srv/work/special": "pi-special",
|
|
},
|
|
"defaultRuntime": {
|
|
"nodeExecutable": "/usr/bin/node",
|
|
"piExecutable": "~/.bun/bin/pi",
|
|
"piAgentDirectory": "~/.pi/agent",
|
|
},
|
|
"profileRuntimes": {
|
|
"pi-work": {
|
|
"nodeExecutable": "/opt/node-22/bin/node",
|
|
"piAgentDirectory": "~/.pi/profiles/work",
|
|
}
|
|
},
|
|
}
|
|
|
|
def test_longest_directory_match_wins(self) -> None:
|
|
self.assertEqual(
|
|
MODULE.resolve_profile(self.config, Path("/srv/work/special/repository")),
|
|
("pi-special", "directory", Path("/srv/work/special")),
|
|
)
|
|
|
|
def test_directory_matches_descendants(self) -> None:
|
|
self.assertEqual(
|
|
MODULE.resolve_profile(self.config, Path("/srv/work/code/repository")),
|
|
("pi-work", "directory", Path("/srv/work")),
|
|
)
|
|
|
|
def test_directory_does_not_match_similar_prefix(self) -> None:
|
|
self.assertEqual(
|
|
MODULE.resolve_profile(self.config, Path("/srv/worker/repository")),
|
|
("pi-local", "default", None),
|
|
)
|
|
|
|
def test_profile_runtime_overrides_defaults(self) -> None:
|
|
self.assertEqual(
|
|
MODULE.runtime_for_profile(self.config, "pi-work"),
|
|
{
|
|
"nodeExecutable": "/opt/node-22/bin/node",
|
|
"piExecutable": str(Path("~/.bun/bin/pi").expanduser()),
|
|
"piAgentDirectory": str(Path("~/.pi/profiles/work").expanduser()),
|
|
},
|
|
)
|
|
|
|
def test_default_runtime_is_used_without_override(self) -> None:
|
|
runtime = MODULE.runtime_for_profile(self.config, "pi-special")
|
|
self.assertEqual(runtime["nodeExecutable"], "/usr/bin/node")
|
|
self.assertEqual(runtime["piAgentDirectory"], str(Path("~/.pi/agent").expanduser()))
|
|
|
|
def test_configuration_requires_complete_default_runtime(self) -> None:
|
|
del self.config["defaultRuntime"]["piExecutable"]
|
|
with self.assertRaisesRegex(ValueError, "missing fields: piExecutable"):
|
|
MODULE.validate_config(self.config)
|
|
|
|
def test_configuration_rejects_noncanonical_directory(self) -> None:
|
|
self.config["directories"] = {"~/work": "pi-local"}
|
|
with self.assertRaisesRegex(ValueError, "canonical absolute physical paths"):
|
|
MODULE.validate_config(self.config)
|
|
|
|
def test_relative_xdg_config_home_is_ignored(self) -> None:
|
|
original_xdg = os.environ.get("XDG_CONFIG_HOME")
|
|
original_override = os.environ.pop("PI_SBX_CONFIG", None)
|
|
os.environ["XDG_CONFIG_HOME"] = "repository-controlled"
|
|
try:
|
|
self.assertEqual(MODULE.config_path(), MODULE.DEFAULT_CONFIG_PATH.expanduser())
|
|
finally:
|
|
if original_xdg is None:
|
|
os.environ.pop("XDG_CONFIG_HOME", None)
|
|
else:
|
|
os.environ["XDG_CONFIG_HOME"] = original_xdg
|
|
if original_override is not None:
|
|
os.environ["PI_SBX_CONFIG"] = original_override
|
|
|
|
def test_relative_config_override_is_rejected(self) -> None:
|
|
original_override = os.environ.get("PI_SBX_CONFIG")
|
|
os.environ["PI_SBX_CONFIG"] = "config.json"
|
|
try:
|
|
with self.assertRaisesRegex(ValueError, "PI_SBX_CONFIG must be an absolute path"):
|
|
MODULE.config_path()
|
|
finally:
|
|
if original_override is None:
|
|
os.environ.pop("PI_SBX_CONFIG", None)
|
|
else:
|
|
os.environ["PI_SBX_CONFIG"] = original_override
|
|
|
|
def test_save_and_load_configuration(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
path = Path(directory) / "pi-sbx" / "config.json"
|
|
MODULE.save_config(self.config, path)
|
|
|
|
self.assertEqual(MODULE.load_config(path), self.config)
|
|
self.assertEqual(path.stat().st_mode & 0o777, 0o600)
|
|
self.assertEqual(json.loads(path.read_text(encoding="utf-8")), self.config)
|
|
|
|
def test_set_without_path_assigns_current_directory(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
temporary = Path(directory)
|
|
config_path = temporary / "config.json"
|
|
workdir = temporary / "repository"
|
|
binary_directory = temporary / "bin"
|
|
workdir.mkdir()
|
|
binary_directory.mkdir()
|
|
MODULE.save_config(self.config, config_path)
|
|
|
|
nono = binary_directory / "nono"
|
|
nono.write_text("#!/bin/sh\nexit 0\n", encoding="utf-8")
|
|
nono.chmod(0o755)
|
|
environment = os.environ.copy()
|
|
environment["PI_SBX_CONFIG"] = str(config_path)
|
|
environment["PATH"] = f"{binary_directory}:{environment['PATH']}"
|
|
|
|
result = subprocess.run(
|
|
[str(MODULE_PATH), "set", "pi-special"],
|
|
cwd=workdir,
|
|
env=environment,
|
|
check=True,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
|
|
self.assertEqual(result.stdout.strip(), f"{workdir} -> pi-special")
|
|
self.assertEqual(MODULE.load_config(config_path)["directories"][str(workdir)], "pi-special")
|
|
|
|
subprocess.run(
|
|
[str(MODULE_PATH), "unset"],
|
|
cwd=workdir,
|
|
env=environment,
|
|
check=True,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
self.assertNotIn(str(workdir), MODULE.load_config(config_path)["directories"])
|
|
|
|
def test_legacy_set_root_command_assigns_current_directory(self) -> None:
|
|
with tempfile.TemporaryDirectory() as directory:
|
|
temporary = Path(directory)
|
|
config_path = temporary / "config.json"
|
|
workdir = temporary / "repository"
|
|
binary_directory = temporary / "bin"
|
|
workdir.mkdir()
|
|
binary_directory.mkdir()
|
|
MODULE.save_config(self.config, config_path)
|
|
|
|
nono = binary_directory / "nono"
|
|
nono.write_text("#!/bin/sh\nexit 0\n", encoding="utf-8")
|
|
nono.chmod(0o755)
|
|
environment = os.environ.copy()
|
|
environment["PI_SBX_CONFIG"] = str(config_path)
|
|
environment["PATH"] = f"{binary_directory}:{environment['PATH']}"
|
|
|
|
subprocess.run(
|
|
[str(Path(__file__).with_name("orca-nono-profile.py")), "set-root", "pi-special"],
|
|
cwd=workdir,
|
|
env=environment,
|
|
check=True,
|
|
capture_output=True,
|
|
text=True,
|
|
)
|
|
|
|
self.assertEqual(MODULE.load_config(config_path)["directories"][str(workdir)], "pi-special")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|