This is the long awaited refactor of the NixSettings. It allows one to set, unset and update any and all settings with a neat and easy-to-use interface closes #846 Change-Id: Id4cfb5f853cc1168b506a1f6f405076f3a7cab65
150 lines
4.8 KiB
Python
150 lines
4.8 KiB
Python
import stat
|
|
import sys
|
|
import pytest
|
|
import signal
|
|
from pathlib import Path
|
|
from textwrap import dedent
|
|
from testlib.fixtures.env import ManagedEnv
|
|
from testlib.fixtures.nix import Nix
|
|
|
|
COMMANDS = ["copy-closure", "collect-garbage"]
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def custom_sub_command_path(tmp_path_factory: pytest.TempPathFactory) -> Path:
|
|
return tmp_path_factory.mktemp(__name__)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def failing_sub_command_path(tmp_path_factory: pytest.TempPathFactory) -> Path:
|
|
return tmp_path_factory.mktemp(__name__ + "-failing")
|
|
|
|
|
|
@pytest.fixture(scope="module", params=COMMANDS)
|
|
def custom_sub_command(request: pytest.FixtureRequest, custom_sub_command_path: Path) -> str:
|
|
# Create an external command that is an alias of an existing one
|
|
lix_cmd = request.param
|
|
|
|
executable = custom_sub_command_path / f"lix-{lix_cmd}"
|
|
executable.write_text(
|
|
dedent(f"""\
|
|
#!{sys.executable}
|
|
import os, sys
|
|
# Start with args[0] set to the actual nix command used for testing
|
|
# as we are not making Lix variants of those.
|
|
os.execvp("nix", [ "nix-{lix_cmd}" ] + sys.argv[1:])
|
|
""")
|
|
)
|
|
executable.chmod(stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
|
|
|
|
return lix_cmd
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def failing_sub_command(failing_sub_command_path: Path, custom_sub_command: str) -> str:
|
|
# Create an external command that will intentionally cause an error
|
|
executable = failing_sub_command_path / f"lix-{custom_sub_command}"
|
|
executable.write_text(
|
|
dedent(f"""\
|
|
#!{sys.executable}
|
|
import sys
|
|
sys.exit(42)
|
|
""")
|
|
)
|
|
executable.chmod(stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
|
|
|
|
return custom_sub_command
|
|
|
|
|
|
@pytest.fixture
|
|
def path(custom_sub_command_path: Path, env: ManagedEnv):
|
|
"""Provide a modified search path"""
|
|
env.path.append("/some/incorrect")
|
|
env.path.append("/location/for/fun")
|
|
env.path.append(str(custom_sub_command_path))
|
|
|
|
|
|
@pytest.fixture
|
|
def path_with_failure(
|
|
request: pytest.FixtureRequest,
|
|
custom_sub_command_path: Path,
|
|
failing_sub_command_path: Path,
|
|
env: ManagedEnv,
|
|
):
|
|
"""
|
|
Provide a search path with failing binaries inserted in the specified position
|
|
"""
|
|
(first, fail) = request.param
|
|
|
|
command_path = [str(custom_sub_command_path), str(failing_sub_command_path)]
|
|
if fail:
|
|
command_path.reverse()
|
|
|
|
if first:
|
|
env.path.prepend(command_path[1])
|
|
env.path.prepend(command_path[0])
|
|
else:
|
|
env.path.append(command_path[0])
|
|
env.path.append(command_path[1])
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("nix_exe", "flag", "expected"),
|
|
[("nix", False, 1), ("lix", False, 1), ("nix", True, 1), ("lix", True, 0)],
|
|
)
|
|
@pytest.mark.usefixtures("path")
|
|
def test_sub_commands(nix: Nix, custom_sub_command: str, nix_exe: str, flag: bool, expected: int):
|
|
if flag:
|
|
nix.settings.add_xp_feature("lix-custom-sub-commands")
|
|
|
|
# Test custom sub commands in various configurations
|
|
nix.nix([custom_sub_command, "--version"], nix_exe=nix_exe).run().expect(expected)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("path_with_failure", "expected"),
|
|
[((True, True), 42), ((True, False), 0), ((False, True), 42), ((False, False), 0)],
|
|
indirect=["path_with_failure"],
|
|
)
|
|
@pytest.mark.usefixtures("path_with_failure")
|
|
def test_sub_command_path_order(nix: Nix, failing_sub_command: str, expected: int):
|
|
# Test handling of the order of the path for custom sub commands
|
|
# Incidentally also tests passing through exit codes
|
|
nix.settings.add_xp_feature("lix-custom-sub-commands")
|
|
nix.nix([failing_sub_command, "--version"], nix_exe="lix").run().expect(expected)
|
|
|
|
|
|
@pytest.mark.skip(
|
|
reason="TODO(raito): we do not support auto completion for custom sub commands for now"
|
|
)
|
|
def test_custom_sub_commands_auto_completion(nix: Nix, tmp_path: Path): ...
|
|
|
|
|
|
@pytest.mark.skip(
|
|
reason="TODO(raito): we do not test flag handling for custom sub commands for now"
|
|
)
|
|
def test_custom_sub_command_flag_handling(nix: Nix, tmp_path: Path):
|
|
# Short, long and multiple flags should be tested as well.
|
|
# `--` special flag
|
|
# test positional arguments, but only `nix-copy-closure` implements some, and it's pesky to test here.
|
|
...
|
|
|
|
|
|
@pytest.mark.usefixtures("path")
|
|
def test_custom_sub_command_signals(nix: Nix, custom_sub_command_path: Path):
|
|
command = custom_sub_command_path / "lix-signals"
|
|
command.write_text(
|
|
dedent(f"""\
|
|
#!{sys.executable}
|
|
import signal
|
|
print(signal.pthread_sigmask(signal.SIG_BLOCK, []))
|
|
""")
|
|
)
|
|
command.chmod(stat.S_IXUSR | stat.S_IRUSR | stat.S_IWUSR)
|
|
|
|
current_mask = signal.pthread_sigmask(signal.SIG_BLOCK, [])
|
|
nix.settings.add_xp_feature("lix-custom-sub-commands")
|
|
result = nix.nix(["signals"], nix_exe="lix").run()
|
|
result.ok()
|
|
assert result.stdout_s.strip() == str(current_mask)
|