f2: don't use diverted stores unless specifically requested

diverted stores are only necessary when the logical store paths of
objects matter for the test itself, such as for derivation hashes,
substitution from golden sample nars, or actual tests of the store
diversion functionality. all other tests can use undiverted stores
to run, especially since only linux can build in diverted a store.

Change-Id: I62f0907bdef9961609af22b610195fcec54c1e57
This commit is contained in:
eldritch horrors
2026-02-11 20:46:18 +00:00
parent 505d0669dc
commit b34f136f10
7 changed files with 36 additions and 28 deletions
+1 -2
View File
@@ -1,4 +1,3 @@
import sys
import re
from pathlib import Path
@@ -24,7 +23,7 @@ def impure_vars(env: ManagedEnv):
def test_bad(nix: Nix):
res = nix.nix_instantiate(["fixed.nix", "-A", "good.0"], build=True).run().ok()
store_path = nix.nix_store(["-q", res.stdout_plain], build=True).run().ok().stdout_plain
path = Path(f"{nix.env.dirs.test_root}{store_path}" if sys.platform != "darwin" else store_path)
path = Path(store_path)
assert not path.exists()
# Building with the bad hash should produce the "good" output path as
+3 -1
View File
@@ -8,7 +8,7 @@ import yaml
from _pytest.python import Metafunc
from lang.lang_util import LangTest, fetch_all_lang_tests, LangTestRunner
from testlib.fixtures.nix import Nix
from testlib.fixtures.nix import Nix, with_diverted_store
from testlib.fixtures.snapshot import Snapshot
@@ -92,6 +92,7 @@ def test_parse_fail(files: Path, nix: Nix, flags: list[str], snapshot: Callable[
assert snapshot("err.exp") == stderr
@with_diverted_store
def test_eval_okay(files: Path, nix: Nix, flags: list[str], snapshot: Callable[[str], Snapshot]):
nix_command = nix.nix_instantiate(["--eval", "--strict", *flags, files / "in.nix"], flake=True)
result = nix_command.run().ok()
@@ -101,6 +102,7 @@ def test_eval_okay(files: Path, nix: Nix, flags: list[str], snapshot: Callable[[
assert snapshot("err.exp") == stderr
@with_diverted_store
def test_eval_fail(files: Path, nix: Nix, flags: list[str], snapshot: Callable[[str], Snapshot]):
nix_command = nix.nix_instantiate(
["--eval", "--strict", "--show-trace", *flags, files / "in.nix"], flake=True
+2 -1
View File
@@ -6,7 +6,7 @@ from pathlib import Path
import pytest
from testlib.fixtures.nix import Nix
from testlib.fixtures.nix import Nix, with_diverted_store
from testlib.nar import (
DirectoryUnordered,
NarItem,
@@ -102,6 +102,7 @@ EVIL_NARS: list[tuple[str, NarItem]] = [
@pytest.mark.parametrize(("name", "nar"), EVIL_NARS, ids=next(zip(*EVIL_NARS)))
@with_diverted_store
def test_evil_nar(nix: Nix, name: str, nar: NarItem, logger: Logger):
bio = BytesIO()
+2 -1
View File
@@ -6,7 +6,7 @@ import pytest
from testlib.fixtures.file_helper import File, with_files
from testlib.fixtures.http_server import http_server
from testlib.fixtures.nix import Nix
from testlib.fixtures.nix import Nix, with_diverted_store
class HTTPStore:
@@ -101,6 +101,7 @@ def nars_from_narinfo_cache(db_path: Path) -> list[dict[str, str | bool]]:
@with_files({"test-file": File("hello world")})
@with_diverted_store
def test_http_simple(nix: Nix, store: HTTPStore, files: Path):
test_file = files / "test-file"
result = nix.nix(cmd=["store", "add-file", test_file], flake=True).run()
+1 -4
View File
@@ -154,10 +154,6 @@ class _Dirs:
tmpdir: Path | None
"""used for nar caching"""
nix_store_dir: Path | None = None
"""
store dir override for building on macos *specifically*. do not
use or set this for any other purpose or many tests will break.
"""
def get_env_keys(self) -> set[str]:
return {f.name.upper() for f in dataclasses.fields(self)}
@@ -194,6 +190,7 @@ class ManagedEnv:
nix_conf_dir=self._get_dir("etc/nix"),
nix_bin_dir=lix_bin,
real_store_dir=self._get_dir("nix/store"),
nix_store_dir=self._get_dir("nix/store"),
cache_dir=self._get_dir("test-binary-cache"),
xdg_cache_home=self._get_dir("test-home/.cache"),
tmpdir=self._get_dir("tmp"),
+25 -12
View File
@@ -147,11 +147,19 @@ class Nix:
if self._settings is None:
self._settings = NixSettings()
self._settings.store = f"local?root={self.env.dirs.test_root}"
if sys.platform == "linux":
# sandbox build dir cannot be withing store dir. choose a short non-overlapping path.
self._settings.sandbox_build_dir = (
"/build-f2" if self.env.dirs.test_root.parts[1] != "build-f2" else "/build.f2"
)
return self._settings
def nix_cmd(
self, argv: list[str], flake: bool = False, build: bool | Literal["auto"] = "auto"
self,
argv: list[str],
flake: bool = False,
build: bool | Literal["auto"] = "auto", # noqa: ARG002
) -> Command:
"""
Constructs a NixCommand with the appropriate settings.
@@ -161,17 +169,6 @@ class Nix:
settings = self.settings.clone()
if flake:
settings.add_xp_feature("nix-command", "flakes")
# FIXME(rootile): Darwin needs special handling here, as it does not support (non-root) chroots...
# Hence, it cannot build using a relocated store so we just use the local (aka global) store instead
# This is kinda ugly but what else can one do
if sys.platform == "darwin":
if build is True or (
# argv[1:2] does not throw a key error on empty lists
# hence not crashing this check on an empty `nix.nix([])` call
build == "auto" and (argv[0] == "nix-build" or argv[1:2] == ["build"])
):
settings.store = None
self.env.dirs.nix_store_dir = self.env.dirs.real_store_dir
settings.to_env_overlay(self.env)
return Command(argv=argv, exe=self._nix_executable, _env=self.env)
@@ -352,3 +349,19 @@ def nix(tmp_path: Path, env: ManagedEnv, logger: logging.Logger) -> Generator[Ni
# for pytest to be able to delete the files during cleanup
cmd = Command(argv=["chmod", "-R", "+w", str(tmp_path.absolute())], _env=env)
cmd.run().ok()
@pytest.fixture
def enable_diverted_store(nix: Nix):
"""
clear NIX_STORE_DIR, resetting it to the default (ie /nix/store).
this makes builds impossible on platforms that cannot bind-mount,
(e.g. macos) but it is important for eval result reproducibility.
while builds may not work, substitution should still be possible.
"""
nix.env.dirs.nix_store_dir = None
nix.settings.sandbox_build_dir = None
def with_diverted_store(func: Callable[[Any], None]) -> Callable[[Any], None]:
return pytest.mark.usefixtures("enable_diverted_store")(func)
@@ -98,13 +98,7 @@ def test_env_dirs_created(env: ManagedEnv):
fields = dataclasses.asdict(env.dirs).items()
assert len(fields) > 1
for name, field in fields:
field: Path | None
# we never want to set NIX_STORE_DIR on linux due to unfortunate config ordering.
# creating a fresh env should always have it unset, it'll only be set when needed
if name == "nix_store_dir":
assert field is None
else:
field.exists()
field.exists()
def test_env_get_path_fails(env: ManagedEnv):
@@ -129,6 +123,7 @@ def test_env_to_env(tmp_path: Path):
"NIX_STATE_DIR",
"NIX_CONF_DIR",
"NIX_BIN_DIR",
"NIX_STORE_DIR",
"REAL_STORE_DIR",
"CACHE_DIR",
"XDG_CACHE_HOME",