1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-10 04:43:53 +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'

View file

@ -104,7 +104,15 @@ in
builder.succeed("mkdir -p -m 700 /root/.ssh")
builder.copy_from_host("key.pub", "/root/.ssh/authorized_keys")
builder.wait_for_unit("sshd")
client.succeed(f"ssh -o StrictHostKeyChecking=no {builder.name} 'echo hello world'")
# Make sure the builder can handle our login correctly
builder.wait_for_unit("multi-user.target")
# Make sure there's no funny business on the client either
# (should not be necessary, but we have reason to be careful)
client.wait_for_unit("multi-user.target")
client.succeed(f"""
ssh -o StrictHostKeyChecking=no {builder.name} \
'echo hello world on $(hostname)' >&2
""")
# Perform a build and check that it was performed on the builder.
out = client.succeed(

View file

@ -27,6 +27,8 @@ deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
rapidcheck = dependency('rapidcheck')
deps_public += rapidcheck

View file

@ -66,12 +66,8 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold";
};
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
meta = {

View file

@ -34,6 +34,9 @@ int main (int argc, char **argv) {
setEnv("_NIX_TEST_NO_SANDBOX", "1");
#endif
// For pipe operator tests in trivial.cc
experimentalFeatureSettings.set("experimental-features", "pipe-operators");
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View file

@ -25,6 +25,8 @@ deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
rapidcheck = dependency('rapidcheck')

View file

@ -1,4 +1,5 @@
{ lib
, buildPackages
, stdenv
, mkMesonDerivation
, releaseTools
@ -41,8 +42,6 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
nativeBuildInputs = [
meson
ninja
@ -72,28 +71,28 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold";
};
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
passthru = {
tests = {
run = runCommand "${finalAttrs.pname}-run" {
} ''
PATH="${lib.makeBinPath [ finalAttrs.finalPackage ]}:$PATH"
meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages;
} (lib.optionalString stdenv.hostPlatform.isWindows ''
export HOME="$PWD/home-dir"
mkdir -p "$HOME"
'' + ''
export _NIX_TEST_UNIT_DATA=${resolvePath ./data}
nix-expr-tests
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
touch $out
'';
'');
};
};
meta = {
platforms = lib.platforms.unix ++ lib.platforms.windows;
mainProgram = finalAttrs.pname + stdenv.hostPlatform.extensions.executable;
};
})

View file

@ -182,6 +182,60 @@ namespace nix {
ASSERT_THAT(v, IsIntEq(15));
}
TEST_F(TrivialExpressionTest, forwardPipe) {
auto v = eval("1 |> builtins.add 2 |> builtins.mul 3");
ASSERT_THAT(v, IsIntEq(9));
}
TEST_F(TrivialExpressionTest, backwardPipe) {
auto v = eval("builtins.add 1 <| builtins.mul 2 <| 3");
ASSERT_THAT(v, IsIntEq(7));
}
TEST_F(TrivialExpressionTest, forwardPipeEvaluationOrder) {
auto v = eval("1 |> null |> (x: 2)");
ASSERT_THAT(v, IsIntEq(2));
}
TEST_F(TrivialExpressionTest, backwardPipeEvaluationOrder) {
auto v = eval("(x: 1) <| null <| 2");
ASSERT_THAT(v, IsIntEq(1));
}
TEST_F(TrivialExpressionTest, differentPipeOperatorsDoNotAssociate) {
ASSERT_THROW(eval("(x: 1) <| 2 |> (x: 3)"), ParseError);
}
TEST_F(TrivialExpressionTest, differentPipeOperatorsParensLeft) {
auto v = eval("((x: 1) <| 2) |> (x: 3)");
ASSERT_THAT(v, IsIntEq(3));
}
TEST_F(TrivialExpressionTest, differentPipeOperatorsParensRight) {
auto v = eval("(x: 1) <| (2 |> (x: 3))");
ASSERT_THAT(v, IsIntEq(1));
}
TEST_F(TrivialExpressionTest, forwardPipeLowestPrecedence) {
auto v = eval("false -> true |> (x: !x)");
ASSERT_THAT(v, IsFalse());
}
TEST_F(TrivialExpressionTest, backwardPipeLowestPrecedence) {
auto v = eval("(x: !x) <| false -> true");
ASSERT_THAT(v, IsFalse());
}
TEST_F(TrivialExpressionTest, forwardPipeStrongerThanElse) {
auto v = eval("if true then 1 else 2 |> 3");
ASSERT_THAT(v, IsIntEq(1));
}
TEST_F(TrivialExpressionTest, backwardPipeStrongerThanElse) {
auto v = eval("if true then 1 else 2 <| 3");
ASSERT_THAT(v, IsIntEq(1));
}
TEST_F(TrivialExpressionTest, bindOr) {
auto v = eval("{ or = 1; }");
ASSERT_THAT(v, IsAttrsOfSize(1));

View file

@ -77,7 +77,7 @@ TEST_F(GitUtilsTest, sink_basic)
// sink->createHardlink("foo-1.1/links/foo-2", CanonPath("foo-1.1/hello"));
auto result = sink->sync();
auto result = repo->dereferenceSingletonDirectory(sink->sync());
auto accessor = repo->getAccessor(result, false);
auto entries = accessor->readDirectory(CanonPath::root);
ASSERT_EQ(entries.size(), 5);
@ -103,7 +103,7 @@ TEST_F(GitUtilsTest, sink_hardlink)
sink->createHardlink(CanonPath("foo-1.1/link"), CanonPath("hello"));
FAIL() << "Expected an exception";
} catch (const nix::Error & e) {
ASSERT_THAT(e.msg(), testing::HasSubstr("invalid hard link target"));
ASSERT_THAT(e.msg(), testing::HasSubstr("cannot find hard link target"));
ASSERT_THAT(e.msg(), testing::HasSubstr("/hello"));
ASSERT_THAT(e.msg(), testing::HasSubstr("foo-1.1/link"));
}

View file

@ -24,6 +24,8 @@ deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
rapidcheck = dependency('rapidcheck')

View file

@ -1,4 +1,5 @@
{ lib
, buildPackages
, stdenv
, mkMesonDerivation
, releaseTools
@ -40,8 +41,6 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
nativeBuildInputs = [
meson
ninja
@ -70,28 +69,28 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold";
};
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
passthru = {
tests = {
run = runCommand "${finalAttrs.pname}-run" {
} ''
PATH="${lib.makeBinPath [ finalAttrs.finalPackage ]}:$PATH"
meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages;
} (lib.optionalString stdenv.hostPlatform.isWindows ''
export HOME="$PWD/home-dir"
mkdir -p "$HOME"
'' + ''
export _NIX_TEST_UNIT_DATA=${resolvePath ./data}
nix-fetchers-tests
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
touch $out
'';
'');
};
};
meta = {
platforms = lib.platforms.unix ++ lib.platforms.windows;
mainProgram = finalAttrs.pname + stdenv.hostPlatform.extensions.executable;
};
})

View file

@ -24,6 +24,8 @@ deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
rapidcheck = dependency('rapidcheck')

View file

@ -1,4 +1,5 @@
{ lib
, buildPackages
, stdenv
, mkMesonDerivation
, releaseTools
@ -40,8 +41,6 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
nativeBuildInputs = [
meson
ninja
@ -70,28 +69,28 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold";
};
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
passthru = {
tests = {
run = runCommand "${finalAttrs.pname}-run" {
} ''
PATH="${lib.makeBinPath [ finalAttrs.finalPackage ]}:$PATH"
meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages;
} (lib.optionalString stdenv.hostPlatform.isWindows ''
export HOME="$PWD/home-dir"
mkdir -p "$HOME"
'' + ''
export _NIX_TEST_UNIT_DATA=${resolvePath ./data}
nix-flake-tests
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
touch $out
'';
'');
};
};
meta = {
platforms = lib.platforms.unix ++ lib.platforms.windows;
mainProgram = finalAttrs.pname + stdenv.hostPlatform.extensions.executable;
};
})

View file

@ -25,6 +25,8 @@ deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
rapidcheck = dependency('rapidcheck')
deps_public += rapidcheck

View file

@ -66,12 +66,8 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold";
};
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
meta = {

View file

@ -0,0 +1,21 @@
#include <gtest/gtest.h>
#include "http-binary-cache-store.hh"
namespace nix {
TEST(HttpBinaryCacheStore, constructConfig)
{
HttpBinaryCacheStoreConfig config{"http", "foo.bar.baz", {}};
EXPECT_EQ(config.cacheUri, "http://foo.bar.baz");
}
TEST(HttpBinaryCacheStore, constructConfigNoTrailingSlash)
{
HttpBinaryCacheStoreConfig config{"https", "foo.bar.baz/a/b/", {}};
EXPECT_EQ(config.cacheUri, "https://foo.bar.baz/a/b");
}
} // namespace nix

View file

@ -0,0 +1,14 @@
#include <gtest/gtest.h>
#include "local-binary-cache-store.hh"
namespace nix {
TEST(LocalBinaryCacheStore, constructConfig)
{
LocalBinaryCacheStoreConfig config{"local", "/foo/bar/baz", {}};
EXPECT_EQ(config.binaryCacheDir, "/foo/bar/baz");
}
} // namespace nix

View file

@ -0,0 +1,34 @@
// FIXME: Odd failures for templates that are causing the PR to break
// for now with discussion with @Ericson2314 to comment out.
#if 0
# include <gtest/gtest.h>
# include "local-overlay-store.hh"
namespace nix {
TEST(LocalOverlayStore, constructConfig_rootQueryParam)
{
LocalOverlayStoreConfig config{
"local-overlay",
"",
{
{
"root",
"/foo/bar",
},
},
};
EXPECT_EQ(config.rootDir.get(), std::optional{"/foo/bar"});
}
TEST(LocalOverlayStore, constructConfig_rootPath)
{
LocalOverlayStoreConfig config{"local-overlay", "/foo/bar", {}};
EXPECT_EQ(config.rootDir.get(), std::optional{"/foo/bar"});
}
} // namespace nix
#endif

View file

@ -0,0 +1,40 @@
// FIXME: Odd failures for templates that are causing the PR to break
// for now with discussion with @Ericson2314 to comment out.
#if 0
# include <gtest/gtest.h>
# include "local-store.hh"
// Needed for template specialisations. This is not good! When we
// overhaul how store configs work, this should be fixed.
# include "args.hh"
# include "config-impl.hh"
# include "abstract-setting-to-json.hh"
namespace nix {
TEST(LocalStore, constructConfig_rootQueryParam)
{
LocalStoreConfig config{
"local",
"",
{
{
"root",
"/foo/bar",
},
},
};
EXPECT_EQ(config.rootDir.get(), std::optional{"/foo/bar"});
}
TEST(LocalStore, constructConfig_rootPath)
{
LocalStoreConfig config{"local", "/foo/bar", {}};
EXPECT_EQ(config.rootDir.get(), std::optional{"/foo/bar"});
}
} // namespace nix
#endif

View file

@ -25,6 +25,8 @@ deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
sqlite = dependency('sqlite3', 'sqlite', version : '>=3.6.19')
@ -58,7 +60,11 @@ sources = files(
'derivation.cc',
'derived-path.cc',
'downstream-placeholder.cc',
'http-binary-cache-store.cc',
'legacy-ssh-store.cc',
'local-binary-cache-store.cc',
'local-overlay-store.cc',
'local-store.cc',
'machines.cc',
'nar-info-disk-cache.cc',
'nar-info.cc',
@ -67,9 +73,11 @@ sources = files(
'path-info.cc',
'path.cc',
'references.cc',
's3-binary-cache-store.cc',
'serve-protocol.cc',
'ssh-store.cc',
'store-reference.cc',
'uds-remote-store.cc',
'worker-protocol.cc',
)

View file

@ -1,4 +1,5 @@
{ lib
, buildPackages
, stdenv
, mkMesonDerivation
, releaseTools
@ -42,8 +43,6 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
nativeBuildInputs = [
meson
ninja
@ -74,12 +73,8 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold";
};
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
passthru = {
@ -94,17 +89,22 @@ mkMesonDerivation (finalAttrs: {
../../functional/derivation
];
};
in runCommand "${finalAttrs.pname}-run" {} ''
PATH="${lib.makeBinPath [ finalAttrs.finalPackage ]}:$PATH"
in runCommand "${finalAttrs.pname}-run" {
meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages;
} (lib.optionalString stdenv.hostPlatform.isWindows ''
export HOME="$PWD/home-dir"
mkdir -p "$HOME"
'' + ''
export _NIX_TEST_UNIT_DATA=${data + "/unit/libstore/data"}
nix-store-tests
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
touch $out
'';
'');
};
};
meta = {
platforms = lib.platforms.unix ++ lib.platforms.windows;
mainProgram = finalAttrs.pname + stdenv.hostPlatform.extensions.executable;
};
})

View file

@ -0,0 +1,18 @@
#if ENABLE_S3
# include <gtest/gtest.h>
# include "s3-binary-cache-store.hh"
namespace nix {
TEST(S3BinaryCacheStore, constructConfig)
{
S3BinaryCacheStoreConfig config{"s3", "foobar", {}};
EXPECT_EQ(config.bucketName, "foobar");
}
} // namespace nix
#endif

View file

@ -1,6 +1,9 @@
#include <gtest/gtest.h>
// FIXME: Odd failures for templates that are causing the PR to break
// for now with discussion with @Ericson2314 to comment out.
#if 0
# include <gtest/gtest.h>
#include "ssh-store.hh"
# include "ssh-store.hh"
namespace nix {
@ -15,7 +18,9 @@ TEST(SSHStore, constructConfig)
// TODO #11106, no more split on space
"foo bar",
},
}};
},
};
EXPECT_EQ(
config.remoteProgram.get(),
(Strings{
@ -23,4 +28,28 @@ TEST(SSHStore, constructConfig)
"bar",
}));
}
TEST(MountedSSHStore, constructConfig)
{
MountedSSHStoreConfig config{
"mounted-ssh",
"localhost",
StoreConfig::Params{
{
"remote-program",
// TODO #11106, no more split on space
"foo bar",
},
},
};
EXPECT_EQ(
config.remoteProgram.get(),
(Strings{
"foo",
"bar",
}));
}
}
#endif

View file

@ -0,0 +1,23 @@
// FIXME: Odd failures for templates that are causing the PR to break
// for now with discussion with @Ericson2314 to comment out.
#if 0
# include <gtest/gtest.h>
# include "uds-remote-store.hh"
namespace nix {
TEST(UDSRemoteStore, constructConfig)
{
UDSRemoteStoreConfig config{"unix", "/tmp/socket", {}};
EXPECT_EQ(config.path, "/tmp/socket");
}
TEST(UDSRemoteStore, constructConfigWrongScheme)
{
EXPECT_THROW(UDSRemoteStoreConfig("http", "/tmp/socket", {}), UsageError);
}
} // namespace nix
#endif

View file

@ -658,15 +658,15 @@ TEST_F(WorkerProtoTest, handshake_log)
FdSink out { toServer.writeSide.get() };
FdSource in0 { toClient.readSide.get() };
TeeSource in { in0, toClientLog };
clientResult = WorkerProto::BasicClientConnection::handshake(
out, in, defaultVersion);
clientResult = std::get<0>(WorkerProto::BasicClientConnection::handshake(
out, in, defaultVersion, {}));
});
{
FdSink out { toClient.writeSide.get() };
FdSource in { toServer.readSide.get() };
WorkerProto::BasicServerConnection::handshake(
out, in, defaultVersion);
out, in, defaultVersion, {});
};
thread.join();
@ -675,6 +675,33 @@ TEST_F(WorkerProtoTest, handshake_log)
});
}
TEST_F(WorkerProtoTest, handshake_features)
{
Pipe toClient, toServer;
toClient.create();
toServer.create();
std::tuple<WorkerProto::Version, std::set<WorkerProto::Feature>> clientResult;
auto clientThread = std::thread([&]() {
FdSink out { toServer.writeSide.get() };
FdSource in { toClient.readSide.get() };
clientResult = WorkerProto::BasicClientConnection::handshake(
out, in, 123, {"bar", "aap", "mies", "xyzzy"});
});
FdSink out { toClient.writeSide.get() };
FdSource in { toServer.readSide.get() };
auto daemonResult = WorkerProto::BasicServerConnection::handshake(
out, in, 456, {"foo", "bar", "xyzzy"});
clientThread.join();
EXPECT_EQ(clientResult, daemonResult);
EXPECT_EQ(std::get<0>(clientResult), 123);
EXPECT_EQ(std::get<1>(clientResult), std::set<WorkerProto::Feature>({"bar", "xyzzy"}));
}
/// Has to be a `BufferedSink` for handshake.
struct NullBufferedSink : BufferedSink {
void writeUnbuffered(std::string_view data) override { }
@ -686,8 +713,8 @@ TEST_F(WorkerProtoTest, handshake_client_replay)
NullBufferedSink nullSink;
StringSource in { toClientLog };
auto clientResult = WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion);
auto clientResult = std::get<0>(WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion, {}));
EXPECT_EQ(clientResult, defaultVersion);
});
@ -705,13 +732,13 @@ TEST_F(WorkerProtoTest, handshake_client_truncated_replay_throws)
if (len < 8) {
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion),
nullSink, in, defaultVersion, {}),
EndOfFile);
} else {
// Not sure why cannot keep on checking for `EndOfFile`.
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion),
nullSink, in, defaultVersion, {}),
Error);
}
}
@ -734,17 +761,17 @@ TEST_F(WorkerProtoTest, handshake_client_corrupted_throws)
// magic bytes don't match
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion),
nullSink, in, defaultVersion, {}),
Error);
} else if (idx < 8 || idx >= 12) {
// Number out of bounds
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion),
nullSink, in, defaultVersion, {}),
SerialisationError);
} else {
auto ver = WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion);
auto ver = std::get<0>(WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion, {}));
// `std::min` of this and the other version saves us
EXPECT_EQ(ver, defaultVersion);
}

View file

@ -23,6 +23,8 @@ deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
rapidcheck = dependency('rapidcheck')
deps_public += rapidcheck

View file

@ -64,12 +64,8 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold";
};
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
meta = {

View file

@ -2,9 +2,10 @@
namespace nix::testing {
void observe_string_cb(const char * start, unsigned int n, std::string * user_data)
void observe_string_cb(const char * start, unsigned int n, void * user_data)
{
*user_data = std::string(start);
auto user_data_casted = reinterpret_cast<std::string *>(user_data);
*user_data_casted = std::string(start);
}
}

View file

@ -3,14 +3,13 @@
namespace nix::testing {
void observe_string_cb(const char * start, unsigned int n, std::string * user_data);
void observe_string_cb(const char * start, unsigned int n, void * user_data);
inline void * observe_string_cb_data(std::string & out)
{
return (void *) &out;
};
#define OBSERVE_STRING(str) \
(nix_get_string_callback) nix::testing::observe_string_cb, nix::testing::observe_string_cb_data(str)
#define OBSERVE_STRING(str) nix::testing::observe_string_cb, nix::testing::observe_string_cb_data(str)
}

View file

@ -25,6 +25,8 @@ deps_public_maybe_subproject = [
]
subdir('build-utils-meson/subprojects')
subdir('build-utils-meson/threads')
subdir('build-utils-meson/export-all-symbols')
rapidcheck = dependency('rapidcheck')

View file

@ -1,4 +1,5 @@
{ lib
, buildPackages
, stdenv
, mkMesonDerivation
, releaseTools
@ -40,8 +41,6 @@ mkMesonDerivation (finalAttrs: {
(fileset.fileFilter (file: file.hasExt "hh") ./.)
];
outputs = [ "out" "dev" ];
nativeBuildInputs = [
meson
ninja
@ -71,28 +70,28 @@ mkMesonDerivation (finalAttrs: {
LDFLAGS = "-fuse-ld=gold";
};
enableParallelBuilding = true;
separateDebugInfo = !stdenv.hostPlatform.isStatic;
strictDeps = true;
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
passthru = {
tests = {
run = runCommand "${finalAttrs.pname}-run" {
} ''
PATH="${lib.makeBinPath [ finalAttrs.finalPackage ]}:$PATH"
meta.broken = !stdenv.hostPlatform.emulatorAvailable buildPackages;
} (lib.optionalString stdenv.hostPlatform.isWindows ''
export HOME="$PWD/home-dir"
mkdir -p "$HOME"
'' + ''
export _NIX_TEST_UNIT_DATA=${./data}
nix-util-tests
${stdenv.hostPlatform.emulator buildPackages} ${lib.getExe finalAttrs.finalPackage}
touch $out
'';
'');
};
};
meta = {
platforms = lib.platforms.unix ++ lib.platforms.windows;
mainProgram = finalAttrs.pname + stdenv.hostPlatform.extensions.executable;
};
})

View file

@ -17,6 +17,10 @@
# define FS_ROOT FS_SEP
#endif
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
namespace nix {
/* ----------- tests for util.hh ------------------------------------------------*/