diff options
Diffstat (limited to 'tests')
52 files changed, 825 insertions, 121 deletions
diff --git a/tests/big-derivation-attr.nix b/tests/big-derivation-attr.nix new file mode 100644 index 000000000..35c1187f6 --- /dev/null +++ b/tests/big-derivation-attr.nix @@ -0,0 +1,13 @@ +let + sixteenBytes = "0123456789abcdef"; + times16 = s: builtins.concatStringsSep "" [s s s s s s s s s s s s s s s s]; + exp = n: x: if n == 1 then x else times16 (exp (n - 1) x); + sixteenMegabyte = exp 6 sixteenBytes; +in +assert builtins.stringLength sixteenMegabyte == 16777216; +derivation { + name = "big-derivation-attr"; + builder = "/x"; + system = "y"; + bigAttr = sixteenMegabyte; +} diff --git a/tests/binary-cache.sh b/tests/binary-cache.sh index d7bc1507b..2368884f7 100644 --- a/tests/binary-cache.sh +++ b/tests/binary-cache.sh @@ -14,6 +14,17 @@ outPath=$(nix-build dependencies.nix --no-out-link) nix copy --to file://$cacheDir $outPath +# Test copying build logs to the binary cache. +nix log --store file://$cacheDir $outPath 2>&1 | grep 'is not available' +nix store copy-log --to file://$cacheDir $outPath +nix log --store file://$cacheDir $outPath | grep FOO +rm -rf $TEST_ROOT/var/log/nix +nix log $outPath 2>&1 | grep 'is not available' +nix log --substituters file://$cacheDir $outPath | grep FOO + +# Test copying build logs from the binary cache. +nix store copy-log --from file://$cacheDir $(nix-store -qd $outPath) +nix log $outPath | grep FOO basicDownloadTests() { # No uploading tests bcause upload with force HTTP doesn't work. diff --git a/tests/ca-shell.nix b/tests/ca-shell.nix new file mode 100644 index 000000000..ad2ab6aff --- /dev/null +++ b/tests/ca-shell.nix @@ -0,0 +1 @@ +{ ... }@args: import ./shell.nix (args // { contentAddressed = true; }) diff --git a/tests/ca/build-with-garbage-path.sh b/tests/ca/build-with-garbage-path.sh index 9aa08a899..884cd2802 100755 --- a/tests/ca/build-with-garbage-path.sh +++ b/tests/ca/build-with-garbage-path.sh @@ -8,7 +8,7 @@ requireDaemonNewerThan "2.4pre20210621" # Get the output path of `rootCA`, and put some garbage instead outPath="$(nix-build ./content-addressed.nix -A rootCA --no-out-link)" -nix-store --delete "$outPath" +nix-store --delete $(nix-store -q --referrers-closure "$outPath") touch "$outPath" # The build should correctly remove the garbage and put the expected path instead diff --git a/tests/ca/import-derivation.sh b/tests/ca/import-derivation.sh new file mode 100644 index 000000000..e98e0fbd0 --- /dev/null +++ b/tests/ca/import-derivation.sh @@ -0,0 +1,6 @@ +source common.sh + +export NIX_TESTS_CA_BY_DEFAULT=1 + +cd .. && source import-derivation.sh + diff --git a/tests/ca/repl.sh b/tests/ca/repl.sh new file mode 100644 index 000000000..3808c7cb2 --- /dev/null +++ b/tests/ca/repl.sh @@ -0,0 +1,5 @@ +source common.sh + +export NIX_TESTS_CA_BY_DEFAULT=1 + +cd .. && source repl.sh diff --git a/tests/check.nix b/tests/check.nix index ec455ae2d..ed91ff845 100644 --- a/tests/check.nix +++ b/tests/check.nix @@ -50,6 +50,6 @@ with import ./config.nix; fetchurl = import <nix/fetchurl.nix> { url = "file://" + toString ./lang/eval-okay-xml.exp.xml; - sha256 = "0kg4sla7ihm8ijr8cb3117fhl99zrc2bwy1jrngsfmkh8bav4m0v"; + sha256 = "sha256-behBlX+DQK/Pjvkuc8Tx68Jwi4E5v86wDq+ZLaHyhQE="; }; } diff --git a/tests/common.sh.in b/tests/common.sh.in index 7daab2460..49068f1c3 100644 --- a/tests/common.sh.in +++ b/tests/common.sh.in @@ -36,8 +36,9 @@ export PATH=@bindir@:$PATH if [[ -n "${NIX_CLIENT_PACKAGE:-}" ]]; then export PATH="$NIX_CLIENT_PACKAGE/bin":$PATH fi +DAEMON_PATH="$PATH" if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then - export NIX_DAEMON_COMMAND="$NIX_DAEMON_PACKAGE/bin/nix-daemon" + DAEMON_PATH="${NIX_DAEMON_PACKAGE}/bin:$DAEMON_PATH" fi coreutils=@coreutils@ @@ -89,10 +90,10 @@ startDaemon() { # Start the daemon, wait for the socket to appear. !!! # ‘nix-daemon’ should have an option to fork into the background. rm -f $NIX_DAEMON_SOCKET_PATH - ${NIX_DAEMON_COMMAND:-nix daemon} & - for ((i = 0; i < 30; i++)); do + PATH=$DAEMON_PATH nix daemon & + for ((i = 0; i < 300; i++)); do if [[ -S $NIX_DAEMON_SOCKET_PATH ]]; then break; fi - sleep 1 + sleep 0.1 done pidDaemon=$! trap "killDaemon" EXIT @@ -101,9 +102,9 @@ startDaemon() { killDaemon() { kill $pidDaemon - for i in {0.10}; do + for i in {0..100}; do kill -0 $pidDaemon || break - sleep 1 + sleep 0.1 done kill -9 $pidDaemon || true wait $pidDaemon || true @@ -126,7 +127,7 @@ isDaemonNewer () { [[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0 local requiredVersion="$1" local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3) - return [[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''2.4''") -ge 0 ]] + [[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''$requiredVersion''") -ge 0 ]] } requireDaemonNewerThan () { diff --git a/tests/config.sh b/tests/config.sh index 01c78f2c3..3d0da3cef 100644 --- a/tests/config.sh +++ b/tests/config.sh @@ -50,4 +50,4 @@ exp_cores=$(nix show-config | grep '^cores' | cut -d '=' -f 2 | xargs) exp_features=$(nix show-config | grep '^experimental-features' | cut -d '=' -f 2 | xargs) [[ $prev != $exp_cores ]] [[ $exp_cores == "4242" ]] -[[ $exp_features == "nix-command flakes" ]] +[[ $exp_features == "flakes nix-command" ]] diff --git a/tests/dependencies.builder0.sh b/tests/dependencies.builder0.sh index c37bf909a..9b11576e0 100644 --- a/tests/dependencies.builder0.sh +++ b/tests/dependencies.builder0.sh @@ -4,7 +4,7 @@ mkdir $out echo $(cat $input1/foo)$(cat $input2/bar) > $out/foobar -ln -s $input2 $out/input-2 +ln -s $input2 $out/reference-to-input-2 # Self-reference. ln -s $out $out/self diff --git a/tests/dependencies.nix b/tests/dependencies.nix index e320d81c9..45aca1793 100644 --- a/tests/dependencies.nix +++ b/tests/dependencies.nix @@ -27,6 +27,8 @@ let { input1 = input1 + "/."; input2 = "${input2}/."; input1_drv = input1; + input2_drv = input2; + input0_drv = input0; meta.description = "Random test package"; }; diff --git a/tests/eval-store.sh b/tests/eval-store.sh index 9ab7a87be..679da5741 100644 --- a/tests/eval-store.sh +++ b/tests/eval-store.sh @@ -1,6 +1,8 @@ source common.sh -requireDaemonNewerThan "2.4pre20210727" +# Using `--eval-store` with the daemon will eventually copy everything +# to the build store, invalidating most of the tests here +needLocalStore eval_store=$TEST_ROOT/eval-store diff --git a/tests/flake-bundler.sh b/tests/flake-bundler.sh new file mode 100644 index 000000000..9496b8f92 --- /dev/null +++ b/tests/flake-bundler.sh @@ -0,0 +1,37 @@ +source common.sh + +clearStore +rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local + +cp ./simple.nix ./simple.builder.sh ./config.nix $TEST_HOME + +cd $TEST_HOME + +cat <<EOF > flake.nix +{ + outputs = {self}: { + bundlers.$system = rec { + simple = drv: + if drv?type && drv.type == "derivation" + then drv + else self.packages.$system.default; + default = simple; + }; + packages.$system.default = import ./simple.nix; + apps.$system.default = { + type = "app"; + program = "\${import ./simple.nix}/hello"; + }; + }; +} +EOF +nix build .# +nix bundle --bundler .# .# +nix bundle --bundler .#bundlers.$system.default .#packages.$system.default +nix bundle --bundler .#bundlers.$system.simple .#packages.$system.default + +nix bundle --bundler .#bundlers.$system.default .#apps.$system.default +nix bundle --bundler .#bundlers.$system.simple .#apps.$system.default + +clearStore + diff --git a/tests/flake-local-settings.sh b/tests/flake-local-settings.sh new file mode 100644 index 000000000..e92c16f87 --- /dev/null +++ b/tests/flake-local-settings.sh @@ -0,0 +1,45 @@ +source common.sh + +clearStore +rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local + +cp ./simple.nix ./simple.builder.sh ./config.nix $TEST_HOME + +cd $TEST_HOME + +rm -f post-hook-ran +cat <<EOF > echoing-post-hook.sh +#!/bin/sh + +echo "ThePostHookRan as \$0" > $PWD/post-hook-ran +EOF +chmod +x echoing-post-hook.sh + +cat <<EOF > flake.nix +{ + nixConfig.post-build-hook = ./echoing-post-hook.sh; + nixConfig.allow-dirty = false; # See #5621 + + outputs = a: { + packages.$system.default = import ./simple.nix; + }; +} +EOF + +# Without --accept-flake-config, the post hook should not run. +nix build < /dev/null +(! [[ -f post-hook-ran ]]) +clearStore + +nix build --accept-flake-config +test -f post-hook-ran || fail "The post hook should have ran" + +# Make sure that the path to the post hook doesn’t change if we change +# something in the flake. +# Otherwise the user would have to re-validate the setting each time. +mv post-hook-ran previous-post-hook-run +echo "# Dummy comment" >> flake.nix +clearStore +nix build --accept-flake-config +diff -q post-hook-ran previous-post-hook-run || \ + fail "Both post hook runs should report the same filename" diff --git a/tests/flake-searching.sh b/tests/flake-searching.sh new file mode 100644 index 000000000..db241f6d2 --- /dev/null +++ b/tests/flake-searching.sh @@ -0,0 +1,52 @@ +source common.sh + +if [[ -z $(type -p git) ]]; then + echo "Git not installed; skipping flake search tests" + exit 99 +fi + +clearStore + +cp ./simple.nix ./simple.builder.sh ./config.nix $TEST_HOME +cd $TEST_HOME +mkdir -p foo/subdir +echo '{ outputs = _: {}; }' > foo/flake.nix +cat <<EOF > flake.nix +{ + inputs.foo.url = "$PWD/foo"; + outputs = a: { + packages.$system = rec { + test = import ./simple.nix; + default = test; + }; + }; +} +EOF +mkdir subdir +pushd subdir + +success=("" . .# .#test ../subdir ../subdir#test "$PWD") +failure=("path:$PWD") + +for i in "${success[@]}"; do + nix build $i || fail "flake should be found by searching up directories" +done + +for i in "${failure[@]}"; do + ! nix build $i || fail "flake should not search up directories when using 'path:'" +done + +popd + +nix build --override-input foo . || fail "flake should search up directories when not an installable" + +sed "s,$PWD/foo,$PWD/foo/subdir,g" -i flake.nix +! nix build || fail "flake should not search upwards when part of inputs" + +pushd subdir +git init +for i in "${success[@]}" "${failure[@]}"; do + ! nix build $i || fail "flake should not search past a git repository" +done +rm -rf .git +popd diff --git a/tests/flakes.sh b/tests/flakes.sh index 57d1b9aad..ea629ae70 100644 --- a/tests/flakes.sh +++ b/tests/flakes.sh @@ -41,8 +41,10 @@ cat > $flake1Dir/flake.nix <<EOF description = "Bla bla"; outputs = inputs: rec { - packages.$system.foo = import ./simple.nix; - defaultPackage.$system = packages.$system.foo; + packages.$system = rec { + foo = import ./simple.nix; + default = foo; + }; # To test "nix flake init". legacyPackages.x86_64-linux.hello = import ./simple.nix; @@ -128,7 +130,7 @@ hash2=$(nix flake metadata flake1 --json --refresh | jq -r .revision) nix build -o $TEST_ROOT/result flake1#foo [[ -e $TEST_ROOT/result/hello ]] -# Test defaultPackage. +# Test packages.default. nix build -o $TEST_ROOT/result flake1 [[ -e $TEST_ROOT/result/hello ]] @@ -140,11 +142,11 @@ nix build -o $flake1Dir/result git+file://$flake1Dir nix path-info $flake1Dir/result # 'getFlake' on a mutable flakeref should fail in pure mode, but succeed in impure mode. -(! nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").defaultPackage.$system") -nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").defaultPackage.$system" --impure +(! nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").packages.$system.default") +nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"$flake1Dir\").packages.$system.default" --impure # 'getFlake' on an immutable flakeref should succeed even in pure mode. -nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"git+file://$flake1Dir?rev=$hash2\").defaultPackage.$system" +nix build -o $TEST_ROOT/result --expr "(builtins.getFlake \"git+file://$flake1Dir?rev=$hash2\").packages.$system.default" # Building a flake with an unlocked dependency should fail in pure mode. (! nix build -o $TEST_ROOT/result flake2#bar --no-registries) @@ -249,6 +251,14 @@ cat > $flake3Dir/flake.nix <<EOF url = git+file://$nonFlakeDir; flake = false; }; + nonFlakeFile = { + url = path://$nonFlakeDir/README.md; + flake = false; + }; + nonFlakeFile2 = { + url = "$nonFlakeDir/README.md"; + flake = false; + }; }; description = "Fnord"; @@ -265,6 +275,8 @@ cat > $flake3Dir/flake.nix <<EOF dummy2 = builtins.readFile (builtins.path { name = "source"; path = inputs.flake1; filter = path: type: baseNameOf path == "simple.nix"; } + "/simple.nix"); buildCommand = '' cat \${inputs.nonFlake}/README.md > \$out + [[ \$(cat \${inputs.nonFlake}/README.md) = \$(cat \${inputs.nonFlakeFile}) ]] + [[ \${inputs.nonFlakeFile} = \${inputs.nonFlakeFile2} ]] ''; }; }; @@ -360,13 +372,13 @@ cat > $templatesDir/flake.nix <<EOF description = "Some templates"; outputs = { self }: { - templates = { + templates = rec { trivial = { path = ./trivial; description = "A trivial flake"; }; + default = trivial; }; - defaultTemplate = self.templates.trivial; }; } EOF @@ -378,8 +390,10 @@ cat > $templatesDir/trivial/flake.nix <<EOF description = "A flake for building Hello World"; outputs = { self, nixpkgs }: { - packages.x86_64-linux.hello = nixpkgs.legacyPackages.x86_64-linux.hello; - defaultPackage.x86_64-linux = self.packages.x86_64-linux.hello; + packages.x86_64-linux = rec { + hello = nixpkgs.legacyPackages.x86_64-linux.hello; + default = hello; + }; }; } EOF @@ -486,17 +500,15 @@ EOF cat > $flake3Dir/flake.nix <<EOF { outputs = { flake1, self }: { - defaultPackage = { - system-1 = "foo"; - system-2 = "bar"; - }; + packages.system-1.default = "foo"; + packages.system-2.default = "bar"; }; } EOF checkRes=$(nix flake check --keep-going $flake3Dir 2>&1 && fail "nix flake check should have failed" || true) -echo "$checkRes" | grep -q "defaultPackage.system-1" -echo "$checkRes" | grep -q "defaultPackage.system-2" +echo "$checkRes" | grep -q "packages.system-1.default" +echo "$checkRes" | grep -q "packages.system-2.default" # Test 'follows' inputs. cat > $flake3Dir/flake.nix <<EOF @@ -581,7 +593,7 @@ mkdir $flake5Dir cat > $flake5Dir/flake.nix <<EOF { outputs = { self, flake1 }: { - defaultPackage.$system = flake1.defaultPackage.$system; + packages.$system.default = flake1.packages.$system.default; expr = assert builtins.pathExists ./flake.lock; 123; }; } @@ -706,11 +718,10 @@ cat > $flakeFollowsA/flake.nix <<EOF inputs = { B = { url = "path:./flakeB"; - inputs.foobar.follows = "D"; + inputs.foobar.follows = "foobar"; }; - D.url = "path:./flakeD"; - foobar.url = "path:./flakeE"; + foobar.url = "path:$flakeFollowsA/flakeE"; }; outputs = { ... }: {}; } @@ -720,7 +731,8 @@ cat > $flakeFollowsB/flake.nix <<EOF { description = "Flake B"; inputs = { - foobar.url = "path:./../flakeE"; + foobar.url = "path:$flakeFollowsA/flakeE"; + goodoo.follows = "C/goodoo"; C = { url = "path:./flakeC"; inputs.foobar.follows = "foobar"; @@ -734,7 +746,8 @@ cat > $flakeFollowsC/flake.nix <<EOF { description = "Flake C"; inputs = { - foobar.url = "path:./../../flakeE"; + foobar.url = "path:$flakeFollowsA/flakeE"; + goodoo.follows = "foobar"; }; outputs = { ... }: {}; } @@ -750,7 +763,7 @@ EOF cat > $flakeFollowsE/flake.nix <<EOF { - description = "Flake D"; + description = "Flake E"; inputs = {}; outputs = { ... }: {}; } @@ -759,12 +772,45 @@ EOF git -C $flakeFollowsA add flake.nix flakeB/flake.nix \ flakeB/flakeC/flake.nix flakeD/flake.nix flakeE/flake.nix +nix flake metadata $flakeFollowsA + +nix flake update $flakeFollowsA + +oldLock="$(cat "$flakeFollowsA/flake.lock")" + +# Ensure that locking twice doesn't change anything + nix flake lock $flakeFollowsA +newLock="$(cat "$flakeFollowsA/flake.lock")" + +diff <(echo "$newLock") <(echo "$oldLock") + [[ $(jq -c .nodes.B.inputs.C $flakeFollowsA/flake.lock) = '"C"' ]] -[[ $(jq -c .nodes.B.inputs.foobar $flakeFollowsA/flake.lock) = '["D"]' ]] +[[ $(jq -c .nodes.B.inputs.foobar $flakeFollowsA/flake.lock) = '["foobar"]' ]] [[ $(jq -c .nodes.C.inputs.foobar $flakeFollowsA/flake.lock) = '["B","foobar"]' ]] +# Ensure removing follows from flake.nix removes them from the lockfile + +cat > $flakeFollowsA/flake.nix <<EOF +{ + description = "Flake A"; + inputs = { + B = { + url = "path:./flakeB"; + inputs.nonFlake.follows = "D"; + }; + D.url = "path:./flakeD"; + }; + outputs = { ... }: {}; +} +EOF + +nix flake lock $flakeFollowsA + +[[ $(jq -c .nodes.B.inputs.foobar $flakeFollowsA/flake.lock) = '"foobar"' ]] +jq -r -c '.nodes | keys | .[]' $flakeFollowsA/flake.lock | grep "^foobar$" + # Ensure a relative path is not allowed to go outside the store path cat > $flakeFollowsA/flake.nix <<EOF { diff --git a/tests/function-trace.sh b/tests/function-trace.sh index 3b7f364e3..0b7f49d82 100755 --- a/tests/function-trace.sh +++ b/tests/function-trace.sh @@ -60,8 +60,6 @@ function-trace exited (string):1:1 at expect_trace '(x: x) 1 2' " function-trace entered (string):1:1 at function-trace exited (string):1:1 at -function-trace entered (string):1:1 at -function-trace exited (string):1:1 at " # Not a function diff --git a/tests/gc-non-blocking.sh b/tests/gc-non-blocking.sh new file mode 100644 index 000000000..0d781485d --- /dev/null +++ b/tests/gc-non-blocking.sh @@ -0,0 +1,33 @@ +# Test whether the collector is non-blocking, i.e. a build can run in +# parallel with it. +source common.sh + +needLocalStore "the GC test needs a synchronisation point" + +clearStore + +fifo=$TEST_ROOT/test.fifo +mkfifo "$fifo" + +dummy=$(nix store add-path ./simple.nix) + +running=$TEST_ROOT/running +touch $running + +(_NIX_TEST_GC_SYNC=$fifo nix-store --gc -vvvvv; rm $running) & +pid=$! + +sleep 2 + +outPath=$(nix-build --max-silent-time 60 -o "$TEST_ROOT/result" -E " + with import ./config.nix; + mkDerivation { + name = \"non-blocking\"; + buildCommand = \"set -x; test -e $running; mkdir \$out; echo > $fifo\"; + }") + +wait $pid + +(! test -e $running) +(! test -e $dummy) +test -e $outPath diff --git a/tests/gc.sh b/tests/gc.sh index cf0e2c32d..ad09a8b39 100644 --- a/tests/gc.sh +++ b/tests/gc.sh @@ -1,5 +1,7 @@ source common.sh +clearStore + drvPath=$(nix-instantiate dependencies.nix) outPath=$(nix-store -rvv "$drvPath") @@ -16,18 +18,24 @@ if nix-store --gc --print-dead | grep -E $outPath$; then false; fi nix-store --gc --print-dead -inUse=$(readLink $outPath/input-2) +inUse=$(readLink $outPath/reference-to-input-2) if nix-store --delete $inUse; then false; fi test -e $inUse if nix-store --delete $outPath; then false; fi test -e $outPath +for i in $NIX_STORE_DIR/*; do + if [[ $i =~ /trash ]]; then continue; fi # compat with old daemon + touch $i.lock + touch $i.chroot +done + nix-collect-garbage # Check that the root and its dependencies haven't been deleted. cat $outPath/foobar -cat $outPath/input-2/bar +cat $outPath/reference-to-input-2/bar # Check that the derivation has been GC'd. if test -e $drvPath; then false; fi @@ -38,3 +46,7 @@ nix-collect-garbage # Check that the output has been GC'd. if test -e $outPath/foobar; then false; fi + +# Check that the store is empty. +rmdir $NIX_STORE_DIR/.links +rmdir $NIX_STORE_DIR diff --git a/tests/lang/eval-okay-groupBy.exp b/tests/lang/eval-okay-groupBy.exp new file mode 100644 index 000000000..bfca5652a --- /dev/null +++ b/tests/lang/eval-okay-groupBy.exp @@ -0,0 +1 @@ +{ "1" = [ 9 ]; "2" = [ 8 ]; "3" = [ 13 29 ]; "4" = [ 3 4 10 11 17 18 ]; "5" = [ 0 23 26 28 ]; "6" = [ 1 12 21 27 30 ]; "7" = [ 7 22 ]; "8" = [ 14 ]; "9" = [ 19 ]; b = [ 16 25 ]; c = [ 24 ]; d = [ 2 ]; e = [ 5 6 15 31 ]; f = [ 20 ]; } diff --git a/tests/lang/eval-okay-groupBy.nix b/tests/lang/eval-okay-groupBy.nix new file mode 100644 index 000000000..862d89dbd --- /dev/null +++ b/tests/lang/eval-okay-groupBy.nix @@ -0,0 +1,5 @@ +with import ./lib.nix; + +builtins.groupBy (n: + builtins.substring 0 1 (builtins.hashString "sha256" (toString n)) +) (range 0 31) diff --git a/tests/lang/eval-okay-regression-20220122.exp b/tests/lang/eval-okay-regression-20220122.exp new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/tests/lang/eval-okay-regression-20220122.exp @@ -0,0 +1 @@ +3 diff --git a/tests/lang/eval-okay-regression-20220122.nix b/tests/lang/eval-okay-regression-20220122.nix new file mode 100644 index 000000000..694e9a13b --- /dev/null +++ b/tests/lang/eval-okay-regression-20220122.nix @@ -0,0 +1 @@ +((_: _) 1) + ((__: __) 2) diff --git a/tests/lang/eval-okay-regression-20220125.exp b/tests/lang/eval-okay-regression-20220125.exp new file mode 100644 index 000000000..00750edc0 --- /dev/null +++ b/tests/lang/eval-okay-regression-20220125.exp @@ -0,0 +1 @@ +3 diff --git a/tests/lang/eval-okay-regression-20220125.nix b/tests/lang/eval-okay-regression-20220125.nix new file mode 100644 index 000000000..485502373 --- /dev/null +++ b/tests/lang/eval-okay-regression-20220125.nix @@ -0,0 +1,2 @@ +((__curPosFoo: __curPosFoo) 1) + ((__curPosBar: __curPosBar) 2) + diff --git a/tests/lang/eval-okay-sort.exp b/tests/lang/eval-okay-sort.exp index 148b93516..899119e20 100644 --- a/tests/lang/eval-okay-sort.exp +++ b/tests/lang/eval-okay-sort.exp @@ -1 +1 @@ -[ [ 42 77 147 249 483 526 ] [ 526 483 249 147 77 42 ] [ "bar" "fnord" "foo" "xyzzy" ] [ { key = 1; value = "foo"; } { key = 1; value = "fnord"; } { key = 2; value = "bar"; } ] ] +[ [ 42 77 147 249 483 526 ] [ 526 483 249 147 77 42 ] [ "bar" "fnord" "foo" "xyzzy" ] [ { key = 1; value = "foo"; } { key = 1; value = "fnord"; } { key = 2; value = "bar"; } ] [ [ ] [ ] [ 1 ] [ 1 4 ] [ 1 5 ] [ 1 6 ] [ 2 ] [ 2 3 ] [ 3 ] [ 3 ] ] ] diff --git a/tests/lang/eval-okay-sort.nix b/tests/lang/eval-okay-sort.nix index 8299c3a4a..50aa78e40 100644 --- a/tests/lang/eval-okay-sort.nix +++ b/tests/lang/eval-okay-sort.nix @@ -4,5 +4,17 @@ with builtins; (sort (x: y: y < x) [ 483 249 526 147 42 77 ]) (sort lessThan [ "foo" "bar" "xyzzy" "fnord" ]) (sort (x: y: x.key < y.key) - [ { key = 1; value = "foo"; } { key = 2; value = "bar"; } { key = 1; value = "fnord"; } ]) + [ { key = 1; value = "foo"; } { key = 2; value = "bar"; } { key = 1; value = "fnord"; } ]) + (sort lessThan [ + [ 1 6 ] + [ ] + [ 2 3 ] + [ 3 ] + [ 1 5 ] + [ 2 ] + [ 1 ] + [ ] + [ 1 4 ] + [ 3 ] + ]) ] diff --git a/tests/lang/eval-okay-xml.exp.xml b/tests/lang/eval-okay-xml.exp.xml index 92b75e0b8..20099326c 100644 --- a/tests/lang/eval-okay-xml.exp.xml +++ b/tests/lang/eval-okay-xml.exp.xml @@ -31,9 +31,9 @@ <attr name="f"> <function> <attrspat> - <attr name="z" /> <attr name="x" /> <attr name="y" /> + <attr name="z" /> </attrspat> </function> </attr> diff --git a/tests/lang/eval-okay-zipAttrsWith.exp b/tests/lang/eval-okay-zipAttrsWith.exp new file mode 100644 index 000000000..9c0b15d22 --- /dev/null +++ b/tests/lang/eval-okay-zipAttrsWith.exp @@ -0,0 +1 @@ +{ "0" = { n = "0"; v = [ 5 23 29 ]; }; "1" = { n = "1"; v = [ 7 30 ]; }; "2" = { n = "2"; v = [ 18 ]; }; "4" = { n = "4"; v = [ 10 ]; }; "5" = { n = "5"; v = [ 15 25 26 31 ]; }; "6" = { n = "6"; v = [ 3 14 ]; }; "7" = { n = "7"; v = [ 12 ]; }; "8" = { n = "8"; v = [ 2 6 8 9 ]; }; "9" = { n = "9"; v = [ 0 16 ]; }; a = { n = "a"; v = [ 17 21 22 27 ]; }; c = { n = "c"; v = [ 11 24 ]; }; d = { n = "d"; v = [ 4 13 28 ]; }; e = { n = "e"; v = [ 20 ]; }; f = { n = "f"; v = [ 1 19 ]; }; } diff --git a/tests/lang/eval-okay-zipAttrsWith.nix b/tests/lang/eval-okay-zipAttrsWith.nix new file mode 100644 index 000000000..877d4e5fa --- /dev/null +++ b/tests/lang/eval-okay-zipAttrsWith.nix @@ -0,0 +1,9 @@ +with import ./lib.nix; + +let + str = builtins.hashString "sha256" "test"; +in +builtins.zipAttrsWith + (n: v: { inherit n v; }) + (map (n: { ${builtins.substring n 1 str} = n; }) + (range 0 31)) diff --git a/tests/local.mk b/tests/local.mk index 894aa976d..7074579c9 100644 --- a/tests/local.mk +++ b/tests/local.mk @@ -1,25 +1,53 @@ nix_tests = \ - hash.sh lang.sh add.sh simple.sh dependencies.sh \ - config.sh \ - gc.sh \ + flakes.sh \ ca/gc.sh \ - gc-concurrent.sh \ + gc.sh \ + remote-store.sh \ + lang.sh \ + fetchMercurial.sh \ gc-auto.sh \ - referrers.sh user-envs.sh logging.sh nix-build.sh misc.sh fixed.sh \ - gc-runtime.sh check-refs.sh filter-source.sh \ - local-store.sh remote-store.sh export.sh export-graph.sh \ - db-migration.sh \ - timeout.sh secure-drv-outputs.sh nix-channel.sh \ - multiple-outputs.sh import-derivation.sh fetchurl.sh optimise-store.sh \ + user-envs.sh \ binary-cache.sh \ + multiple-outputs.sh \ + ca/build.sh \ + nix-build.sh \ + gc-concurrent.sh \ + repair.sh \ + fixed.sh \ + export-graph.sh \ + timeout.sh \ + fetchGitRefs.sh \ + gc-runtime.sh \ + tarball.sh \ + fetchGit.sh \ + fetchurl.sh \ + simple.sh \ + referrers.sh \ + optimise-store.sh \ substitute-with-invalid-ca.sh \ - binary-cache-build-remote.sh \ - nix-profile.sh repair.sh dump-db.sh case-hack.sh \ - check-reqs.sh pass-as-file.sh tarball.sh restricted.sh \ - placeholders.sh nix-shell.sh \ - linux-sandbox.sh \ - build-dry.sh \ + ca/concurrent-builds.sh \ + signing.sh \ + ca/build-with-garbage-path.sh \ + hash.sh \ + gc-non-blocking.sh \ + check.sh \ + ca/substitute.sh \ + nix-shell.sh \ + ca/signatures.sh \ + ca/nix-shell.sh \ + ca/nix-copy.sh \ + check-refs.sh \ build-remote-input-addressed.sh \ + secure-drv-outputs.sh \ + restricted.sh \ + fetchGitSubmodules.sh \ + flake-searching.sh \ + ca/duplicate-realisation-in-closure.sh \ + readfile-context.sh \ + nix-channel.sh \ + recursive.sh \ + dependencies.sh \ + check-reqs.sh \ build-remote-content-addressed-fixed.sh \ build-remote-content-addressed-floating.sh \ build-remote-trustless-should-pass-0.sh \ @@ -27,44 +55,53 @@ nix_tests = \ build-remote-trustless-should-pass-2.sh \ build-remote-trustless-should-pass-3.sh \ build-remote-trustless-should-fail-0.sh \ - ssh-relay.sh \ nar-access.sh \ + pure-eval.sh \ + ca/post-hook.sh \ + repl.sh \ + ca/repl.sh \ + ca/recursive.sh \ + binary-cache-build-remote.sh \ + search.sh \ + logging.sh \ + export.sh \ + config.sh \ + add.sh \ + local-store.sh \ + filter-source.sh \ + misc.sh \ + dump-db.sh \ + linux-sandbox.sh \ + build-dry.sh \ structured-attrs.sh \ - fetchGit.sh \ - fetchGitRefs.sh \ - fetchGitSubmodules.sh \ - fetchMercurial.sh \ - signing.sh \ shell.sh \ brotli.sh \ zstd.sh \ compression-levels.sh \ - pure-eval.sh \ - check.sh \ - plugins.sh \ - search.sh \ nix-copy-ssh.sh \ post-hook.sh \ - ca/post-hook.sh \ function-trace.sh \ - recursive.sh \ - describe-stores.sh \ - flakes.sh \ + flake-local-settings.sh \ + eval-store.sh \ + why-depends.sh \ + import-derivation.sh \ + ca/import-derivation.sh \ + nix_path.sh \ + case-hack.sh \ + placeholders.sh \ + ssh-relay.sh \ + plugins.sh \ build.sh \ - compute-levels.sh \ - repl.sh \ - ca/build.sh \ - ca/build-with-garbage-path.sh \ - ca/duplicate-realisation-in-closure.sh \ - ca/substitute.sh \ - ca/signatures.sh \ - ca/nix-shell.sh \ ca/nix-run.sh \ - ca/recursive.sh \ - ca/concurrent-builds.sh \ - ca/nix-copy.sh \ - eval-store.sh - # parallel.sh + db-migration.sh \ + nix-profile.sh \ + pass-as-file.sh \ + describe-stores.sh \ + store-ping.sh + +ifeq ($(HAVE_LIBCPUID), 1) + nix_tests += compute-levels.sh +endif install-tests += $(foreach x, $(nix_tests), tests/$(x)) diff --git a/tests/multiple-outputs.sh b/tests/multiple-outputs.sh index 0bca12b42..0d45ad35b 100644 --- a/tests/multiple-outputs.sh +++ b/tests/multiple-outputs.sh @@ -76,7 +76,10 @@ if nix-build multiple-outputs.nix -A cyclic --no-out-link; then exit 1 fi +# Do a GC. This should leave an empty store. echo "collecting garbage..." rm $TEST_ROOT/result* nix-store --gc --keep-derivations --keep-outputs nix-store --gc --print-roots +rm -rf $NIX_STORE_DIR/.links +rmdir $NIX_STORE_DIR diff --git a/tests/nix-channel.sh b/tests/nix-channel.sh index 63c0f97ba..54b8f5979 100644 --- a/tests/nix-channel.sh +++ b/tests/nix-channel.sh @@ -35,16 +35,14 @@ grep -q 'item.*attrPath="foo".*name="dependencies-top"' $TEST_ROOT/meta.xml nix-env -i dependencies-top [ -e $TEST_HOME/.nix-profile/foobar ] -clearProfiles -rm -f $TEST_HOME/.nix-channels - # Test updating from a tarball -nix-channel --add file://$TEST_ROOT/foo/nixexprs.tar.bz2 foo +nix-channel --add file://$TEST_ROOT/foo/nixexprs.tar.bz2 bar nix-channel --update # Do a query. nix-env -qa \* --meta --xml --out-path > $TEST_ROOT/meta.xml grep -q 'meta.*description.*Random test package' $TEST_ROOT/meta.xml +grep -q 'item.*attrPath="bar".*name="dependencies-top"' $TEST_ROOT/meta.xml grep -q 'item.*attrPath="foo".*name="dependencies-top"' $TEST_ROOT/meta.xml # Do an install. diff --git a/tests/nix-shell.sh b/tests/nix-shell.sh index a31d35887..3241d7a0f 100644 --- a/tests/nix-shell.sh +++ b/tests/nix-shell.sh @@ -3,59 +3,53 @@ source common.sh clearStore if [[ -n ${CONTENT_ADDRESSED:-} ]]; then - nix-shell () { - command nix-shell --arg contentAddressed true "$@" - } - - nix_develop() { - nix develop --arg contentAddressed true "$@" - } + shellDotNix="$PWD/ca-shell.nix" else - nix_develop() { - nix develop "$@" - } + shellDotNix="$PWD/shell.nix" fi +export NIX_PATH=nixpkgs="$shellDotNix" + # Test nix-shell -A export IMPURE_VAR=foo export SELECTED_IMPURE_VAR=baz -export NIX_BUILD_SHELL=$SHELL -output=$(nix-shell --pure shell.nix -A shellDrv --run \ + +output=$(nix-shell --pure "$shellDotNix" -A shellDrv --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') [ "$output" = " - foo - bar - true" ] # Test --keep -output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR shell.nix -A shellDrv --run \ +output=$(nix-shell --pure --keep SELECTED_IMPURE_VAR "$shellDotNix" -A shellDrv --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $SELECTED_IMPURE_VAR"') [ "$output" = " - foo - bar - baz" ] # Test nix-shell on a .drv -[[ $(nix-shell --pure $(nix-instantiate shell.nix -A shellDrv) --run \ +[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]] -[[ $(nix-shell --pure $(nix-instantiate shell.nix -A shellDrv) --run \ +[[ $(nix-shell --pure $(nix-instantiate "$shellDotNix" -A shellDrv) --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX - $TEST_inNixShell"') = " - foo - bar - false" ]] # Test nix-shell on a .drv symlink # Legacy: absolute path and .drv extension required -nix-instantiate shell.nix -A shellDrv --add-root $TEST_ROOT/shell.drv +nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell.drv [[ $(nix-shell --pure $TEST_ROOT/shell.drv --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]] # New behaviour: just needs to resolve to a derivation in the store -nix-instantiate shell.nix -A shellDrv --add-root $TEST_ROOT/shell +nix-instantiate "$shellDotNix" -A shellDrv --add-root $TEST_ROOT/shell [[ $(nix-shell --pure $TEST_ROOT/shell --run \ 'echo "$IMPURE_VAR - $VAR_FROM_STDENV_SETUP - $VAR_FROM_NIX"') = " - foo - bar" ]] # Test nix-shell -p -output=$(NIX_PATH=nixpkgs=shell.nix nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"') +output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo bar --run 'echo "$(foo) $(bar)"') [ "$output" = "foo bar" ] # Test nix-shell -p --arg x y -output=$(NIX_PATH=nixpkgs=shell.nix nix-shell --pure -p foo --argstr fooContents baz --run 'echo "$(foo)"') +output=$(NIX_PATH=nixpkgs="$shellDotNix" nix-shell --pure -p foo --argstr fooContents baz --run 'echo "$(foo)"') [ "$output" = "baz" ] # Test nix-shell shebang mode @@ -91,18 +85,18 @@ output=$($TEST_ROOT/spaced\ \\\'\"shell.shebang.rb abc ruby) [ "$output" = '-e load(ARGV.shift) -- '"$TEST_ROOT"'/spaced \'\''"shell.shebang.rb abc ruby' ] # Test 'nix develop'. -nix_develop -f shell.nix shellDrv -c bash -c '[[ -n $stdenv ]]' +nix develop -f "$shellDotNix" shellDrv -c bash -c '[[ -n $stdenv ]]' # Ensure `nix develop -c` preserves stdin -echo foo | nix develop -f shell.nix shellDrv -c cat | grep -q foo +echo foo | nix develop -f "$shellDotNix" shellDrv -c cat | grep -q foo # Ensure `nix develop -c` actually executes the command if stdout isn't a terminal -nix_develop -f shell.nix shellDrv -c echo foo |& grep -q foo +nix develop -f "$shellDotNix" shellDrv -c echo foo |& grep -q foo # Test 'nix print-dev-env'. -[[ $(nix print-dev-env -f shell.nix shellDrv --json | jq -r .variables.arr1.value[2]) = '3 4' ]] +[[ $(nix print-dev-env -f "$shellDotNix" shellDrv --json | jq -r .variables.arr1.value[2]) = '3 4' ]] -source <(nix print-dev-env -f shell.nix shellDrv) +source <(nix print-dev-env -f "$shellDotNix" shellDrv) [[ -n $stdenv ]] [[ ${arr1[2]} = "3 4" ]] [[ ${arr2[1]} = $'\n' ]] diff --git a/tests/nix_path.sh b/tests/nix_path.sh new file mode 100644 index 000000000..d3657abf0 --- /dev/null +++ b/tests/nix_path.sh @@ -0,0 +1,11 @@ +# Regression for https://github.com/NixOS/nix/issues/5998 and https://github.com/NixOS/nix/issues/5980 + +source common.sh + +export NIX_PATH=non-existent=/non-existent/but-unused-anyways:by-absolute-path=$PWD:by-relative-path=. + +nix-instantiate --eval -E '<by-absolute-path/simple.nix>' --restrict-eval +nix-instantiate --eval -E '<by-relative-path/simple.nix>' --restrict-eval + +# Should ideally also test this, but there’s no pure way to do it, so just trust me that it works +# nix-instantiate --eval -E '<nixpkgs>' -I nixpkgs=channel:nixos-unstable --restrict-eval diff --git a/tests/plugins/plugintest.cc b/tests/plugins/plugintest.cc index c085d3329..cd7c9f8b1 100644 --- a/tests/plugins/plugintest.cc +++ b/tests/plugins/plugintest.cc @@ -16,9 +16,9 @@ static GlobalConfig::Register rs(&mySettings); static void prim_anotherNull (EvalState & state, const Pos & pos, Value ** args, Value & v) { if (mySettings.settingSet) - mkNull(v); + v.mkNull(); else - mkBool(v, false); + v.mkBool(false); } static RegisterPrimOp rp("anotherNull", 0, prim_anotherNull); diff --git a/tests/pure-eval.sh b/tests/pure-eval.sh index c994fbb98..1a4568ea6 100644 --- a/tests/pure-eval.sh +++ b/tests/pure-eval.sh @@ -6,7 +6,13 @@ nix eval --expr 'assert 1 + 2 == 3; true' [[ $(nix eval --impure --expr 'builtins.readFile ./pure-eval.sh') =~ clearStore ]] -(! nix eval --expr 'builtins.readFile ./pure-eval.sh') +missingImpureErrorMsg=$(! nix eval --expr 'builtins.readFile ./pure-eval.sh' 2>&1) + +echo "$missingImpureErrorMsg" | grep -q -- --impure || \ + fail "The error message should mention the “--impure” flag to unblock users" + +[[ $(nix eval --expr 'builtins.pathExists ./pure-eval.sh') == false ]] || \ + fail "Calling 'pathExists' on a non-authorised path should return false" (! nix eval --expr builtins.currentTime) (! nix eval --expr builtins.currentSystem) diff --git a/tests/readfile-context.builder.sh b/tests/readfile-context.builder.sh new file mode 100644 index 000000000..7084a08cb --- /dev/null +++ b/tests/readfile-context.builder.sh @@ -0,0 +1 @@ +echo "$input" > $out diff --git a/tests/readfile-context.nix b/tests/readfile-context.nix new file mode 100644 index 000000000..600036a94 --- /dev/null +++ b/tests/readfile-context.nix @@ -0,0 +1,19 @@ +with import ./config.nix; + +let + + input = import ./simple.nix; + + dependent = mkDerivation { + name = "dependent"; + builder = ./readfile-context.builder.sh; + input = "${input}/hello"; + }; + + readDependent = mkDerivation { + name = "read-dependent"; + builder = ./readfile-context.builder.sh; + input = builtins.readFile dependent; + }; + +in readDependent diff --git a/tests/readfile-context.sh b/tests/readfile-context.sh new file mode 100644 index 000000000..31e70ddb1 --- /dev/null +++ b/tests/readfile-context.sh @@ -0,0 +1,16 @@ +source common.sh + +clearStore + +outPath=$(nix-build --no-out-link readfile-context.nix) + +# Set a GC root. +ln -s $outPath "$NIX_STATE_DIR"/gcroots/foo + +# Check that file exists. +[ "$(cat $(cat $outPath))" = "Hello World!" ] + +nix-collect-garbage + +# Check that file still exists. +[ "$(cat $(cat $outPath))" = "Hello World!" ] diff --git a/tests/repair.sh b/tests/repair.sh index 12dcde8ea..c8f07b1c6 100644 --- a/tests/repair.sh +++ b/tests/repair.sh @@ -30,7 +30,7 @@ nix-store --verify-path $path2 chmod u+w $path2 touch $path2/bad -nix-store --delete $(nix-store -qd $path2) +nix-store --delete $(nix-store -q --referrers-closure $(nix-store -qd $path2)) (! nix-store --verify --check-contents --repair) @@ -74,3 +74,50 @@ if [ "$(nix-hash $path2)" != "$hash" -o -e $path2/bad ]; then echo "path not repaired properly" >&2 exit 1 fi + +# Check that --repair-path also checks content of optimised symlinks (1/2) +nix-store --verify-path $path2 + +if (! nix-store --optimize); then + echo "nix-store --optimize failed to optimize the store" >&2 + exit 1 +fi +chmod u+w $path2/bar +echo 'rabrab' > $path2/bar # different length + +if nix-store --verify-path $path2; then + echo "nix-store --verify-path did not detect .links file corruption" >&2 + exit 1 +fi + +nix-store --repair-path $path2 --option auto-optimise-store true + +if [ "$(nix-hash $path2)" != "$hash" -o "BAR" != "$(< $path2/bar)" ]; then + echo "path not repaired properly" >&2 + exit 1 +fi + +# Check that --repair-path also checks content of optimised symlinks (2/2) +nix-store --verify-path $path2 + +if (! nix-store --optimize); then + echo "nix-store --optimize failed to optimize the store" >&2 + exit 1 +fi +chmod u+w $path2 +chmod u+w $path2/bar +sed -e 's/./X/g' < $path2/bar > $path2/tmp # same length, different content. +cp $path2/tmp $path2/bar +rm $path2/tmp + +if nix-store --verify-path $path2; then + echo "nix-store --verify-path did not detect .links file corruption" >&2 + exit 1 +fi + +nix-store --repair-path $path2 --substituters "file://$cacheDir" --no-require-sigs --option auto-optimise-store true + +if [ "$(nix-hash $path2)" != "$hash" -o "BAR" != "$(< $path2/bar)" ]; then + echo "path not repaired properly" >&2 + exit 1 +fi diff --git a/tests/repl.sh b/tests/repl.sh index 4e3059517..6505f1741 100644 --- a/tests/repl.sh +++ b/tests/repl.sh @@ -1,18 +1,65 @@ source common.sh replCmds=" +simple = 1 simple = import ./simple.nix :b simple +:log simple +" + +replFailingCmds=" +failing = import ./simple-failing.nix +:b failing +:log failing +" + +replUndefinedVariable=" +import ./undefined-variable.nix " testRepl () { local nixArgs=("$@") - local outPath=$(nix repl "${nixArgs[@]}" <<< "$replCmds" |& + local replOutput="$(nix repl "${nixArgs[@]}" <<< "$replCmds")" + echo "$replOutput" + local outPath=$(echo "$replOutput" |& grep -o -E "$NIX_STORE_DIR/\w*-simple") nix path-info "${nixArgs[@]}" "$outPath" + # simple.nix prints a PATH during build + echo "$replOutput" | grep -qs 'PATH=' || fail "nix repl :log doesn't output logs" + local replOutput="$(nix repl "${nixArgs[@]}" <<< "$replFailingCmds" 2>&1)" + echo "$replOutput" + echo "$replOutput" | grep -qs 'This should fail' \ + || fail "nix repl :log doesn't output logs for a failed derivation" + local replOutput="$(nix repl --show-trace "${nixArgs[@]}" <<< "$replUndefinedVariable" 2>&1)" + echo "$replOutput" + echo "$replOutput" | grep -qs "while evaluating the file" \ + || fail "nix repl --show-trace doesn't show the trace" } # Simple test, try building a drv testRepl # Same thing (kind-of), but with a remote store. testRepl --store "$TEST_ROOT/store?real=$NIX_STORE_DIR" + +testReplResponse () { + local response="$(nix repl <<< "$1")" + echo "$response" | grep -qs "$2" \ + || fail "repl command set: + +$1 + +does not respond with: + +$2 + +but with: + +$response" +} + +# :a uses the newest version of a symbol +testReplResponse ' +:a { a = "1"; } +:a { a = "2"; } +"result: ${a}" +' "result: 2" diff --git a/tests/search.sh b/tests/search.sh index ee3261687..52e12f381 100644 --- a/tests/search.sh +++ b/tests/search.sh @@ -23,3 +23,16 @@ clearCache nix search -f search.nix '' |grep -q foo nix search -f search.nix '' |grep -q bar nix search -f search.nix '' |grep -q hello + +## Tests for multiple regex/match highlighting + +e=$'\x1b' # grep doesn't support \e, \033 or even \x1b +# Multiple overlapping regexes +(( $(nix search -f search.nix '' 'oo' 'foo' 'oo' | grep "$e\[32;1mfoo$e\\[0;1m" | wc -l) == 1 )) +(( $(nix search -f search.nix '' 'broken b' 'en bar' | grep "$e\[32;1mbroken bar$e\\[0m" | wc -l) == 1 )) + +# Multiple matches +# Searching for 'o' should yield the 'o' in 'broken bar', the 'oo' in foo and 'o' in hello +(( $(nix search -f search.nix '' 'o' | grep -Eo "$e\[32;1mo{1,2}$e\[(0|0;1)m" | wc -l) == 3 )) +# Searching for 'b' should yield the 'b' in bar and the two 'b's in 'broken bar' +(( $(nix search -f search.nix '' 'b' | grep -Eo "$e\[32;1mb$e\[(0|0;1)m" | wc -l) == 3 )) diff --git a/tests/shell.nix b/tests/shell.nix index 4912d295a..92d94fbc2 100644 --- a/tests/shell.nix +++ b/tests/shell.nix @@ -74,6 +74,10 @@ let pkgs = rec { ''; bash = shell; + bashInteractive = runCommand "bash" {} '' + mkdir -p $out/bin + ln -s ${shell} $out/bin/bash + ''; # ruby "interpreter" that outputs "$@" ruby = runCommand "ruby" {} '' diff --git a/tests/simple-failing.nix b/tests/simple-failing.nix new file mode 100644 index 000000000..d176c9c51 --- /dev/null +++ b/tests/simple-failing.nix @@ -0,0 +1,12 @@ +with import ./config.nix; + +mkDerivation { + name = "simple-failing"; + builder = builtins.toFile "builder.sh" + '' + echo "This should fail" + exit 1 + ''; + PATH = ""; + goodPath = path; +} diff --git a/tests/simple.sh b/tests/simple.sh index 15bd2bd16..50d44f93f 100644 --- a/tests/simple.sh +++ b/tests/simple.sh @@ -25,3 +25,9 @@ if test "$outPath" != "/foo/lfy1s6ca46rm5r6w4gg9hc0axiakjcnm-dependencies.drv"; echo "hashDerivationModulo appears broken, got $outPath" exit 1 fi + +outPath="$(NIX_REMOTE=local?store=/foo\&real=$TEST_ROOT/real-store nix-instantiate --readonly-mode big-derivation-attr.nix)" +if test "$outPath" != "/foo/xxiwa5zlaajv6xdjynf9yym9g319d6mn-big-derivation-attr.drv"; then + echo "big-derivation-attr.nix hash appears broken, got $outPath. Memory corruption in large drv attr?" + exit 1 +fi diff --git a/tests/sourcehut-flakes.nix b/tests/sourcehut-flakes.nix new file mode 100644 index 000000000..d1d89d149 --- /dev/null +++ b/tests/sourcehut-flakes.nix @@ -0,0 +1,156 @@ +{ nixpkgs, system, overlay }: + +with import (nixpkgs + "/nixos/lib/testing-python.nix") +{ + inherit system; + extraConfigurations = [{ nixpkgs.overlays = [ overlay ]; }]; +}; + +let + # Generate a fake root CA and a fake git.sr.ht certificate. + cert = pkgs.runCommand "cert" { buildInputs = [ pkgs.openssl ]; } + '' + mkdir -p $out + + openssl genrsa -out ca.key 2048 + openssl req -new -x509 -days 36500 -key ca.key \ + -subj "/C=NL/ST=Denial/L=Springfield/O=Dis/CN=Root CA" -out $out/ca.crt + + openssl req -newkey rsa:2048 -nodes -keyout $out/server.key \ + -subj "/C=CN/ST=Denial/L=Springfield/O=Dis/CN=git.sr.ht" -out server.csr + openssl x509 -req -extfile <(printf "subjectAltName=DNS:git.sr.ht") \ + -days 36500 -in server.csr -CA $out/ca.crt -CAkey ca.key -CAcreateserial -out $out/server.crt + ''; + + registry = pkgs.writeTextFile { + name = "registry"; + text = '' + { + "flakes": [ + { + "from": { + "type": "indirect", + "id": "nixpkgs" + }, + "to": { + "type": "sourcehut", + "owner": "~NixOS", + "repo": "nixpkgs" + } + } + ], + "version": 2 + } + ''; + destination = "/flake-registry.json"; + }; + + nixpkgs-repo = pkgs.runCommand "nixpkgs-flake" { } + '' + dir=NixOS-nixpkgs-${nixpkgs.shortRev} + cp -prd ${nixpkgs} $dir + + # Set the correct timestamp in the tarball. + find $dir -print0 | xargs -0 touch -t ${builtins.substring 0 12 nixpkgs.lastModifiedDate}.${builtins.substring 12 2 nixpkgs.lastModifiedDate} -- + + mkdir -p $out/archive + tar cfz $out/archive/${nixpkgs.rev}.tar.gz $dir --hard-dereference + + echo 'ref: refs/heads/master' > $out/HEAD + + mkdir -p $out/info + echo '${nixpkgs.rev} refs/heads/master' > $out/info/refs + ''; + +in + +makeTest ( + + { + name = "sourcehut-flakes"; + + nodes = + { + # Impersonate git.sr.ht + sourcehut = + { config, pkgs, ... }: + { + networking.firewall.allowedTCPPorts = [ 80 443 ]; + + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.httpd.extraConfig = '' + ErrorLog syslog:local6 + ''; + services.httpd.virtualHosts."git.sr.ht" = + { + forceSSL = true; + sslServerKey = "${cert}/server.key"; + sslServerCert = "${cert}/server.crt"; + servedDirs = + [ + { + urlPath = "/~NixOS/nixpkgs"; + dir = nixpkgs-repo; + } + { + urlPath = "/~NixOS/flake-registry/blob/master"; + dir = registry; + } + ]; + }; + }; + + client = + { config, lib, pkgs, nodes, ... }: + { + virtualisation.writableStore = true; + virtualisation.diskSize = 2048; + virtualisation.pathsInNixDB = [ pkgs.hello pkgs.fuse ]; + virtualisation.memorySize = 4096; + nix.binaryCaches = lib.mkForce [ ]; + nix.extraOptions = '' + experimental-features = nix-command flakes + flake-registry = https://git.sr.ht/~NixOS/flake-registry/blob/master/flake-registry.json + ''; + environment.systemPackages = [ pkgs.jq ]; + networking.hosts.${(builtins.head nodes.sourcehut.config.networking.interfaces.eth1.ipv4.addresses).address} = + [ "git.sr.ht" ]; + security.pki.certificateFiles = [ "${cert}/ca.crt" ]; + }; + }; + + testScript = { nodes }: '' + # fmt: off + import json + import time + + start_all() + + sourcehut.wait_for_unit("httpd.service") + + client.succeed("curl -v https://git.sr.ht/ >&2") + client.succeed("nix registry list | grep nixpkgs") + + rev = client.succeed("nix flake info nixpkgs --json | jq -r .revision") + assert rev.strip() == "${nixpkgs.rev}", "revision mismatch" + + client.succeed("nix registry pin nixpkgs") + + client.succeed("nix flake info nixpkgs --tarball-ttl 0 >&2") + + # Shut down the web server. The flake should be cached on the client. + sourcehut.succeed("systemctl stop httpd.service") + + info = json.loads(client.succeed("nix flake info nixpkgs --json")) + date = time.strftime("%Y%m%d%H%M%S", time.gmtime(info['lastModified'])) + assert date == "${nixpkgs.lastModifiedDate}", "time mismatch" + + client.succeed("nix build nixpkgs#hello") + + # The build shouldn't fail even with --tarball-ttl 0 (the server + # being down should not be a fatal error). + client.succeed("nix build nixpkgs#fuse --tarball-ttl 0") + ''; + + }) diff --git a/tests/store-ping.sh b/tests/store-ping.sh new file mode 100644 index 000000000..f9427cf0a --- /dev/null +++ b/tests/store-ping.sh @@ -0,0 +1,13 @@ +source common.sh + +STORE_INFO=$(nix store ping 2>&1) + +echo "$STORE_INFO" | grep "Store URL: ${NIX_REMOTE}" + +if [[ -v NIX_DAEMON_PACKAGE ]] && isDaemonNewer "2.7.0pre20220126"; then + DAEMON_VERSION=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3) + echo "$STORE_INFO" | grep "Version: $DAEMON_VERSION" +fi + +expect 127 NIX_REMOTE=unix:$PWD/store nix store ping || \ + fail "nix store ping on a non-existent store should fail" diff --git a/tests/structured-attrs.sh b/tests/structured-attrs.sh index e585ce37f..378dbc735 100644 --- a/tests/structured-attrs.sh +++ b/tests/structured-attrs.sh @@ -2,7 +2,7 @@ source common.sh # 27ce722638 required some incompatible changes to the nix file, so skip this # tests for the older versions -requireDaemonNewerThan "2.4pre20210622" +requireDaemonNewerThan "2.4pre20210712" clearStore diff --git a/tests/undefined-variable.nix b/tests/undefined-variable.nix new file mode 100644 index 000000000..579985497 --- /dev/null +++ b/tests/undefined-variable.nix @@ -0,0 +1 @@ +let f = builtins.toFile "test-file.nix" "asd"; in import f diff --git a/tests/user-envs.nix b/tests/user-envs.nix index 43eff1a68..6ac896ed8 100644 --- a/tests/user-envs.nix +++ b/tests/user-envs.nix @@ -9,7 +9,8 @@ assert foo == "foo"; let makeDrv = name: progName: (mkDerivation { - inherit name progName system; + name = assert progName != "fail"; name; + inherit progName system; builder = ./user-envs.builder.sh; } // { meta = { @@ -26,4 +27,5 @@ in (makeDrv "foo-2.0" "foo") (makeDrv "bar-0.1.1" "bar") (makeDrv "foo-0.1" "foo" // { meta.priority = 10; }) + (makeDrv "fail-0.1" "fail") ] diff --git a/tests/why-depends.sh b/tests/why-depends.sh new file mode 100644 index 000000000..c12941e76 --- /dev/null +++ b/tests/why-depends.sh @@ -0,0 +1,21 @@ +source common.sh + +clearStore + +cp ./dependencies.nix ./dependencies.builder0.sh ./config.nix $TEST_HOME + +cd $TEST_HOME + +nix-build ./dependencies.nix -A input0_drv -o dep +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" | grep -q input-2 +echo "$PRECISE_WHY_DEPENDS_OUTPUT" | grep -q input-2 + +# But only the “precise” one should refere to `reference-to-input-2` +echo "$FAST_WHY_DEPENDS_OUTPUT" | (! grep -q reference-to-input-2) +echo "$PRECISE_WHY_DEPENDS_OUTPUT" | grep -q reference-to-input-2 |