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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user