From fc2eedf9dbb002b7fde7e9a91fe127141cb076a1 Mon Sep 17 00:00:00 2001 From: "Commentator2.0" Date: Sat, 7 Jun 2025 01:57:49 +0200 Subject: [PATCH] tests/functional2: migrate why-depends.sh Make builds work on darwin and migrate the first building test :D Change-Id: Ia301c78d3bc771cd826d93dc114b098167043e97 --- tests/functional/meson.build | 1 - tests/functional/why-depends.sh | 41 ----------- .../functional2/commands/test_why_depends.py | 71 +++++++++++++++++++ tests/functional2/testlib/fixtures/nix.py | 28 ++++++-- .../testlib/global_assets/dependencies.nix | 8 +++ 5 files changed, 103 insertions(+), 46 deletions(-) delete mode 100644 tests/functional/why-depends.sh create mode 100644 tests/functional2/commands/test_why_depends.py diff --git a/tests/functional/meson.build b/tests/functional/meson.build index 9b5aed46d..b65f9f599 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -138,7 +138,6 @@ functional_tests_scripts = [ 'flakes/config.sh', 'fmt.sh', 'eval-store.sh', - 'why-depends.sh', 'derivation-json.sh', 'import-derivation.sh', 'nix_path.sh', diff --git a/tests/functional/why-depends.sh b/tests/functional/why-depends.sh deleted file mode 100644 index 8103df666..000000000 --- a/tests/functional/why-depends.sh +++ /dev/null @@ -1,41 +0,0 @@ -source common.sh - -clearStore - -cp ./dependencies.nix ./dependencies.builder0.sh ./config.nix $TEST_HOME - -cd $TEST_HOME - -nix why-depends --derivation --file ./dependencies.nix input2_drv input1_drv -nix why-depends --file ./dependencies.nix input2_drv input1_drv - -nix-build ./dependencies.nix -A input0_drv -o dep -nix-build ./dependencies.nix -A input3_drv -o dep3 -nix-build ./dependencies.nix -o toplevel - -FAST_WHY_DEPENDS_OUTPUT=$(nix why-depends ./toplevel ./dep) -PRECISE_WHY_DEPENDS_OUTPUT=$(nix why-depends ./toplevel ./dep --precise) - -# Both outputs should show that `input-2` is in the dependency chain -echo "$FAST_WHY_DEPENDS_OUTPUT" | grepQuiet input-2 -echo "$PRECISE_WHY_DEPENDS_OUTPUT" | grepQuiet input-2 - -# But only the “precise” one should refer to `reference-to-input-2` -echo "$FAST_WHY_DEPENDS_OUTPUT" | grepQuietInverse reference-to-input-2 -echo "$PRECISE_WHY_DEPENDS_OUTPUT" | grepQuiet reference-to-input-2 - -<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '2p' | grepQuiet "└───reference-to-input-2 -> " -<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '3p' | grep " →" | grepQuiet "dependencies-input-2" -<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '4p' | grepQuiet " └───input0: …" # in input-2, file input0 -<<<"$PRECISE_WHY_DEPENDS_OUTPUT" sed -n '5p' | grep " →" | grepQuiet "dependencies-input-0" # is dependencies-input-0 referenced - -WHY_DEPENDS_SELF_REF="$(nix why-depends ./toplevel ./toplevel)" -<<<"$WHY_DEPENDS_SELF_REF" sed -n '1p' | grepQuiet "dependencies-top" -<<<"$WHY_DEPENDS_SELF_REF" sed -n '2p' | grep "└─" | grepQuiet "dependencies-top" -test -z "$(<<<"$WHY_DEPENDS_SELF_REF" sed -n '3p')" - -WHY_DEPENDS_ALL="$(nix why-depends ./toplevel ./dep3 --all)" -<<<"$WHY_DEPENDS_ALL" sed -n '1p' | grep -v "└─" | grepQuiet "dependencies-top" -<<<"$WHY_DEPENDS_ALL" sed -n '2p' | grep "├─" | grepQuiet "input-3" -<<<"$WHY_DEPENDS_ALL" sed -n '3p' | grep "└─" | grepQuiet "input-2" -<<<"$WHY_DEPENDS_ALL" sed -n '4p' | grep " └─" | grepQuiet "input-3" diff --git a/tests/functional2/commands/test_why_depends.py b/tests/functional2/commands/test_why_depends.py new file mode 100644 index 000000000..d338378fd --- /dev/null +++ b/tests/functional2/commands/test_why_depends.py @@ -0,0 +1,71 @@ +from functional2.testlib.fixtures.file_helper import with_files +from functional2.testlib.fixtures.nix import Nix +from functional2.testlib.utils import get_global_asset_pack + + +@with_files(get_global_asset_pack("dependencies")) +def test_command_doesnt_crash(nix: Nix): + nix.nix_store(["--init"]).run().ok() + nix.nix( + ["why-depends", "--derivation", "--file", "./dependencies.nix", "input2_drv", "input1_drv"], + flake=True, + build=True, + ).run().ok() + nix.nix( + ["why-depends", "--file", "./dependencies.nix", "input2_drv", "input1_drv"], + flake=True, + build=True, + ).run().ok() + + +def built_files(nix: Nix): + nix.nix_build(["./dependencies.nix", "-A", "input0_drv", "-o", "dep"]).run().ok() + nix.nix_build(["./dependencies.nix", "-A", "input3_drv", "-o", "dep3"]).run().ok() + nix.nix_build(["./dependencies.nix", "-o", "toplevel"]).run().ok() + + +@with_files(get_global_asset_pack("dependencies")) +def test_fast_depends(nix: Nix): + built_files(nix) + res = nix.nix(["why-depends", "./toplevel", "./dep"], flake=True, build=True).run().ok() + assert "input-2" in res.stdout_plain + assert "reference-to-input-2" not in res.stdout_plain + + +@with_files(get_global_asset_pack("dependencies")) +def test_precise_depends(nix: Nix): + built_files(nix) + res = ( + nix.nix(["why-depends", "./toplevel", "./dep", "--precise"], flake=True, build=True) + .run() + .ok() + ) + out = res.stdout_plain + assert "input-2" in out + assert "reference-to-input-2" in out + lines = out.splitlines() + assert "reference-to-input-2 -> " in lines[1] + assert "dependencies-input-2" in lines[2] + assert "input0: " in lines[3] + assert "dependencies-input-0" in lines[4] + + +@with_files(get_global_asset_pack("dependencies")) +def test_self_ref(nix: Nix): + built_files(nix) + res = nix.nix(["why-depends", "./toplevel", "./toplevel"], flake=True, build=True).run().ok() + lines = res.stdout_plain.splitlines() + assert "dependencies-top" in lines[0] + assert "dependencies-top" in lines[1] + + +@with_files(get_global_asset_pack("dependencies")) +def test_all(nix: Nix): + built_files(nix) + res = ( + nix.nix(["why-depends", "./toplevel", "./dep3", "--all"], flake=True, build=True).run().ok() + ) + lines = res.stdout_plain.splitlines() + assert "dependencies-top" in lines[0] + assert "input-2" in lines[1] + assert "input-3" in lines[2] diff --git a/tests/functional2/testlib/fixtures/nix.py b/tests/functional2/testlib/fixtures/nix.py index 83b4822ce..f794ecf9a 100644 --- a/tests/functional2/testlib/fixtures/nix.py +++ b/tests/functional2/testlib/fixtures/nix.py @@ -1,8 +1,9 @@ import dataclasses +import sys from functools import partialmethod from pathlib import Path from textwrap import dedent -from typing import Any +from typing import Any, Literal from collections.abc import Callable, Generator import pytest @@ -96,19 +97,38 @@ class Nix: return self._settings - def nix_cmd(self, argv: list[str], flake: bool = False) -> Command: + def nix_cmd( + self, argv: list[str], flake: bool = False, build: bool | Literal["auto"] = "auto" + ) -> Command: """ Constructs a NixCommand with the appropriate settings. + :param build: if the executed command wants to build stuff. This is required due to darwin shenanigans. "auto" will try to autodetect, override using `True` or `False`. Has no effect on linux. """ # Create a copy of settings to not have a writing side effect settings = dataclasses.replace(self.settings) if flake: settings.feature("nix-command", "flakes") + # FIXME(Commentator2.0): 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 ( + build == "auto" and (argv[0] == "nix-build" or argv[1] == "build") + ): + settings.store = None + settings.nix_store_dir = self.env.dirs.nix_store_dir + settings.to_env_overlay(self.env) return Command(argv=argv, _env=self.env) - def nix(self, cmd: list[str], nix_exe: str = "nix", flake: bool = False) -> Command: - return self.nix_cmd([nix_exe, *cmd], flake=flake) + def nix( + self, + cmd: list[str], + nix_exe: str = "nix", + flake: bool = False, + build: bool | Literal["auto"] = "auto", + ) -> Command: + return self.nix_cmd([nix_exe, *cmd], flake=flake, build=build) # Mark each of these as correct as they are not ClassVars, but we also don't want to turn off RUF045 nix_build = partialmethod(nix, nix_exe="nix-build") # noqa: RUF045 diff --git a/tests/functional2/testlib/global_assets/dependencies.nix b/tests/functional2/testlib/global_assets/dependencies.nix index 6463bcb32..d9e3e3f1f 100644 --- a/tests/functional2/testlib/global_assets/dependencies.nix +++ b/tests/functional2/testlib/global_assets/dependencies.nix @@ -20,9 +20,15 @@ let head -c 100k /dev/zero > $out/filler echo BAR > $out/bar echo ${input0} > $out/input0 + echo ${input3} > $out/input3 ''; }; + input3 = mkDerivation { + name = "dependencies-input-3"; + buildCommand = "mkdir $out; echo FOO > $out/foo"; + }; + fod_input = mkDerivation { name = "fod-input"; buildCommand = '' @@ -40,8 +46,10 @@ mkDerivation { builder = ./dependencies.builder0.sh + "/FOOBAR/../."; input1 = input1 + "/."; input2 = "${input2}/."; + input3 = "${input3}/."; input1_drv = input1; input2_drv = input2; + input3_drv = input3; input0_drv = input0; fod_input_drv = fod_input; meta.description = "Random test package";