From 1657d0eb4773baf8e6ae3d9819c05b16d7b90f90 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Sun, 12 Jul 2026 20:28:05 +0200 Subject: [PATCH] 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 --- tests/functional2/build/test_build_jobless.py | 4 +- tests/functional2/build/test_remote.py | 18 ++------ tests/functional2/build/test_substitution.py | 5 +- .../commands/test_build/test_timeout.py | 2 +- .../eval/fetchers/test_tarball_ttl.py | 1 - tests/functional2/pyproject.toml | 6 ++- .../functional2/store/test_optimise_store.py | 2 +- tests/functional2/testlib/fixtures/nix.py | 46 +++++++++++++++---- 8 files changed, 53 insertions(+), 31 deletions(-) diff --git a/tests/functional2/build/test_build_jobless.py b/tests/functional2/build/test_build_jobless.py index 0f52f3d7b..9986cc599 100644 --- a/tests/functional2/build/test_build_jobless.py +++ b/tests/functional2/build/test_build_jobless.py @@ -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) diff --git a/tests/functional2/build/test_remote.py b/tests/functional2/build/test_remote.py index c58825a11..9337186d0 100644 --- a/tests/functional2/build/test_remote.py +++ b/tests/functional2/build/test_remote.py @@ -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( diff --git a/tests/functional2/build/test_substitution.py b/tests/functional2/build/test_substitution.py index 8131b0ed4..73a87136b 100644 --- a/tests/functional2/build/test_substitution.py +++ b/tests/functional2/build/test_substitution.py @@ -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) diff --git a/tests/functional2/commands/test_build/test_timeout.py b/tests/functional2/commands/test_build/test_timeout.py index 30f701c44..4add2846e 100644 --- a/tests/functional2/commands/test_build/test_timeout.py +++ b/tests/functional2/commands/test_build/test_timeout.py @@ -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 = ( diff --git a/tests/functional2/eval/fetchers/test_tarball_ttl.py b/tests/functional2/eval/fetchers/test_tarball_ttl.py index a458e96fe..c37fe00ea 100644 --- a/tests/functional2/eval/fetchers/test_tarball_ttl.py +++ b/tests/functional2/eval/fetchers/test_tarball_ttl.py @@ -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 diff --git a/tests/functional2/pyproject.toml b/tests/functional2/pyproject.toml index c628b61c1..051bdcf2e 100644 --- a/tests/functional2/pyproject.toml +++ b/tests/functional2/pyproject.toml @@ -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 diff --git a/tests/functional2/store/test_optimise_store.py b/tests/functional2/store/test_optimise_store.py index 7d156a5c4..1ca0323f4 100644 --- a/tests/functional2/store/test_optimise_store.py +++ b/tests/functional2/store/test_optimise_store.py @@ -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")}) diff --git a/tests/functional2/testlib/fixtures/nix.py b/tests/functional2/testlib/fixtures/nix.py index ade2a9326..dcaa9eec4 100644 --- a/tests/functional2/testlib/fixtures/nix.py +++ b/tests/functional2/testlib/fixtures/nix.py @@ -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