f2: add mark for nix settings defaults and use it

this fixes a large portion of tests currently marked no_daemon. most of
them only needed to set some trusted settings, which is easily done now

Change-Id: Id5a5ee94951cdc92bddd2264c738ca4f98980c8b
This commit is contained in:
eldritch horrors
2026-07-12 20:28:05 +02:00
parent 527ecba696
commit 1657d0eb47
8 changed files with 53 additions and 31 deletions
@@ -38,7 +38,7 @@ def test_j0_without_remotes_fails(nix: Nix):
)
@pytest.mark.no_daemon
@pytest.mark.nix_settings(trusted_users="*")
def test_j0_with_mismatched_remotes_fails(nix: Nix):
remote = f"ssh://localhost?remote-store={nix.env.dirs.home}/machine1"
result = nix.nix_build(["-j0", "--expr", drv, "--builders", remote]).run().expect(1)
@@ -48,7 +48,7 @@ def test_j0_with_mismatched_remotes_fails(nix: Nix):
)
@pytest.mark.no_daemon
@pytest.mark.nix_settings(trusted_users="*")
@with_files({"config.nix": get_global_asset("config.nix"), "default.nix": File(local_drv)})
def test_j0_without_local_jobs(nix: Nix):
result = nix.nix_build(["-j0", "--extra-local-jobs", "0"]).run().expect(1)
+4 -14
View File
@@ -56,7 +56,7 @@ def _builders(proto: str, flags: list[str], env: ManagedEnv) -> str:
""")
@pytest.mark.no_daemon
@pytest.mark.nix_settings(trusted_users="*", system_features=["bar"])
@pytest.mark.full_sandbox
@with_files(
{
@@ -66,17 +66,7 @@ def _builders(proto: str, flags: list[str], env: ManagedEnv) -> str:
)
def test_remote_trustless_unsigned(nix: Nix, env: ManagedEnv, busybox_args: list[str]):
# We first build a dependency of the derivation we eventually want to build.
nix.nix_build(
[
"build-hook.nix",
"-A",
"passthru.input2",
*busybox_args,
"--option",
"system-features",
"bar",
]
).run().ok()
nix.nix_build(["build-hook.nix", "-A", "passthru.input2", *busybox_args]).run().ok()
# Now when we go to build that downstream derivation, Lix will try to
# copy our already-build `input2` to the remote store. That store object
@@ -99,7 +89,7 @@ def test_remote_trustless_unsigned(nix: Nix, env: ManagedEnv, busybox_args: list
)
@pytest.mark.no_daemon
@pytest.mark.nix_settings(trusted_users="*")
@pytest.mark.full_sandbox
@pytest.mark.parametrize(
("protocol", "flags"), [("ssh", []), ("ssh-ng", []), ("ssh-ng", ["--force-untrusted"])]
@@ -129,7 +119,7 @@ def test_remote_trustless_ia(
assert nix.physical_store_path_for(out_path).read_text() == "FOO BAR BAZ\n"
@pytest.mark.no_daemon
@pytest.mark.nix_settings(trusted_users="*")
@pytest.mark.full_sandbox
@pytest.mark.parametrize(("protocol", "flags"), [("ssh", []), ("ssh-ng", ["--force-untrusted"])])
@with_files(
+2 -3
View File
@@ -7,6 +7,8 @@ from testlib.fixtures.command import CommandResult
from testlib.fixtures.nix import Nix
from testlib.fixtures.env import ManagedEnv
pytestmark = [pytest.mark.nix_settings(trusted_users="*")]
def build(nix: Nix, *args) -> CommandResult:
expr = """
@@ -51,21 +53,18 @@ def test_substitution_fallback_good_first(nix: Nix, caches: Caches):
build(nix, "--substituters", f"{caches.good} {caches.bad}").ok()
@pytest.mark.no_daemon
def test_substitution_fallback_bad_first(nix: Nix, caches: Caches):
# we expect three warnings for the single nar: two from querying, one from the substitution itself
result = build(nix, "--substituters", f"{caches.bad} {caches.good}").ok()
assert len(re.findall(r"warning.*narinfo", result.stderr_s)) == 3
@pytest.mark.no_daemon
def test_substitution_fallback_may_build(nix: Nix, caches: Caches):
# we expect two errors for the single nar: one from querying, one from the substitution itself
result = build(nix, "--substituters", f"{caches.bad}", "--fallback").ok()
assert len(re.findall(r"error.*narinfo", result.stderr_s)) == 2
@pytest.mark.no_daemon
def test_substitution_fallback_no_build(nix: Nix, caches: Caches):
# we expect one error, and it's fatal
result = build(nix, "--substituters", f"{caches.bad}").expect(1)
@@ -19,7 +19,7 @@ def test_timeout_timeout(nix: Nix):
assert "timed out" in res.stderr_plain
@pytest.mark.no_daemon
@pytest.mark.nix_settings(trusted_users="*")
@with_files(_files)
def test_timeout_max_log(nix: Nix):
res = (
@@ -5,7 +5,6 @@ import pytest
from testlib.fixtures.nix import Nix
@pytest.mark.no_daemon
@pytest.mark.parametrize("sha", ["", "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="])
def test_locked_tarball_ttl(nix: Nix, sha: str):
files = nix.env.dirs.home
+5 -1
View File
@@ -6,7 +6,11 @@ requires-python = ">=3.12"
[tool.pytest.ini_options]
addopts = "-p no:xonsh"
markers = ["full_sandbox: test requires a fully isolated sandbox", "no_daemon: only use the local store for this test and do not test the daemon protocol implementations"]
markers = [
"full_sandbox: test requires a fully isolated sandbox",
"no_daemon: only use the local store for this test and do not test the daemon protocol implementations",
"nix_settings: default settings for Nix and NixDaemon fixtures",
]
# xfail tests should fail when not failing as described
xfail_strict = true
@@ -6,7 +6,7 @@ from testlib.utils import get_global_asset
import pytest
pytestmark = pytest.mark.no_daemon
pytestmark = [pytest.mark.nix_settings(trusted_users="*")]
@with_files({"config.nix": get_global_asset("config.nix")})
+38 -8
View File
@@ -2,7 +2,7 @@ import contextlib
import copy
import dataclasses
import sys
from functools import partialmethod, partial
from functools import partialmethod
from pathlib import Path
from typing import Any, Literal, get_args
from collections.abc import Callable, Generator
@@ -401,10 +401,17 @@ def _daemon_wrapper(
log_daemon_result(result, level)
@pytest.fixture
def nix_settings(request: pytest.FixtureRequest) -> dict[str, _NixSettingValue]:
return getattr(request, "param", {})
def _nix_plain_impl(
tmp_path: Path, env: ManagedEnv, logger: logging.Logger
tmp_path: Path, env: ManagedEnv, logger: logging.Logger, settings: dict[str, _NixSettingValue]
) -> Generator[Nix, Any, None]:
yield Nix(env, logger)
nix = Nix(env, logger)
nix.settings.update(settings)
yield nix
# when things are done using the nix store, the permissions for the store are read only
# after the test was executed, we set the permissions to rwx (write being the important part)
# for pytest to be able to delete the files during cleanup
@@ -414,27 +421,43 @@ def _nix_plain_impl(
@pytest.fixture
def nix(
tmp_path: Path, env: ManagedEnv, logger: logging.Logger, request: pytest.FixtureRequest
tmp_path: Path,
env: ManagedEnv,
logger: logging.Logger,
request: pytest.FixtureRequest,
nix_settings: dict[str, _NixSettingValue],
) -> Generator[Nix, Any, None]:
"""
Provides a rich way of calling `nix`.
For pre-applied commands use `nix.nix_instantiate`, `nix.nix_build` etc.
After configuring the command, use `.run()` to run it
"""
for nix in _nix_plain_impl(tmp_path, env, logger):
for nix in _nix_plain_impl(tmp_path, env, logger, nix_settings):
if getattr(request, "param", None) is None:
yield nix
else:
with _daemon_wrapper(request.param, nix) as inner:
with _daemon_wrapper(request.param, nix, settings=nix_settings) as inner:
yield inner
@pytest.fixture(params=daemon_protocols)
def daemon(request: pytest.FixtureRequest) -> NixDaemon:
def daemon(request: pytest.FixtureRequest, nix_settings: dict[str, _NixSettingValue]) -> NixDaemon:
"""
paramterize every daemon tests to run using all supported nix protocols
"""
return partial(_daemon_wrapper, request.param)
def wrapper(
nix: Nix,
args: list[str] | None = None,
settings: dict[str, _NixSettingValue] | None = None,
protocol: NixDaemonProtocol | None = None,
**kwargs,
) -> contextlib.AbstractAsyncContextManager[Nix]:
return _daemon_wrapper(
request.param, nix, args, nix_settings | (settings or {}), protocol, **kwargs
)
return wrapper
def pytest_generate_tests(metafunc: pytest.Metafunc):
@@ -444,6 +467,13 @@ def pytest_generate_tests(metafunc: pytest.Metafunc):
"""
if "nix" not in metafunc.fixturenames or "daemon" in metafunc.fixturenames:
return
nix_settings = {}
for settings in metafunc.definition.iter_markers("nix_settings"):
nix_settings.update({k.replace("_", "-"): v for k, v in settings.kwargs.items()})
if nix_settings:
metafunc.parametrize(
"nix_settings", [nix_settings], indirect=True, ids=[pytest.HIDDEN_PARAM]
)
if not list(metafunc.definition.iter_markers("no_daemon")):
protocols = [None, *daemon_protocols]
ids = protocols