1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-23 02:39:37 +01:00

Harden tests' bash

Use `set -u` and `set -o pipefail` to catch accidental mistakes and
failures more strongly.

 - `set -u` catches the use of undefined variables
 - `set -o pipefail` catches failures (like `set -e`) earlier in the
   pipeline.

This makes the tests a bit more robust. It is nice to read code not
worrying about these spurious success paths (via uncaught) errors
undermining the tests. Indeed, I caught some bugs doing this.

There are a few tests where we run a command that should fail, and then
search its output to make sure the failure message is one that we
expect. Before, since the `grep` was the last command in the pipeline
the exit code of those failing programs was silently ignored. Now with
`set -o pipefail` it won't be, and we have to do something so the
expected failure doesn't accidentally fail the test.

To do that we use `expect` and a new `expectStderr` to check for the
exact failing exit code. See the comments on each for why.

`grep -q` is replaced with `grepQuiet`, see the comments on that
function for why.

`grep -v` when we just want the exit code is replaced with `grepInverse,
see the comments on that function for why.

`grep -q -v` together is, surprise surprise, replaced with
`grepQuietInverse`, which is both combined.

(cherry picked from commit c11836126b)
This commit is contained in:
John Ericson 2021-12-09 15:26:46 +00:00
parent 5e13c907b4
commit 67ab776e15
22 changed files with 233 additions and 93 deletions

View file

@ -1,6 +1,6 @@
#!/bin/sh
set -u
set -eu -o pipefail
red=""
green=""
@ -15,8 +15,9 @@ if [ -t 1 ]; then
normal=""
fi
(cd $(dirname $1) && env ${TESTS_ENVIRONMENT} init.sh 2>/dev/null > /dev/null)
log="$(cd $(dirname $1) && env ${TESTS_ENVIRONMENT} $(basename $1) 2>&1)"
status=$?
log="$(cd $(dirname $1) && env ${TESTS_ENVIRONMENT} $(basename $1) 2>&1)" && status=0 || status=$?
if [ $status -eq 0 ]; then
echo "$post_run_msg [${green}PASS$normal]"
elif [ $status -eq 99 ]; then

View file

@ -62,8 +62,8 @@ mv $nar $nar.good
mkdir -p $TEST_ROOT/empty
nix-store --dump $TEST_ROOT/empty | xz > $nar
nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log
grep -q "hash mismatch" $TEST_ROOT/log
expect 1 nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log
grepQuiet "hash mismatch" $TEST_ROOT/log
mv $nar.good $nar
@ -110,7 +110,7 @@ clearStore
rm $(grep -l "StorePath:.*dependencies-input-2" $cacheDir/*.narinfo)
nix-build --substituters "file://$cacheDir" --no-require-sigs dependencies.nix -o $TEST_ROOT/result 2>&1 | tee $TEST_ROOT/log
grep -q "copying path" $TEST_ROOT/log
grepQuiet "copying path" $TEST_ROOT/log
if [ -n "$HAVE_SODIUM" ]; then

View file

@ -20,7 +20,7 @@ nix build -f dependencies.nix --dry-run 2>&1 | grep "will be built"
# TODO: XXX: FIXME: #1793
# Disable this part of the test until the problem is resolved:
if [ -n "$ISSUE_1795_IS_FIXED" ]; then
if [ -n "${ISSUE_1795_IS_FIXED-}" ]; then
clearStore
clearCache

View file

@ -8,14 +8,14 @@ dep=$(nix-build -o $RESULT check-refs.nix -A dep)
# test1 references dep, not itself.
test1=$(nix-build -o $RESULT check-refs.nix -A test1)
(! nix-store -q --references $test1 | grep -q $test1)
nix-store -q --references $test1 | grep -q $dep
nix-store -q --references $test1 | grepQuietInverse $test1
nix-store -q --references $test1 | grepQuiet $dep
# test2 references src, not itself nor dep.
test2=$(nix-build -o $RESULT check-refs.nix -A test2)
(! nix-store -q --references $test2 | grep -q $test2)
(! nix-store -q --references $test2 | grep -q $dep)
nix-store -q --references $test2 | grep -q aux-ref
nix-store -q --references $test2 | grepQuietInverse $test2
nix-store -q --references $test2 | grepQuietInverse $dep
nix-store -q --references $test2 | grepQuiet aux-ref
# test3 should fail (unallowed ref).
(! nix-build -o $RESULT check-refs.nix -A test3)

View file

@ -8,8 +8,8 @@ nix-build -o $RESULT check-reqs.nix -A test1
(! nix-build -o $RESULT check-reqs.nix -A test2)
(! nix-build -o $RESULT check-reqs.nix -A test3)
(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grep -q 'check-reqs-dep1'
(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grep -q 'check-reqs-dep2'
(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grepQuiet 'check-reqs-dep1'
(! nix-build -o $RESULT check-reqs.nix -A test4) 2>&1 | grepQuiet 'check-reqs-dep2'
(! nix-build -o $RESULT check-reqs.nix -A test5)
(! nix-build -o $RESULT check-reqs.nix -A test6)

View file

@ -1,6 +1,6 @@
set -e
set -eu -o pipefail
if [[ -z "$COMMON_SH_SOURCED" ]]; then
if [[ -z "${COMMON_SH_SOURCED-}" ]]; then
COMMON_SH_SOURCED=1
@ -24,7 +24,7 @@ if [[ -n $NIX_STORE ]]; then
fi
export _NIX_IN_TEST=$TEST_ROOT/shared
export _NIX_TEST_NO_LSOF=1
export NIX_REMOTE=$NIX_REMOTE_
export NIX_REMOTE=${NIX_REMOTE_-}
unset NIX_PATH
export TEST_HOME=$TEST_ROOT/test-home
export HOME=$TEST_HOME
@ -91,12 +91,14 @@ startDaemon() {
# nix-daemon should have an option to fork into the background.
rm -f $NIX_DAEMON_SOCKET_PATH
PATH=$DAEMON_PATH nix-daemon &
pidDaemon=$!
for ((i = 0; i < 30; i++)); do
if [[ -S $NIX_DAEMON_SOCKET_PATH ]]; then break; fi
sleep 1
done
pidDaemon=$!
trap "killDaemon" EXIT
# Save for if daemon is killed
NIX_REMOTE_OLD=$NIX_REMOTE
export NIX_REMOTE=daemon
}
@ -108,6 +110,8 @@ killDaemon() {
done
kill -9 $pidDaemon || true
wait $pidDaemon || true
# Restore old nix remote
NIX_REMOTE=$NIX_REMOTE_OLD
trap "" EXIT
}
@ -115,7 +119,6 @@ restartDaemon() {
[[ -z "${pidDaemon:-}" ]] && return 0
killDaemon
unset NIX_REMOTE
startDaemon
}
@ -146,7 +149,7 @@ requireDaemonNewerThan () {
}
canUseSandbox() {
if [[ ! $_canUseSandbox ]]; then
if [[ ! ${_canUseSandbox-} ]]; then
echo "Sandboxing not supported, skipping this test..."
return 1
fi
@ -159,15 +162,43 @@ fail() {
exit 1
}
# Run a command failing if it didn't exit with the expected exit code.
#
# Has two advantages over the built-in `!`:
#
# 1. `!` conflates all non-0 codes. `expect` allows testing for an exact
# code.
#
# 2. `!` unexpectedly negates `set -e`, and cannot be used on individual
# pipeline stages with `set -o pipefail`. It only works on the entire
# pipeline, which is useless if we want, say, `nix ...` invocation to
# *fail*, but a grep on the error message it outputs to *succeed*.
expect() {
local expected res
expected="$1"
shift
set +e
"$@"
res="$?"
"$@" && res=0 || res="$?"
set -e
[[ $res -eq $expected ]]
if [[ $res -ne $expected ]]; then
echo "Expected '$expected' but got '$res' while running '${*@Q}'" >&2
return 1
fi
return 0
}
# Better than just doing `expect ... >&2` because the "Expected..."
# message below will *not* be redirected.
expectStderr() {
local expected res
expected="$1"
shift
"$@" 2>&1 && res=0 || res="$?"
if [[ $res -ne $expected ]]; then
echo "Expected '$expected' but got '$res' while running '${*@Q}'" >&2
return 1
fi
return 0
}
needLocalStore() {
@ -179,7 +210,36 @@ needLocalStore() {
# Just to make it easy to find which tests should be fixed
buggyNeedLocalStore () {
needLocalStore
needLocalStore "$1"
}
# `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*.
grepInverse() {
! grep "$@"
}
# A shorthand, `> /dev/null` is a bit noisy.
#
# `grep -q` would seem to do this, no function necessary, but it is a
# bad fit with pipes and `set -o pipefail`: `-q` will exit after the
# first match, and then subsequent writes will result in broken pipes.
#
# Note that reproducing the above is a bit tricky as it depends on
# non-deterministic properties such as the timing between the match and
# 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.
grepQuiet() {
grep "$@" > /dev/null
}
# The previous two, combined
grepQuietInverse() {
! grep "$@" > /dev/null
}
set -x

View file

@ -22,7 +22,7 @@ nix-store -q --graph "$outPath" > $TEST_ROOT/graph
if test -n "$dot"; then
# Does it parse?
$dot < $TEST_ROOT/graph
fi
fi
nix-store -q --tree "$outPath" | grep '+---.*dependencies-input-2'
@ -36,10 +36,10 @@ deps=$(nix-store -quR "$drvPath")
echo "output closure contains $deps"
# The output path should be in the closure.
echo "$deps" | grep -q "$outPath"
echo "$deps" | grepQuiet "$outPath"
# Input-1 is not retained.
if echo "$deps" | grep -q "dependencies-input-1"; then exit 1; fi
if echo "$deps" | grepQuiet "dependencies-input-1"; then exit 1; fi
# Input-2 is retained.
input2OutPath=$(echo "$deps" | grep "dependencies-input-2")
@ -49,4 +49,4 @@ nix-store -q --referrers-closure "$input2OutPath" | grep "$outPath"
# Check that the derivers are set properly.
test $(nix-store -q --deriver "$outPath") = "$drvPath"
nix-store -q --deriver "$input2OutPath" | grep -q -- "-input-2.drv"
nix-store -q --deriver "$input2OutPath" | grepQuiet -- "-input-2.drv"

View file

@ -4,7 +4,7 @@ clearStore
clearProfiles
checkRef() {
nix-store -q --references $TEST_ROOT/result | grep -q "$1"'$' || fail "missing reference $1"
nix-store -q --references $TEST_ROOT/result | grepQuiet "$1"'$' || fail "missing reference $1"
}
# Test the export of the runtime dependency graph.

View file

@ -60,7 +60,7 @@ hash=$(nix-hash --flat --type sha256 $nar)
outPath=$(nix-build '<nix/fetchurl.nix>' --argstr url file://$nar --argstr sha256 $hash \
--arg unpack true --argstr name xyzzy --no-out-link)
echo $outPath | grep -q 'xyzzy'
echo $outPath | grepQuiet 'xyzzy'
test -x $outPath/fetchurl.sh
test -L $outPath/symlink

View file

@ -10,17 +10,15 @@ expect_trace() {
--trace-function-calls \
--expr "$expr" 2>&1 \
| grep "function-trace" \
| sed -e 's/ [0-9]*$//'
);
| sed -e 's/ [0-9]*$//' \
|| true
)
echo -n "Tracing expression '$expr'"
set +e
msg=$(diff -swB \
<(echo "$expect") \
<(echo "$actual")
);
result=$?
set -e
) && result=0 || result=$?
if [ $result -eq 0 ]; then
echo " ok."
else
@ -81,5 +79,3 @@ function-trace exited undefined position at
function-trace entered (string):1:1 at
function-trace exited (string):1:1 at
"
set -e

View file

@ -2,7 +2,7 @@ source common.sh
try () {
printf "%s" "$2" > $TEST_ROOT/vector
hash=$(nix hash-file --base16 $EXTRA --type "$1" $TEST_ROOT/vector)
hash=$(nix hash-file --base16 ${EXTRA-} --type "$1" $TEST_ROOT/vector)
if test "$hash" != "$3"; then
echo "hash $1, expected $3, got $hash"
exit 1

View file

@ -2,9 +2,9 @@ source common.sh
export TEST_VAR=foo # for eval-okay-getenv.nix
nix-instantiate --eval -E 'builtins.trace "Hello" 123' 2>&1 | grep -q Hello
(! nix-instantiate --show-trace --eval -E 'builtins.addErrorContext "Hello" 123' 2>&1 | grep -q Hello)
nix-instantiate --show-trace --eval -E 'builtins.addErrorContext "Hello" (throw "Foo")' 2>&1 | grep -q Hello
nix-instantiate --eval -E 'builtins.trace "Hello" 123' 2>&1 | grepQuiet Hello
nix-instantiate --show-trace --eval -E 'builtins.addErrorContext "Hello" 123' 2>&1 | grepQuietInverse Hello
expectStderr 1 nix-instantiate --show-trace --eval -E 'builtins.addErrorContext "Hello" (throw "Foo")' 2>&1 | grepQuiet Hello
set +x

View file

@ -31,7 +31,8 @@ nix_tests = \
search.sh \
nix-copy-ssh.sh \
post-hook.sh \
function-trace.sh
function-trace.sh \
test-infra.sh \
# parallel.sh
install-tests += $(foreach x, $(nix_tests), tests/$(x))

View file

@ -3,17 +3,17 @@ source common.sh
# Tests miscellaneous commands.
# Do all commands have help?
#nix-env --help | grep -q install
#nix-store --help | grep -q realise
#nix-instantiate --help | grep -q eval
#nix-hash --help | grep -q base32
#nix-env --help | grepQuiet install
#nix-store --help | grepQuiet realise
#nix-instantiate --help | grepQuiet eval
#nix-hash --help | grepQuiet base32
# Can we ask for the version number?
nix-env --version | grep "$version"
# Usage errors.
nix-env --foo 2>&1 | grep "no operation"
nix-env -q --foo 2>&1 | grep "unknown flag"
expect 1 nix-env --foo 2>&1 | grep "no operation"
expect 1 nix-env -q --foo 2>&1 | grep "unknown flag"
# Eval Errors.
nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 | grep "infinite recursion encountered, at .*(string).*:1:15$"
expect 1 nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 | grep "infinite recursion encountered, at .*(string).*:1:15$"

View file

@ -13,8 +13,8 @@ echo "evaluating c..."
# outputs.
drvPath=$(nix-instantiate multiple-outputs.nix -A c)
#[ "$drvPath" = "$drvPath2" ]
grep -q 'multiple-outputs-a.drv",\["first","second"\]' $drvPath
grep -q 'multiple-outputs-b.drv",\["out"\]' $drvPath
grepQuiet 'multiple-outputs-a.drv",\["first","second"\]' $drvPath
grepQuiet 'multiple-outputs-b.drv",\["out"\]' $drvPath
# While we're at it, test the unsafeDiscardOutputDependency primop.
outPath=$(nix-build multiple-outputs.nix -A d --no-out-link)

View file

@ -34,8 +34,8 @@ diff -u baz.cat-nar $storePath/foo/baz
[[ $(nix ls-store --json -R $storePath/foo/bar) = '{"type":"regular","size":0}' ]]
# Test missing files.
nix ls-store --json -R $storePath/xyzzy 2>&1 | grep 'does not exist in NAR'
nix ls-store $storePath/xyzzy 2>&1 | grep 'does not exist'
expect 1 nix ls-store --json -R $storePath/xyzzy 2>&1 | grep 'does not exist in NAR'
expect 1 nix ls-store $storePath/xyzzy 2>&1 | grep 'does not exist'
# Test failure to dump.
if nix-store --dump $storePath >/dev/full ; then

View file

@ -6,7 +6,7 @@ rm -f $TEST_HOME/.nix-channels $TEST_HOME/.nix-profile
# Test add/list/remove.
nix-channel --add http://foo/bar xyzzy
nix-channel --list | grep -q http://foo/bar
nix-channel --list | grepQuiet http://foo/bar
nix-channel --remove xyzzy
[ -e $TEST_HOME/.nix-channels ]
@ -31,8 +31,8 @@ nix-env -qa \* --meta --xml --out-path > $TEST_ROOT/meta.xml
if [ "$xmllint" != false ]; then
$xmllint --noout $TEST_ROOT/meta.xml || fail "malformed XML"
fi
grep -q 'meta.*description.*Random test package' $TEST_ROOT/meta.xml
grep -q 'item.*attrPath="foo".*name="dependencies"' $TEST_ROOT/meta.xml
grepQuiet 'meta.*description.*Random test package' $TEST_ROOT/meta.xml
grepQuiet 'item.*attrPath="foo".*name="dependencies"' $TEST_ROOT/meta.xml
# Do an install.
nix-env -i dependencies
@ -50,8 +50,8 @@ nix-env -qa \* --meta --xml --out-path > $TEST_ROOT/meta.xml
if [ "$xmllint" != false ]; then
$xmllint --noout $TEST_ROOT/meta.xml || fail "malformed XML"
fi
grep -q 'meta.*description.*Random test package' $TEST_ROOT/meta.xml
grep -q 'item.*attrPath="foo".*name="dependencies"' $TEST_ROOT/meta.xml
grepQuiet 'meta.*description.*Random test package' $TEST_ROOT/meta.xml
grepQuiet 'item.*attrPath="foo".*name="dependencies"' $TEST_ROOT/meta.xml
# Do an install.
nix-env -i dependencies

View file

@ -38,6 +38,6 @@ clearCache
## Search expressions
# Check that empty search string matches all
nix search|grep -q foo
nix search|grep -q bar
nix search|grep -q hello
nix search|grepQuiet foo
nix search|grepQuiet bar
nix search|grepQuiet hello

View file

@ -13,7 +13,7 @@ cp config.nix dependencies.builder*.sh $tarroot/
tarball=$TEST_ROOT/tarball.tar.xz
(cd $TEST_ROOT && tar cf - tarball) | xz > $tarball
nix-env -f file://$tarball -qa --out-path | grep -q dependencies
nix-env -f file://$tarball -qa --out-path | grepQuiet dependencies
nix-build -o $TEST_ROOT/result file://$tarball

85
tests/test-infra.sh Normal file
View file

@ -0,0 +1,85 @@
# Test the functions for testing themselves!
# Also test some assumptions on how bash works that they rely on.
source common.sh
# `true` should exit with 0
expect 0 true
# `false` should exit with 1
expect 1 false
# `expect` will fail when we get it wrong
expect 1 expect 0 false
noisyTrue () {
echo YAY! >&2
true
}
noisyFalse () {
echo NAY! >&2
false
}
# These should redirect standard error to standard output
expectStderr 0 noisyTrue | grepQuiet YAY
expectStderr 1 noisyFalse | grepQuiet NAY
# `set -o pipefile` is enabled
pipefailure () {
# shellcheck disable=SC2216
true | false | true
}
expect 1 pipefailure
unset pipefailure
pipefailure () {
# shellcheck disable=SC2216
false | true | true
}
expect 1 pipefailure
unset pipefailure
commandSubstitutionPipeFailure () {
# shellcheck disable=SC2216
res=$(set -eu -o pipefail; false | true | echo 0)
}
expect 1 commandSubstitutionPipeFailure
# `set -u` is enabled
# note (...), making function use subshell, as unbound variable errors
# in the outer shell are *rightly* not recoverable.
useUnbound () (
set -eu
# shellcheck disable=SC2154
echo "$thisVariableIsNotBound"
)
expect 1 useUnbound
# ! alone unfortunately negates `set -e`, but it works in functions:
# shellcheck disable=SC2251
! true
funBang () {
! true
}
expect 1 funBang
unset funBang
# `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.
{ echo foo; echo bar; } | grep -v -q foo
{ echo foo; echo bar; } | expect 1 grepInverse foo
# `grepQuiet` is quiet
res=$(set -eu -o pipefail; echo foo | grepQuiet foo | wc -c)
(( res == 0 ))
unset res
# `greqQietInverse` is both
{ echo foo; echo bar; } | expect 1 grepQuietInverse foo
res=$(set -eu -o pipefail; echo foo | expect 1 grepQuietInverse foo | wc -c)
(( res == 0 ))
unset res

View file

@ -5,17 +5,14 @@ source common.sh
# XXX: This shouldnt be, but #4813 cause this test to fail
needLocalStore "see #4813"
set +e
messages=$(nix-build -Q timeout.nix -A infiniteLoop --timeout 2 2>&1)
status=$?
set -e
messages=$(nix-build -Q timeout.nix -A infiniteLoop --timeout 2 2>&1) && status=0 || status=$?
if [ $status -ne 101 ]; then
echo "error: 'nix-store' exited with '$status'; should have exited 101"
exit 1
fi
if ! echo "$messages" | grep -q "timed out"; then
if echo "$messages" | grepQuietInvert "timed out"; then
echo "error: build may have failed for reasons other than timeout; output:"
echo "$messages" >&2
exit 1

View file

@ -1,6 +1,6 @@
source common.sh
if [ -z "$storeCleared" ]; then
if [ -z "${storeCleared-}" ]; then
clearStore
fi
@ -19,13 +19,13 @@ drvPath10=$(nix-env -f ./user-envs.nix -qa --drv-path --no-name '*' | grep foo-1
[ -n "$outPath10" -a -n "$drvPath10" ]
# Query descriptions.
nix-env -f ./user-envs.nix -qa '*' --description | grep -q silly
nix-env -f ./user-envs.nix -qa '*' --description | grepQuiet silly
rm -rf $HOME/.nix-defexpr
ln -s $(pwd)/user-envs.nix $HOME/.nix-defexpr
nix-env -qa '*' --description | grep -q silly
nix-env -qa '*' --description | grepQuiet silly
# Query the system.
nix-env -qa '*' --system | grep -q $system
nix-env -qa '*' --system | grepQuiet $system
# Install "foo-1.0".
nix-env -i foo-1.0
@ -33,19 +33,19 @@ nix-env -i foo-1.0
# Query installed: should contain foo-1.0 now (which should be
# executable).
test "$(nix-env -q '*' | wc -l)" -eq 1
nix-env -q '*' | grep -q foo-1.0
nix-env -q '*' | grepQuiet foo-1.0
test "$($profiles/test/bin/foo)" = "foo-1.0"
# Test nix-env -qc to compare installed against available packages, and vice versa.
nix-env -qc '*' | grep -q '< 2.0'
nix-env -qac '*' | grep -q '> 1.0'
nix-env -qc '*' | grepQuiet '< 2.0'
nix-env -qac '*' | grepQuiet '> 1.0'
# Test the -b flag to filter out source-only packages.
[ "$(nix-env -qab | wc -l)" -eq 1 ]
# Test the -s flag to get package status.
nix-env -qas | grep -q 'IP- foo-1.0'
nix-env -qas | grep -q -- '--- bar-0.1'
nix-env -qas | grepQuiet 'IP- foo-1.0'
nix-env -qas | grepQuiet -- '--- bar-0.1'
# Disable foo.
nix-env --set-flag active false foo
@ -65,15 +65,15 @@ nix-env -i foo-2.0pre1
# Query installed: should contain foo-2.0pre1 now.
test "$(nix-env -q '*' | wc -l)" -eq 1
nix-env -q '*' | grep -q foo-2.0pre1
nix-env -q '*' | grepQuiet foo-2.0pre1
test "$($profiles/test/bin/foo)" = "foo-2.0pre1"
# Upgrade "foo": should install foo-2.0.
NIX_PATH=nixpkgs=./user-envs.nix:$NIX_PATH nix-env -f '<nixpkgs>' -u foo
NIX_PATH=nixpkgs=./user-envs.nix:${NIX_PATH-} nix-env -f '<nixpkgs>' -u foo
# Query installed: should contain foo-2.0 now.
test "$(nix-env -q '*' | wc -l)" -eq 1
nix-env -q '*' | grep -q foo-2.0
nix-env -q '*' | grepQuiet foo-2.0
test "$($profiles/test/bin/foo)" = "foo-2.0"
# Store the path of foo-2.0.
@ -85,20 +85,20 @@ nix-env -i bar-0.1
nix-env -e foo
# Query installed: should only contain bar-0.1 now.
if nix-env -q '*' | grep -q foo; then false; fi
nix-env -q '*' | grep -q bar
if nix-env -q '*' | grepQuiet foo; then false; fi
nix-env -q '*' | grepQuiet bar
# Rollback: should bring "foo" back.
oldGen="$(nix-store -q --resolve $profiles/test)"
nix-env --rollback
[ "$(nix-store -q --resolve $profiles/test)" != "$oldGen" ]
nix-env -q '*' | grep -q foo-2.0
nix-env -q '*' | grep -q bar
nix-env -q '*' | grepQuiet foo-2.0
nix-env -q '*' | grepQuiet bar
# Rollback again: should remove "bar".
nix-env --rollback
nix-env -q '*' | grep -q foo-2.0
if nix-env -q '*' | grep -q bar; then false; fi
nix-env -q '*' | grepQuiet foo-2.0
if nix-env -q '*' | grepQuiet bar; then false; fi
# Count generations.
nix-env --list-generations
@ -120,7 +120,7 @@ nix-env --switch-generation 7
# Install foo-1.0, now using its store path.
nix-env -i "$outPath10"
nix-env -q '*' | grep -q foo-1.0
nix-env -q '*' | grepQuiet foo-1.0
nix-store -qR $profiles/test | grep "$outPath10"
nix-store -q --referrers-closure $profiles/test | grep "$(nix-store -q --resolve $profiles/test)"
[ "$(nix-store -q --deriver "$outPath10")" = $drvPath10 ]
@ -128,12 +128,12 @@ nix-store -q --referrers-closure $profiles/test | grep "$(nix-store -q --resolve
# Uninstall foo-1.0, using a symlink to its store path.
ln -sfn $outPath10/bin/foo $TEST_ROOT/symlink
nix-env -e $TEST_ROOT/symlink
if nix-env -q '*' | grep -q foo; then false; fi
(! nix-store -qR $profiles/test | grep "$outPath10")
if nix-env -q '*' | grepQuiet foo; then false; fi
nix-store -qR $profiles/test | grepInverse "$outPath10"
# Install foo-1.0, now using a symlink to its store path.
nix-env -i $TEST_ROOT/symlink
nix-env -q '*' | grep -q foo
nix-env -q '*' | grepQuiet foo
# Delete all old generations.
nix-env --delete-generations old
@ -151,7 +151,7 @@ test "$(nix-env -q '*' | wc -l)" -eq 0
# Installing "foo" should only install the newest foo.
nix-env -i foo
test "$(nix-env -q '*' | grep foo- | wc -l)" -eq 1
nix-env -q '*' | grep -q foo-2.0
nix-env -q '*' | grepQuiet foo-2.0
# On the other hand, this should install both (and should fail due to
# a collision).
@ -162,8 +162,8 @@ nix-env -e '*'
nix-env -e '*'
nix-env -i '*'
test "$(nix-env -q '*' | wc -l)" -eq 2
nix-env -q '*' | grep -q foo-2.0
nix-env -q '*' | grep -q bar-0.1.1
nix-env -q '*' | grepQuiet foo-2.0
nix-env -q '*' | grepQuiet bar-0.1.1
# Test priorities: foo-0.1 has a lower priority than foo-1.0, so it
# should be possible to install both without a collision. Also test