1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-12 19:05:08 +02:00

Merge commit 'b24757f08a' into sync-2.24.2

This commit is contained in:
Eelco Dolstra 2024-08-08 15:34:12 +02:00
commit c1d27763c6
330 changed files with 4907 additions and 1814 deletions

View file

@ -140,6 +140,18 @@ nix build --impure -f multiple-outputs.nix --json e --no-link | jq --exit-status
(.outputs | keys == ["a_a", "b"]))
'
# Make sure that the 3 types of aliases work
# BaseSettings<T>, BaseSettings<bool>, and BaseSettings<SandboxMode>.
nix build --impure -f multiple-outputs.nix --json e --no-link \
--build-max-jobs 3 \
--gc-keep-outputs \
--build-use-sandbox | \
jq --exit-status '
(.[0] |
(.drvPath | match(".*multiple-outputs-e.drv")) and
(.outputs | keys == ["a_a", "b"]))
'
# Make sure that `--stdin` works and does not apply any defaults
printf "" | nix build --no-link --stdin --json | jq --exit-status '. == []'
printf "%s\n" "$drv^*" | nix build --no-link --stdin --json | jq --exit-status '.[0]|has("drvPath")'

View file

@ -190,7 +190,7 @@ isDaemonNewer () {
skipTest () {
echo "$1, skipping this test..." >&2
exit 99
exit 77
}
TODO_NixOS() {
@ -236,7 +236,8 @@ expect() {
expected="$1"
shift
"$@" && res=0 || res="$?"
if [[ $res -ne $expected ]]; then
# also match "negative" codes, which wrap around to >127
if [[ $res -ne $expected && $res -ne $[256 + expected] ]]; then
echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2
return 1
fi
@ -250,7 +251,8 @@ expectStderr() {
expected="$1"
shift
"$@" 2>&1 && res=0 || res="$?"
if [[ $res -ne $expected ]]; then
# also match "negative" codes, which wrap around to >127
if [[ $res -ne $expected && $res -ne $[256 + expected] ]]; then
echo "Expected exit code '$expected' but got '$res' from command ${*@Q}" >&2
return 1
fi
@ -295,13 +297,67 @@ onError() {
done
}
# Prints an error message prefix referring to the last call into this file.
# Ignores `expect` and `expectStderr` calls.
# Set a special exit code when test suite functions are misused, so that
# functions like expectStderr won't mistake them for expected Nix CLI errors.
# Suggestion: -101 (negative to indicate very abnormal, and beyond the normal
# range of signals)
# Example (showns as string): 'repl.sh:123: in call to grepQuiet: '
# This function is inefficient, so it should only be used in error messages.
callerPrefix() {
# Find the closest caller that's not from this file
# using the bash `caller` builtin.
local i file line fn savedFn
# Use `caller`
for i in $(seq 0 100); do
caller $i > /dev/null || {
if [[ -n "${file:-}" ]]; then
echo "$file:$line: ${savedFn+in call to $savedFn: }"
fi
break
}
line="$(caller $i | cut -d' ' -f1)"
fn="$(caller $i | cut -d' ' -f2)"
file="$(caller $i | cut -d' ' -f3)"
if [[ $file != "${BASH_SOURCE[0]}" ]]; then
echo "$file:$line: ${savedFn+in call to $savedFn: }"
return
fi
case "$fn" in
# Ignore higher order functions that don't report any misuse of themselves
# This way a misuse of a foo in `expectStderr 1 foo` will be reported as
# calling foo, not expectStderr.
expect|expectStderr|callerPrefix)
;;
*)
savedFn="$fn"
;;
esac
done
}
checkGrepArgs() {
local arg
for arg in "$@"; do
if [[ "$arg" != "${arg//$'\n'/_}" ]]; then
echo "$(callerPrefix)newline not allowed in arguments; grep would try each line individually as if connected by an OR operator" >&2
return -101
fi
done
}
# `grep -v` doesn't work well for exit codes. We want `!(exist line l. l
# matches)`. It gives us `exist line l. !(l matches)`.
#
# `!` normally doesn't work well with `set -e`, but when we wrap in a
# function it *does*.
#
# `command grep` lets us avoid re-checking the args by going directly to the
# executable.
grepInverse() {
! grep "$@"
checkGrepArgs "$@" && \
! command grep "$@"
}
# A shorthand, `> /dev/null` is a bit noisy.
@ -315,13 +371,26 @@ grepInverse() {
# the closing of the pipe, the buffering of the pipe, and the speed of
# the producer into the pipe. But rest assured we've seen it happen in
# CI reliably.
#
# `command grep` lets us avoid re-checking the args by going directly to the
# executable.
grepQuiet() {
grep "$@" > /dev/null
checkGrepArgs "$@" && \
command grep "$@" > /dev/null
}
# The previous two, combined
grepQuietInverse() {
! grep "$@" > /dev/null
checkGrepArgs "$@" && \
! command grep "$@" > /dev/null
}
# Wrap grep to remove its newline footgun; see checkGrepArgs.
# Note that we keep the checkGrepArgs calls in the other helpers, because some
# of them are negated and that would defeat this check.
grep() {
checkGrepArgs "$@" && \
command grep "$@"
}
# Return the number of arguments

View file

@ -58,3 +58,7 @@ fi
# Test that unknown settings are warned about
out="$(expectStderr 0 nix eval --option foobar baz --expr '""' --raw)"
[[ "$(echo "$out" | grep foobar | wc -l)" = 1 ]]
# Test flag alias
out="$(nix eval --expr '{}' --build-cores 1)"
[[ "$(echo "$out" | wc -l)" = 1 ]]

View file

@ -0,0 +1,24 @@
flake-tests := \
$(d)/flakes.sh \
$(d)/develop.sh \
$(d)/edit.sh \
$(d)/run.sh \
$(d)/mercurial.sh \
$(d)/circular.sh \
$(d)/init.sh \
$(d)/inputs.sh \
$(d)/follow-paths.sh \
$(d)/bundle.sh \
$(d)/check.sh \
$(d)/unlocked-override.sh \
$(d)/absolute-paths.sh \
$(d)/absolute-attr-paths.sh \
$(d)/build-paths.sh \
$(d)/flake-in-submodule.sh \
$(d)/prefetch.sh \
$(d)/eval-cache.sh \
$(d)/search-root.sh \
$(d)/config.sh \
$(d)/show.sh
install-tests-groups += flake

View file

@ -29,5 +29,26 @@ nix run --no-write-lock-file .#pkgAsPkg
! nix run --no-write-lock-file .#pkgAsApp || fail "'nix run' shouldnt accept an 'app' defined under 'packages'"
! nix run --no-write-lock-file .#appAsPkg || fail "elements of 'apps' should be of type 'app'"
# Test that we're not setting any more environment variables than necessary.
# For instance, we might set an environment variable temporarily to affect some
# initialization or whatnot, but this must not leak into the environment of the
# command being run.
env > $TEST_ROOT/expected-env
nix run -f shell-hello.nix env > $TEST_ROOT/actual-env
# Remove/reset variables we expect to be different.
# - PATH is modified by nix shell
# - _ is set by bash and is expected to differ because it contains the original command
# - __CF_USER_TEXT_ENCODING is set by macOS and is beyond our control
sed -i \
-e 's/PATH=.*/PATH=.../' \
-e 's/_=.*/_=.../' \
-e '/^__CF_USER_TEXT_ENCODING=.*$/d' \
$TEST_ROOT/expected-env $TEST_ROOT/actual-env
sort $TEST_ROOT/expected-env | uniq > $TEST_ROOT/expected-env.sorted
# nix run appears to clear _. I don't understand why. Is this ok?
echo "_=..." >> $TEST_ROOT/actual-env
sort $TEST_ROOT/actual-env | uniq > $TEST_ROOT/actual-env.sorted
diff $TEST_ROOT/expected-env.sorted $TEST_ROOT/actual-env.sorted
clearStore

View file

@ -0,0 +1,36 @@
# shellcheck shell=bash
# Regression tests for the evaluator
# These are not in lang.sh because they generally only need to run in CI,
# whereas lang.sh is often run locally during development
source common.sh
set -o pipefail
skipTest "Too memory instensive for CI. Attempt to reduce memory usage was unsuccessful, because it made detection of the bug unreliable."
# Regression test for #11141. The stack pointer corrector assigned the base
# instead of the top (which resides at the low end of the stack). Sounds confusing?
# Stacks grow downwards, so that's why this mistake happened.
# My manual testing did not uncover this, because it didn't rely on the stack enough.
# https://github.com/NixOS/nix/issues/11141
test_issue_11141() {
mkdir -p "$TEST_ROOT/issue-11141/src"
cp lang-gc/issue-11141-gc-coroutine-test.nix "$TEST_ROOT/issue-11141/"
(
set +x;
n=10
echo "populating $TEST_ROOT/issue-11141/src with $((n*100)) files..."
for i in $(seq 0 $n); do
touch "$TEST_ROOT/issue-11141/src/file-$i"{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}
done
)
GC_INITIAL_HEAP_SIZE=$((1024 * 1024)) \
NIX_SHOW_STATS=1 \
nix eval -vvv\
-f "$TEST_ROOT/issue-11141/issue-11141-gc-coroutine-test.nix"
}
test_issue_11141

View file

@ -0,0 +1,65 @@
# Run:
# GC_INITIAL_HEAP_SIZE=$[1024 * 1024] NIX_SHOW_STATS=1 nix eval -f gc-coroutine-test.nix -vvvv
let
inherit (builtins)
foldl'
isList
;
# Generate a tree of numbers, n deep, such that the numbers add up to (1 + salt) * 10^n.
# The salting makes the numbers all different, increasing the likelihood of catching
# any memory corruptions that might be caused by the GC or otherwise.
garbage = salt: n:
if n == 0
then [(1 + salt)]
else [
(garbage (10 * salt + 1) (n - 1))
(garbage (10 * salt - 1) (n - 1))
(garbage (10 * salt + 2) (n - 1))
(garbage (10 * salt - 2) (n - 1))
(garbage (10 * salt + 3) (n - 1))
(garbage (10 * salt - 3) (n - 1))
(garbage (10 * salt + 4) (n - 1))
(garbage (10 * salt - 4) (n - 1))
(garbage (10 * salt + 5) (n - 1))
(garbage (10 * salt - 5) (n - 1))
];
pow = base: n:
if n == 0
then 1
else base * (pow base (n - 1));
sumNestedLists = l:
if isList l
then foldl' (a: b: a + sumNestedLists b) 0 l
else l;
in
assert sumNestedLists (garbage 0 3) == pow 10 3;
assert sumNestedLists (garbage 0 6) == pow 10 6;
builtins.foldl'
(a: b:
assert
"${
builtins.path {
path = ./src;
filter = path: type:
# We're not doing common subexpression elimination, so this reallocates
# the fairly big tree over and over, producing a lot of garbage during
# source filtering, whose filter runs in a coroutine.
assert sumNestedLists (garbage 0 3) == pow 10 3;
true;
}
}"
== "${./src}";
# These asserts don't seem necessary, as the lambda value get corrupted first
assert a.okay;
assert b.okay;
{ okay = true; }
)
{ okay = true; }
[ { okay = true; } { okay = true; } { okay = true; } ]

View file

@ -50,11 +50,25 @@ set +x
badDiff=0
badExitCode=0
# Extra post-processing that's specific to each test case
postprocess() {
if [[ -e "lang/$1.postprocess" ]]; then
(
# We could allow arbitrary interpreters in .postprocess, but that
# just exposes us to the complexity of not having /usr/bin/env in
# the sandbox. So let's just hardcode bash for now.
set -x;
bash "lang/$1.postprocess" "lang/$1"
)
fi
}
for i in lang/parse-fail-*.nix; do
echo "parsing $i (should fail)";
i=$(basename "$i" .nix)
if expectStderr 1 nix-instantiate --parse - < "lang/$i.nix" > "lang/$i.err"
then
postprocess "$i"
diffAndAccept "$i" err err.exp
else
echo "FAIL: $i shouldn't parse"
@ -71,6 +85,7 @@ for i in lang/parse-okay-*.nix; do
2> "lang/$i.err"
then
sed "s!$(pwd)!/pwd!g" "lang/$i.out" "lang/$i.err"
postprocess "$i"
diffAndAccept "$i" out exp
diffAndAccept "$i" err err.exp
else
@ -94,6 +109,7 @@ for i in lang/eval-fail-*.nix; do
expectStderr 1 nix-instantiate $flags "lang/$i.nix" \
| sed "s!$(pwd)!/pwd!g" > "lang/$i.err"
then
postprocess "$i"
diffAndAccept "$i" err err.exp
else
echo "FAIL: $i shouldn't evaluate"
@ -109,6 +125,7 @@ for i in lang/eval-okay-*.nix; do
if expect 0 nix-instantiate --eval --xml --no-location --strict \
"lang/$i.nix" > "lang/$i.out.xml"
then
postprocess "$i"
diffAndAccept "$i" out.xml exp.xml
else
echo "FAIL: $i should evaluate"
@ -129,6 +146,7 @@ for i in lang/eval-okay-*.nix; do
2> "lang/$i.err"
then
sed -i "s!$(pwd)!/pwd!g" "lang/$i.out" "lang/$i.err"
postprocess "$i"
diffAndAccept "$i" out exp
diffAndAccept "$i" err err.exp
else

View file

@ -0,0 +1,8 @@
error:
… while evaluating the condition of the assertion '({ a = true; } == { a = true; b = true; })'
at /pwd/lang/eval-fail-assert-equal-attrs-names-2.nix:1:1:
1| assert { a = true; } == { a = true; b = true; };
| ^
2| throw "unreachable"
error: attribute names of attribute set '{ a = true; }' differs from attribute set '{ a = true; b = true; }'

View file

@ -0,0 +1,2 @@
assert { a = true; } == { a = true; b = true; };
throw "unreachable"

View file

@ -0,0 +1,8 @@
error:
… while evaluating the condition of the assertion '({ a = true; b = true; } == { a = true; })'
at /pwd/lang/eval-fail-assert-equal-attrs-names.nix:1:1:
1| assert { a = true; b = true; } == { a = true; };
| ^
2| throw "unreachable"
error: attribute names of attribute set '{ a = true; b = true; }' differs from attribute set '{ a = true; }'

View file

@ -0,0 +1,2 @@
assert { a = true; b = true; } == { a = true; };
throw "unreachable"

View file

@ -0,0 +1,26 @@
error:
… while evaluating the condition of the assertion '({ foo = { outPath = "/nix/store/0"; type = "derivation"; }; } == { foo = { devious = true; outPath = "/nix/store/1"; type = "derivation"; }; })'
at /pwd/lang/eval-fail-assert-equal-derivations-extra.nix:1:1:
1| assert
| ^
2| { foo = { type = "derivation"; outPath = "/nix/store/0"; }; }
… while comparing attribute 'foo'
… where left hand side is
at /pwd/lang/eval-fail-assert-equal-derivations-extra.nix:2:5:
1| assert
2| { foo = { type = "derivation"; outPath = "/nix/store/0"; }; }
| ^
3| ==
… where right hand side is
at /pwd/lang/eval-fail-assert-equal-derivations-extra.nix:4:5:
3| ==
4| { foo = { type = "derivation"; outPath = "/nix/store/1"; devious = true; }; };
| ^
5| throw "unreachable"
… while comparing a derivation by its 'outPath' attribute
error: string '"/nix/store/0"' is not equal to string '"/nix/store/1"'

View file

@ -0,0 +1,5 @@
assert
{ foo = { type = "derivation"; outPath = "/nix/store/0"; }; }
==
{ foo = { type = "derivation"; outPath = "/nix/store/1"; devious = true; }; };
throw "unreachable"

View file

@ -0,0 +1,26 @@
error:
… while evaluating the condition of the assertion '({ foo = { ignored = (abort "not ignored"); outPath = "/nix/store/0"; type = "derivation"; }; } == { foo = { ignored = (abort "not ignored"); outPath = "/nix/store/1"; type = "derivation"; }; })'
at /pwd/lang/eval-fail-assert-equal-derivations.nix:1:1:
1| assert
| ^
2| { foo = { type = "derivation"; outPath = "/nix/store/0"; ignored = abort "not ignored"; }; }
… while comparing attribute 'foo'
… where left hand side is
at /pwd/lang/eval-fail-assert-equal-derivations.nix:2:5:
1| assert
2| { foo = { type = "derivation"; outPath = "/nix/store/0"; ignored = abort "not ignored"; }; }
| ^
3| ==
… where right hand side is
at /pwd/lang/eval-fail-assert-equal-derivations.nix:4:5:
3| ==
4| { foo = { type = "derivation"; outPath = "/nix/store/1"; ignored = abort "not ignored"; }; };
| ^
5| throw "unreachable"
… while comparing a derivation by its 'outPath' attribute
error: string '"/nix/store/0"' is not equal to string '"/nix/store/1"'

View file

@ -0,0 +1,5 @@
assert
{ foo = { type = "derivation"; outPath = "/nix/store/0"; ignored = abort "not ignored"; }; }
==
{ foo = { type = "derivation"; outPath = "/nix/store/1"; ignored = abort "not ignored"; }; };
throw "unreachable"

View file

@ -0,0 +1,22 @@
error:
… while evaluating the condition of the assertion '({ b = 1; } == { b = 1.01; })'
at /pwd/lang/eval-fail-assert-equal-floats.nix:1:1:
1| assert { b = 1.0; } == { b = 1.01; };
| ^
2| abort "unreachable"
… while comparing attribute 'b'
… where left hand side is
at /pwd/lang/eval-fail-assert-equal-floats.nix:1:10:
1| assert { b = 1.0; } == { b = 1.01; };
| ^
2| abort "unreachable"
… where right hand side is
at /pwd/lang/eval-fail-assert-equal-floats.nix:1:26:
1| assert { b = 1.0; } == { b = 1.01; };
| ^
2| abort "unreachable"
error: a float with value '1' is not equal to a float with value '1.01'

View file

@ -0,0 +1,2 @@
assert { b = 1.0; } == { b = 1.01; };
abort "unreachable"

View file

@ -0,0 +1,9 @@
error:
… while evaluating the condition of the assertion '((x: x) == (x: x))'
at /pwd/lang/eval-fail-assert-equal-function-direct.nix:3:1:
2| # This only compares a direct comparison and makes no claims about functions in nested structures.
3| assert
| ^
4| (x: x)
error: distinct functions and immediate comparisons of identical functions compare as unequal

View file

@ -0,0 +1,7 @@
# Note: functions in nested structures, e.g. attributes, may be optimized away by pointer identity optimization.
# This only compares a direct comparison and makes no claims about functions in nested structures.
assert
(x: x)
==
(x: x);
abort "unreachable"

View file

@ -0,0 +1,8 @@
error:
… while evaluating the condition of the assertion '(1 == 1.1)'
at /pwd/lang/eval-fail-assert-equal-int-float.nix:1:1:
1| assert 1 == 1.1;
| ^
2| throw "unreachable"
error: an integer with value '1' is not equal to a float with value '1.1'

View file

@ -0,0 +1,2 @@
assert 1 == 1.1;
throw "unreachable"

View file

@ -0,0 +1,22 @@
error:
… while evaluating the condition of the assertion '({ b = 1; } == { b = 2; })'
at /pwd/lang/eval-fail-assert-equal-ints.nix:1:1:
1| assert { b = 1; } == { b = 2; };
| ^
2| abort "unreachable"
… while comparing attribute 'b'
… where left hand side is
at /pwd/lang/eval-fail-assert-equal-ints.nix:1:10:
1| assert { b = 1; } == { b = 2; };
| ^
2| abort "unreachable"
… where right hand side is
at /pwd/lang/eval-fail-assert-equal-ints.nix:1:24:
1| assert { b = 1; } == { b = 2; };
| ^
2| abort "unreachable"
error: an integer with value '1' is not equal to an integer with value '2'

View file

@ -0,0 +1,2 @@
assert { b = 1; } == { b = 2; };
abort "unreachable"

View file

@ -0,0 +1,8 @@
error:
… while evaluating the condition of the assertion '([ (1) (0) ] == [ (10) ])'
at /pwd/lang/eval-fail-assert-equal-list-length.nix:1:1:
1| assert [ 1 0 ] == [ 10 ];
| ^
2| throw "unreachable"
error: list of size '2' is not equal to list of size '1', left hand side is '[ 1 0 ]', right hand side is '[ 10 ]'

View file

@ -0,0 +1,2 @@
assert [ 1 0 ] == [ 10 ];
throw "unreachable"

View file

@ -0,0 +1,8 @@
error:
… while evaluating the condition of the assertion '(/pwd/lang/foo == /pwd/lang/bar)'
at /pwd/lang/eval-fail-assert-equal-paths.nix:1:1:
1| assert ./foo == ./bar;
| ^
2| throw "unreachable"
error: path '/pwd/lang/foo' is not equal to path '/pwd/lang/bar'

View file

@ -0,0 +1,2 @@
assert ./foo == ./bar;
throw "unreachable"

View file

@ -0,0 +1,22 @@
error:
… while evaluating the condition of the assertion '({ ding = false; } == { ding = null; })'
at /pwd/lang/eval-fail-assert-equal-type-nested.nix:1:1:
1| assert { ding = false; } == { ding = null; };
| ^
2| abort "unreachable"
… while comparing attribute 'ding'
… where left hand side is
at /pwd/lang/eval-fail-assert-equal-type-nested.nix:1:10:
1| assert { ding = false; } == { ding = null; };
| ^
2| abort "unreachable"
… where right hand side is
at /pwd/lang/eval-fail-assert-equal-type-nested.nix:1:31:
1| assert { ding = false; } == { ding = null; };
| ^
2| abort "unreachable"
error: a Boolean of value 'false' is not equal to null of value 'null'

View file

@ -0,0 +1,2 @@
assert { ding = false; } == { ding = null; };
abort "unreachable"

View file

@ -0,0 +1,8 @@
error:
… while evaluating the condition of the assertion '(false == null)'
at /pwd/lang/eval-fail-assert-equal-type.nix:1:1:
1| assert false == null;
| ^
2| abort "unreachable"
error: a Boolean of value 'false' is not equal to null of value 'null'

View file

@ -0,0 +1,2 @@
assert false == null;
abort "unreachable"

View file

@ -0,0 +1,74 @@
error:
… while evaluating the condition of the assertion '({ a = { b = [ ({ c = { d = true; }; }) ]; }; } == { a = { b = [ ({ c = { d = false; }; }) ]; }; })'
at /pwd/lang/eval-fail-assert-nested-bool.nix:1:1:
1| assert
| ^
2| { a.b = [ { c.d = true; } ]; }
… while comparing attribute 'a'
… where left hand side is
at /pwd/lang/eval-fail-assert-nested-bool.nix:2:5:
1| assert
2| { a.b = [ { c.d = true; } ]; }
| ^
3| ==
… where right hand side is
at /pwd/lang/eval-fail-assert-nested-bool.nix:4:5:
3| ==
4| { a.b = [ { c.d = false; } ]; };
| ^
5|
… while comparing attribute 'b'
… where left hand side is
at /pwd/lang/eval-fail-assert-nested-bool.nix:2:5:
1| assert
2| { a.b = [ { c.d = true; } ]; }
| ^
3| ==
… where right hand side is
at /pwd/lang/eval-fail-assert-nested-bool.nix:4:5:
3| ==
4| { a.b = [ { c.d = false; } ]; };
| ^
5|
… while comparing list element 0
… while comparing attribute 'c'
… where left hand side is
at /pwd/lang/eval-fail-assert-nested-bool.nix:2:15:
1| assert
2| { a.b = [ { c.d = true; } ]; }
| ^
3| ==
… where right hand side is
at /pwd/lang/eval-fail-assert-nested-bool.nix:4:15:
3| ==
4| { a.b = [ { c.d = false; } ]; };
| ^
5|
… while comparing attribute 'd'
… where left hand side is
at /pwd/lang/eval-fail-assert-nested-bool.nix:2:15:
1| assert
2| { a.b = [ { c.d = true; } ]; }
| ^
3| ==
… where right hand side is
at /pwd/lang/eval-fail-assert-nested-bool.nix:4:15:
3| ==
4| { a.b = [ { c.d = false; } ]; };
| ^
5|
error: boolean 'true' is not equal to boolean 'false'

View file

@ -0,0 +1,6 @@
assert
{ a.b = [ { c.d = true; } ]; }
==
{ a.b = [ { c.d = false; } ]; };
abort "unreachable"

View file

@ -20,9 +20,11 @@ error:
| ^
3|
error: assertion '(arg == "y")' failed
at /pwd/lang/eval-fail-assert.nix:2:12:
… while evaluating the condition of the assertion '(arg == "y")'
at /pwd/lang/eval-fail-assert.nix:2:12:
1| let {
2| x = arg: assert arg == "y"; 123;
| ^
3|
error: string '"x"' is not equal to string '"y"'

View file

@ -1,26 +1,26 @@
error:
… while evaluating the attribute 'outPath'
at <nix/derivation-internal.nix>:19:9:
18| value = commonAttrs // {
19| outPath = builtins.getAttr outputName strict;
at <nix/derivation-internal.nix>:<number>:<number>:
<number>| value = commonAttrs // {
<number>| outPath = builtins.getAttr outputName strict;
| ^
20| drvPath = strict.drvPath;
<number>| drvPath = strict.drvPath;
… while calling the 'getAttr' builtin
at <nix/derivation-internal.nix>:19:19:
18| value = commonAttrs // {
19| outPath = builtins.getAttr outputName strict;
at <nix/derivation-internal.nix>:<number>:<number>:
<number>| value = commonAttrs // {
<number>| outPath = builtins.getAttr outputName strict;
| ^
20| drvPath = strict.drvPath;
<number>| drvPath = strict.drvPath;
… while calling the 'derivationStrict' builtin
at <nix/derivation-internal.nix>:9:12:
8|
9| strict = derivationStrict drvAttrs;
at <nix/derivation-internal.nix>:<number>:<number>:
<number>|
<number>| strict = derivationStrict drvAttrs;
| ^
10|
<number>|
… while evaluating derivation '~jiggle~'
whose name attribute is located at /pwd/lang/eval-fail-derivation-name.nix:2:3
whose name attribute is located at /pwd/lang/eval-fail-derivation-name.nix:<number>:<number>
error: invalid derivation name: name '~jiggle~' contains illegal character '~'. Please pass a different 'name'.

View file

@ -0,0 +1,9 @@
# shellcheck shell=bash
set -euo pipefail
testcaseBasename=$1
# Line numbers change when derivation.nix docs are updated.
sed -i "$testcaseBasename.err" \
-e 's/[0-9 ][0-9 ][0-9 ][0-9 ][0-9 ][0-9 ][0-9 ][0-9]\([^0-9]\)/<number>\1/g' \
-e 's/[0-9][0-9]*/<number>/g' \
;

View file

@ -0,0 +1,5 @@
error: experimental Nix feature 'pipe-operators' is disabled; add '--extra-experimental-features pipe-operators' to enable it
at /pwd/lang/eval-fail-pipe-operators.nix:1:3:
1| 1 |> 2
| ^
2|

View file

@ -0,0 +1 @@
1 |> 2

View file

@ -0,0 +1 @@
(let string = "str"; in [ (/some/path) ((/some/path)) ((/some/path)) ((/some/path + "\n end")) (string) ((string)) ((string)) ((string + "\n end")) ("") ("") ("end") ])

View file

@ -0,0 +1,31 @@
let
string = "str";
in [
/some/path
''${/some/path}''
''
${/some/path}''
''${/some/path}
end''
string
''${string}''
''
${string}''
''${string}
end''
''''
''
''
''
end''
]

View file

@ -1,28 +1,11 @@
nix_tests = \
test-infra.sh \
flakes/flakes.sh \
flakes/develop.sh \
flakes/edit.sh \
flakes/run.sh \
flakes/mercurial.sh \
flakes/circular.sh \
flakes/init.sh \
flakes/inputs.sh \
flakes/follow-paths.sh \
flakes/bundle.sh \
flakes/check.sh \
flakes/unlocked-override.sh \
flakes/absolute-paths.sh \
flakes/absolute-attr-paths.sh \
flakes/build-paths.sh \
flakes/flake-in-submodule.sh \
flakes/prefetch.sh \
flakes/eval-cache.sh \
gc.sh \
nix-collect-garbage-d.sh \
remote-store.sh \
legacy-ssh-store.sh \
lang.sh \
lang-gc.sh \
characterisation-test-infra.sh \
experimental-features.sh \
fetchMercurial.sh \
@ -60,7 +43,6 @@ nix_tests = \
restricted.sh \
fetchGitSubmodules.sh \
fetchGitVerification.sh \
flakes/search-root.sh \
readfile-context.sh \
nix-channel.sh \
recursive.sh \
@ -101,7 +83,6 @@ nix_tests = \
nix-copy-ssh-ng.sh \
post-hook.sh \
function-trace.sh \
flakes/config.sh \
fmt.sh \
eval-store.sh \
why-depends.sh \
@ -124,7 +105,6 @@ nix_tests = \
store-info.sh \
fetchClosure.sh \
completions.sh \
flakes/show.sh \
impure-derivations.sh \
path-from-hash-part.sh \
path-info.sh \

View file

@ -65,6 +65,25 @@ chmod a+rx $TEST_ROOT/shell.shebang.sh
output=$($TEST_ROOT/shell.shebang.sh abc def)
[ "$output" = "foo bar abc def" ]
# Test nix-shell shebang mode with an alternate working directory
sed -e "s|@ENV_PROG@|$(type -P env)|" shell.shebang.expr > $TEST_ROOT/shell.shebang.expr
chmod a+rx $TEST_ROOT/shell.shebang.expr
# Should fail due to expressions using relative path
! $TEST_ROOT/shell.shebang.expr bar
cp shell.nix config.nix $TEST_ROOT
# Should succeed
echo "cwd: $PWD"
output=$($TEST_ROOT/shell.shebang.expr bar)
[ "$output" = foo ]
# Test nix-shell shebang mode with an alternate working directory
sed -e "s|@ENV_PROG@|$(type -P env)|" shell.shebang.legacy.expr > $TEST_ROOT/shell.shebang.legacy.expr
chmod a+rx $TEST_ROOT/shell.shebang.legacy.expr
# Should fail due to expressions using relative path
mkdir -p "$TEST_ROOT/somewhere-unrelated"
output="$(cd "$TEST_ROOT/somewhere-unrelated"; $TEST_ROOT/shell.shebang.legacy.expr bar;)"
[[ $(realpath "$output") = $(realpath "$TEST_ROOT/somewhere-unrelated") ]]
# Test nix-shell shebang mode again with metacharacters in the filename.
# First word of filename is chosen to not match any file in the test root.
sed -e "s|@ENV_PROG@|$(type -P env)|" shell.shebang.sh > $TEST_ROOT/spaced\ \\\'\"shell.shebang.sh

View file

@ -14,3 +14,75 @@ nix-instantiate --eval -E '<by-relative-path/simple.nix>' --restrict-eval
[[ $(nix-instantiate --find-file by-absolute-path/simple.nix) = $PWD/simple.nix ]]
[[ $(nix-instantiate --find-file by-relative-path/simple.nix) = $PWD/simple.nix ]]
# this is the human-readable specification for the following test cases of interactions between various ways of specifying NIX_PATH.
# TODO: the actual tests are incomplete and too manual.
# there should be 43 of them, since the table has 9 rows and columns, and 2 interactions are meaningless
# ideally they would work off the table programmatically.
#
# | precedence | hard-coded | nix-path in file | extra-nix-path in file | nix-path in env | extra-nix-path in env | NIX_PATH | nix-path | extra-nix-path | -I |
# |------------------------|------------|------------------|------------------------|-----------------|-----------------------|-----------|-----------|-----------------|-----------------|
# | hard-coded | x | ^override | ^append | ^override | ^append | ^override | ^override | ^append | ^prepend |
# | nix-path in file | | last wins | ^append | ^override | ^append | ^override | ^override | ^append | ^prepend |
# | extra-nix-path in file | | | append in order | ^override | ^append | ^override | ^override | ^append | ^prepend |
# | nix-path in env | | | | last wins | ^append | ^override | ^override | ^append | ^prepend |
# | extra-nix-path in env | | | | | append in order | ^override | ^override | ^append | ^prepend |
# | NIX_PATH | | | | | | x | ^override | ^append | ^prepend |
# | nix-path | | | | | | | last wins | ^append | ^prepend |
# | extra-nix-path | | | | | | | | append in order | append in order |
# | -I | | | | | | | | | append in order |
unset NIX_PATH
mkdir -p $TEST_ROOT/{from-nix-path-file,from-NIX_PATH,from-nix-path,from-extra-nix-path,from-I}
for i in from-nix-path-file from-NIX_PATH from-nix-path from-extra-nix-path from-I; do
touch $TEST_ROOT/$i/only-$i.nix
done
# finding something that's not in any of the default paths fails
( ! $(nix-instantiate --find-file test) )
echo "nix-path = test=$TEST_ROOT/from-nix-path-file" >> "$test_nix_conf"
# Use nix.conf in absence of NIX_PATH
[[ $(nix-instantiate --find-file test) = $TEST_ROOT/from-nix-path-file ]]
# NIX_PATH overrides nix.conf
[[ $(NIX_PATH=test=$TEST_ROOT/from-NIX_PATH nix-instantiate --find-file test) = $TEST_ROOT/from-NIX_PATH ]]
# if NIX_PATH does not have the desired entry, it fails
(! NIX_PATH=test=$TEST_ROOT nix-instantiate --find-file test/only-from-nix-path-file.nix)
# -I extends nix.conf
[[ $(nix-instantiate -I test=$TEST_ROOT/from-I --find-file test/only-from-I.nix) = $TEST_ROOT/from-I/only-from-I.nix ]]
# if -I does not have the desired entry, the value from nix.conf is used
[[ $(nix-instantiate -I test=$TEST_ROOT/from-I --find-file test/only-from-nix-path-file.nix) = $TEST_ROOT/from-nix-path-file/only-from-nix-path-file.nix ]]
# -I extends NIX_PATH
[[ $(NIX_PATH=test=$TEST_ROOT/from-NIX_PATH nix-instantiate -I test=$TEST_ROOT/from-I --find-file test/only-from-I.nix) = $TEST_ROOT/from-I/only-from-I.nix ]]
# -I takes precedence over NIX_PATH
[[ $(NIX_PATH=test=$TEST_ROOT/from-NIX_PATH nix-instantiate -I test=$TEST_ROOT/from-I --find-file test) = $TEST_ROOT/from-I ]]
# if -I does not have the desired entry, the value from NIX_PATH is used
[[ $(NIX_PATH=test=$TEST_ROOT/from-NIX_PATH nix-instantiate -I test=$TEST_ROOT/from-I --find-file test/only-from-NIX_PATH.nix) = $TEST_ROOT/from-NIX_PATH/only-from-NIX_PATH.nix ]]
# --extra-nix-path extends NIX_PATH
[[ $(NIX_PATH=test=$TEST_ROOT/from-NIX_PATH nix-instantiate --extra-nix-path test=$TEST_ROOT/from-extra-nix-path --find-file test/only-from-extra-nix-path.nix) = $TEST_ROOT/from-extra-nix-path/only-from-extra-nix-path.nix ]]
# if --extra-nix-path does not have the desired entry, the value from NIX_PATH is used
[[ $(NIX_PATH=test=$TEST_ROOT/from-NIX_PATH nix-instantiate --extra-nix-path test=$TEST_ROOT/from-extra-nix-path --find-file test/only-from-NIX_PATH.nix) = $TEST_ROOT/from-NIX_PATH/only-from-NIX_PATH.nix ]]
# --nix-path overrides NIX_PATH
[[ $(NIX_PATH=test=$TEST_ROOT/from-NIX_PATH nix-instantiate --nix-path test=$TEST_ROOT/from-nix-path --find-file test) = $TEST_ROOT/from-nix-path ]]
# if --nix-path does not have the desired entry, it fails
(! NIX_PATH=test=$TEST_ROOT/from-NIX_PATH nix-instantiate --nix-path test=$TEST_ROOT/from-nix-path --find-file test/only-from-NIX_PATH.nix)
# --nix-path overrides nix.conf
[[ $(nix-instantiate --nix-path test=$TEST_ROOT/from-nix-path --find-file test) = $TEST_ROOT/from-nix-path ]]
(! nix-instantiate --nix-path test=$TEST_ROOT/from-nix-path --find-file test/only-from-nix-path-file.nix)
# --extra-nix-path extends nix.conf
[[ $(nix-instantiate --extra-nix-path test=$TEST_ROOT/from-extra-nix-path --find-file test/only-from-extra-nix-path.nix) = $TEST_ROOT/from-extra-nix-path/only-from-extra-nix-path.nix ]]
# if --extra-nix-path does not have the desired entry, it is taken from nix.conf
[[ $(nix-instantiate --extra-nix-path test=$TEST_ROOT/from-extra-nix-path --find-file test) = $TEST_ROOT/from-nix-path-file ]]
# -I extends --nix-path
[[ $(nix-instantiate --nix-path test=$TEST_ROOT/from-nix-path -I test=$TEST_ROOT/from-I --find-file test/only-from-I.nix) = $TEST_ROOT/from-I/only-from-I.nix ]]
[[ $(nix-instantiate --nix-path test=$TEST_ROOT/from-nix-path -I test=$TEST_ROOT/from-I --find-file test/only-from-nix-path.nix) = $TEST_ROOT/from-nix-path/only-from-nix-path.nix ]]

View file

@ -262,6 +262,23 @@ badExitCode=0
nixVersion="$(nix eval --impure --raw --expr 'builtins.nixVersion' --extra-experimental-features nix-command)"
# TODO: write a repl interacter for testing. Papering over the differences between readline / editline and between platforms is a pain.
# I couldn't get readline and editline to agree on the newline before the prompt,
# so let's just force it to be one empty line.
stripEmptyLinesBeforePrompt() {
# --null-data: treat input as NUL-terminated instead of newline-terminated
sed --null-data 's/\n\n*nix-repl>/\n\nnix-repl>/g'
}
# We don't get a final prompt on darwin, so we strip this as well.
stripFinalPrompt() {
# Strip the final prompt and/or any trailing spaces
sed --null-data \
-e 's/\(.*[^\n]\)\n\n*nix-repl>[ \n]*$/\1/' \
-e 's/[ \n]*$/\n/'
}
runRepl () {
# That is right, we are also filtering out the testdir _without underscores_.
@ -273,8 +290,13 @@ runRepl () {
testDirNoUnderscores="${testDir//_/}"
# TODO: pass arguments to nix repl; see lang.sh
_NIX_TEST_RAW_MARKDOWN=1 \
_NIX_TEST_REPL_ECHO=1 \
nix repl 2>&1 \
| stripColors \
| tr -d '\0' \
| stripEmptyLinesBeforePrompt \
| stripFinalPrompt \
| sed \
-e "s@$testDir@/path/to/tests/functional@g" \
-e "s@$testDirNoUnderscores@/path/to/tests/functional@g" \
@ -289,7 +311,10 @@ for test in $(cd "$testDir/repl"; echo *.in); do
in="$testDir/repl/$test.in"
actual="$testDir/repl/$test.actual"
expected="$testDir/repl/$test.expected"
(cd "$testDir/repl"; set +x; runRepl 2>&1) < "$in" > "$actual"
(cd "$testDir/repl"; set +x; runRepl 2>&1) < "$in" > "$actual" || {
echo "FAIL: $test (exit code $?)" >&2
badExitCode=1
}
diffAndAcceptInner "$test" "$actual" "$expected"
done

View file

@ -1,24 +1,28 @@
Nix <nix version>
Type :? for help.
nix-repl> :l doc-comments.nix
Added <number omitted> variables.
Function curriedArgs
… defined at
/path/to/tests/functional/repl/doc-comments.nix:48:5
nix-repl> :doc curriedArgs
Function `curriedArgs`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:48:5
A documented function.
A documented function.
nix-repl> x = curriedArgs 1
nix-repl> "Note that users may not expect this to behave as it currently does"
"Note that users may not expect this to behave as it currently does"
Function curriedArgs
… defined at
/path/to/tests/functional/repl/doc-comments.nix:50:5
nix-repl> :doc x
Function `curriedArgs`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:50:5
The function returned by applying once
The function returned by applying once
"This won't produce documentation, because we can't actually document arbitrary values"
nix-repl> "This won't produce docs; no support for arbitrary values"
"This won't produce docs; no support for arbitrary values"
nix-repl> :doc x 2
error: value does not have documentation

View file

@ -3,5 +3,5 @@
x = curriedArgs 1
"Note that users may not expect this to behave as it currently does"
:doc x
"This won't produce documentation, because we can't actually document arbitrary values"
"This won't produce docs; no support for arbitrary values"
:doc x 2

View file

@ -1,13 +1,14 @@
Nix <nix version>
Type :? for help.
nix-repl> :l doc-comments.nix
Added <number omitted> variables.
nix-repl> "Note that this is not yet complete"
"Note that this is not yet complete"
Function documentedFormals
… defined at
/path/to/tests/functional/repl/doc-comments.nix:57:5
Finds x
nix-repl> :doc documentedFormals
Function `documentedFormals`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:57:5
Finds x

View file

@ -1,8 +1,7 @@
Nix <nix version>
Type :? for help.
Function defined at
/path/to/tests/functional/repl/doc-comment-function.nix:2:1
A doc comment for a file that only contains a function
nix-repl> :doc import ./doc-comment-function.nix
Function defined at /path/to/tests/functional/repl/doc-comment-function.nix:2:1
A doc comment for a file that only contains a function

View file

@ -1,11 +1,11 @@
Nix <nix version>
Type :? for help.
nix-repl> :l doc-comments.nix
Added <number omitted> variables.
Function compact
… defined at
/path/to/tests/functional/repl/doc-comments.nix:18:20
boom
nix-repl> :doc compact
Function `compact`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:18:20
boom

View file

@ -1,23 +1,27 @@
Nix <nix version>
Type :? for help.
nix-repl> :l doc-comments.nix
Added <number omitted> variables.
nix-repl> :doc constant
error: value does not have documentation
Attribute version
nix-repl> :doc lib.version
Attribute `version`
… defined at
/path/to/tests/functional/repl/doc-comments.nix:30:3
… defined at /path/to/tests/functional/repl/doc-comments.nix:30:3
Immovably fixed.
Immovably fixed.
Attribute empty
nix-repl> :doc lib.attr.empty
Attribute `empty`
… defined at
/path/to/tests/functional/repl/doc-comments.nix:33:3
… defined at /path/to/tests/functional/repl/doc-comments.nix:33:3
Unchangeably constant.
Unchangeably constant.
nix-repl> :doc lib.attr.undocument
error:
… while evaluating the attribute 'attr.undocument'
at /path/to/tests/functional/repl/doc-comments.nix:33:3:
@ -32,59 +36,65 @@ error:
| ^
Did you mean undocumented?
Attribute constant
nix-repl> :doc (import ./doc-comments.nix).constant
Attribute `constant`
… defined at
/path/to/tests/functional/repl/doc-comments.nix:27:3
… defined at /path/to/tests/functional/repl/doc-comments.nix:27:3
Firmly rigid.
Firmly rigid.
Attribute version
nix-repl> :doc (import ./doc-comments.nix).lib.version
Attribute `version`
… defined at
/path/to/tests/functional/repl/doc-comments.nix:30:3
… defined at /path/to/tests/functional/repl/doc-comments.nix:30:3
Immovably fixed.
Immovably fixed.
Attribute empty
nix-repl> :doc (import ./doc-comments.nix).lib.attr.empty
Attribute `empty`
… defined at
/path/to/tests/functional/repl/doc-comments.nix:33:3
… defined at /path/to/tests/functional/repl/doc-comments.nix:33:3
Unchangeably constant.
Unchangeably constant.
Attribute undocumented
nix-repl> :doc (import ./doc-comments.nix).lib.attr.undocumented
Attribute `undocumented`
… defined at
/path/to/tests/functional/repl/doc-comments.nix:35:3
… defined at /path/to/tests/functional/repl/doc-comments.nix:35:3
No documentation found.
No documentation found.
nix-repl> :doc missing
error: undefined variable 'missing'
at «string»:1:1:
1| missing
| ^
nix-repl> :doc constanz
error: undefined variable 'constanz'
at «string»:1:1:
1| constanz
| ^
nix-repl> :doc missing.attr
error: undefined variable 'missing'
at «string»:1:1:
1| missing.attr
| ^
nix-repl> :doc lib.missing
error: attribute 'missing' missing
at «string»:1:1:
1| lib.missing
| ^
nix-repl> :doc lib.missing.attr
error: attribute 'missing' missing
at «string»:1:1:
1| lib.missing.attr
| ^
nix-repl> :doc lib.attr.undocumental
error:
… while evaluating the attribute 'attr.undocumental'
at /path/to/tests/functional/repl/doc-comments.nix:33:3:
@ -98,5 +108,3 @@ error:
1| lib.attr.undocumental
| ^
Did you mean undocumented?

View file

@ -1,11 +1,11 @@
Nix <nix version>
Type :? for help.
nix-repl> :l doc-comments.nix
Added <number omitted> variables.
Function floatedIn
… defined at
/path/to/tests/functional/repl/doc-comments.nix:16:5
This also works.
nix-repl> :doc floatedIn
Function `floatedIn`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:16:5
This also works.

View file

@ -1,29 +1,29 @@
Nix <nix version>
Type :? for help.
nix-repl> :l doc-comments.nix
Added <number omitted> variables.
Function nonStrict
… defined at
/path/to/tests/functional/repl/doc-comments.nix:37:70
nix-repl> :doc nonStrict
Function `nonStrict`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:37:70
My syntax is not strict, but I'm strict anyway.
My syntax is not strict, but I'm strict anyway.
Function strict
… defined at
/path/to/tests/functional/repl/doc-comments.nix:38:63
nix-repl> :doc strict
Function `strict`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:38:63
I don't have to be strict, but I am anyway.
I don't have to be strict, but I am anyway.
Function strictPre
… defined at
/path/to/tests/functional/repl/doc-comments.nix:40:48
nix-repl> :doc strictPre
Function `strictPre`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:40:48
Here's one way to do this
Function strictPost
… defined at
/path/to/tests/functional/repl/doc-comments.nix:41:53
Here's another way to do this
Here's one way to do this
nix-repl> :doc strictPost
Function `strictPost`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:41:53
Here's another way to do this

View file

@ -1,11 +1,11 @@
Nix <nix version>
Type :? for help.
nix-repl> :l doc-comments.nix
Added <number omitted> variables.
Function measurement
… defined at
/path/to/tests/functional/repl/doc-comments.nix:13:17
👈 precisely this wide 👉
nix-repl> :doc measurement
Function `measurement`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:13:17
👈 precisely this wide 👉

View file

@ -1,15 +1,17 @@
Nix <nix version>
Type :? for help.
nix-repl> :l doc-comments.nix
Added <number omitted> variables.
Function multiply
… defined at
/path/to/tests/functional/repl/doc-comments.nix:10:14
Perform arithmetic multiplication. It's kind of like
repeated addition, very neat.
| multiply 2 3
| => 6
nix-repl> :doc multiply
Function `multiply`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:10:14
Perform *arithmetic* multiplication. It's kind of like repeated **addition**, very neat.
```nix
multiply 2 3
=> 6
```

View file

@ -1,11 +1,11 @@
Nix <nix version>
Type :? for help.
nix-repl> :l doc-comments.nix
Added <number omitted> variables.
Function unambiguous
… defined at
/path/to/tests/functional/repl/doc-comments.nix:24:5
Very close
nix-repl> :doc unambiguous
Function `unambiguous`\
… defined at /path/to/tests/functional/repl/doc-comments.nix:24:5
Very close

View file

@ -0,0 +1,37 @@
Nix <nix version>
Type :? for help.
nix-repl> :l pretty-print-idempotent.nix
Added <number omitted> variables.
nix-repl> oneDeep
{ homepage = "https://example.com"; }
nix-repl> oneDeep
{ homepage = "https://example.com"; }
nix-repl> twoDeep
{
layerOne = { ... };
}
nix-repl> twoDeep
{
layerOne = { ... };
}
nix-repl> oneDeepList
[ "https://example.com" ]
nix-repl> oneDeepList
[ "https://example.com" ]
nix-repl> twoDeepList
[
[ ... ]
]
nix-repl> twoDeepList
[
[ ... ]
]

View file

@ -0,0 +1,9 @@
:l pretty-print-idempotent.nix
oneDeep
oneDeep
twoDeep
twoDeep
oneDeepList
oneDeepList
twoDeepList
twoDeepList

View file

@ -0,0 +1,19 @@
{
oneDeep = {
homepage = "https://" + "example.com";
};
twoDeep = {
layerOne = {
homepage = "https://" + "example.com";
};
};
oneDeepList = [
("https://" + "example.com")
];
twoDeepList = [
[
("https://" + "example.com")
]
];
}

View file

@ -10,6 +10,9 @@ nix-instantiate --restrict-eval --eval -E '1 + 2'
nix-instantiate --restrict-eval ./simple.nix -I src=.
nix-instantiate --restrict-eval ./simple.nix -I src1=simple.nix -I src2=config.nix -I src3=./simple.builder.sh
# no default NIX_PATH
(unset NIX_PATH; ! nix-instantiate --restrict-eval --find-file .)
(! nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix')
nix-instantiate --restrict-eval --eval -E 'builtins.readFile ./simple.nix' -I src=../..

View file

@ -55,4 +55,26 @@ rec {
chmod +x $out/bin/hello
'';
};
# execs env from PATH, so that we can probe the environment
# does not allow arguments, because we don't need them
env = mkDerivation {
name = "env";
outputs = [ "out" ];
buildCommand =
''
mkdir -p $out/bin
cat > $out/bin/env <<EOF
#! ${shell}
if [ $# -ne 0 ]; then
echo "env: Unexpected arguments ($#): $@" 1>&2
exit 1
fi
exec env
EOF
chmod +x $out/bin/env
'';
};
}

View file

@ -46,6 +46,7 @@ let pkgs = rec {
ASCII_PERCENT = "%";
ASCII_AT = "@";
TEST_inNixShell = if inNixShell then "true" else "false";
FOO = fooContents;
inherit stdenv;
outputs = ["dev" "out"];
} // {

View file

@ -23,6 +23,25 @@ nix shell -f shell-hello.nix hello-symlink -c hello | grep 'Hello World'
# Test that symlinks outside of the store don't work.
expect 1 nix shell -f shell-hello.nix forbidden-symlink -c hello 2>&1 | grepQuiet "is not in the Nix store"
# Test that we're not setting any more environment variables than necessary.
# For instance, we might set an environment variable temporarily to affect some
# initialization or whatnot, but this must not leak into the environment of the
# command being run.
env > $TEST_ROOT/expected-env
nix shell -f shell-hello.nix hello -c env > $TEST_ROOT/actual-env
# Remove/reset variables we expect to be different.
# - PATH is modified by nix shell
# - _ is set by bash and is expectedf to differ because it contains the original command
# - __CF_USER_TEXT_ENCODING is set by macOS and is beyond our control
sed -i \
-e 's/PATH=.*/PATH=.../' \
-e 's/_=.*/_=.../' \
-e '/^__CF_USER_TEXT_ENCODING=.*$/d' \
$TEST_ROOT/expected-env $TEST_ROOT/actual-env
sort $TEST_ROOT/expected-env > $TEST_ROOT/expected-env.sorted
sort $TEST_ROOT/actual-env > $TEST_ROOT/actual-env.sorted
diff $TEST_ROOT/expected-env.sorted $TEST_ROOT/actual-env.sorted
if isDaemonNewer "2.20.0pre20231220"; then
# Test that command line attribute ordering is reflected in the PATH
# https://github.com/NixOS/nix/issues/7905

View file

@ -0,0 +1,9 @@
#! @ENV_PROG@ nix-shell
#! nix-shell "{ script, path, ... }: assert path == ./shell.nix; script { }"
#! nix-shell --no-substitute
#! nix-shell --expr
#! nix-shell --arg script "import ./shell.nix"
#! nix-shell --arg path "./shell.nix"
#! nix-shell -A shellDrv
#! nix-shell -i bash
echo "$FOO"

View file

@ -0,0 +1,10 @@
#! @ENV_PROG@ nix-shell
#! nix-shell "{ script, path, ... }: assert path == ./shell.nix; script { fooContents = toString ./.; }"
#! nix-shell --no-substitute
#! nix-shell --expr
#! nix-shell --arg script "import ((builtins.getEnv ''TEST_ROOT'')+''/shell.nix'')"
#! nix-shell --arg path "./shell.nix"
#! nix-shell -A shellDrv
#! nix-shell -i bash
#! nix-shell --option nix-shell-shebang-arguments-relative-to-script false
echo "$FOO"

View file

@ -83,3 +83,20 @@ path="$(nix flake prefetch --json "tarball+file://$(pwd)/tree.tar.gz" | jq -r .s
[[ $(cat "$path/a/zzz") = bar ]]
[[ $(cat "$path/c/aap") = bar ]]
[[ $(cat "$path/fnord") = bar ]]
# Test a tarball that has multiple top-level directories.
rm -rf "$TEST_ROOT/tar_root"
mkdir -p "$TEST_ROOT/tar_root" "$TEST_ROOT/tar_root/foo" "$TEST_ROOT/tar_root/bar"
tar cvf "$TEST_ROOT/tar.tar" -C "$TEST_ROOT/tar_root" .
path="$(nix flake prefetch --json "tarball+file://$TEST_ROOT/tar.tar" | jq -r .storePath)"
[[ -d "$path/foo" ]]
[[ -d "$path/bar" ]]
# Test a tarball that has a single regular file.
rm -rf "$TEST_ROOT/tar_root"
mkdir -p "$TEST_ROOT/tar_root"
echo bar > "$TEST_ROOT/tar_root/foo"
chmod +x "$TEST_ROOT/tar_root/foo"
tar cvf "$TEST_ROOT/tar.tar" -C "$TEST_ROOT/tar_root" .
path="$(nix flake prefetch --refresh --json "tarball+file://$TEST_ROOT/tar.tar" | jq -r .storePath)"
[[ $(cat "$path/foo") = bar ]]

View file

@ -13,6 +13,25 @@ expect 1 false
# `expect` will fail when we get it wrong
expect 1 expect 0 false
function ret() {
return $1
}
# `expect` can call functions, not just executables
expect 0 ret 0
expect 1 ret 1
# `expect` supports negative exit codes
expect -1 ret -1
# or high positive ones, equivalent to negative ones
expect 255 ret 255
expect 255 ret -1
expect -1 ret 255
# but it doesn't confuse negative exit codes with positive ones
expect 1 expect -10 ret 10
noisyTrue () {
echo YAY! >&2
true
@ -69,6 +88,10 @@ funBang () {
expect 1 funBang
unset funBang
# callerPrefix can be used by the test framework to improve error messages
# it reports about our call site here
echo "<[$(callerPrefix)]>" | grepQuiet -F "<[test-infra.sh:$LINENO: ]>"
# `grep -v -q` is not what we want for exit codes, but `grepInverse` is
# Avoid `grep -v -q`. The following line proves the point, and if it fails,
# we'll know that `grep` had a breaking change or `-v -q` may not be portable.
@ -85,3 +108,12 @@ unset res
res=$(set -eu -o pipefail; echo foo | expect 1 grepQuietInverse foo | wc -c)
(( res == 0 ))
unset res
# `grepQuiet` does not allow newlines in its arguments, because grep quietly
# treats them as multiple queries.
{ echo foo; echo bar; } | expectStderr -101 grepQuiet $'foo\nbar' \
| grepQuiet -E 'test-infra\.sh:[0-9]+: in call to grepQuiet: newline not allowed in arguments; grep would try each line individually as if connected by an OR operator'
# We took the blue pill and woke up in a world where `grep` is moderately safe.
expectStderr -101 grep $'foo\nbar' \
| grepQuiet -E 'test-infra\.sh:[0-9]+: in call to grep: newline not allowed in arguments; grep would try each line individually as if connected by an OR operator'