Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[backport 2.3] Allow testing with different daemons #5650

Draft
wants to merge 14 commits into
base: 2.3-maintenance
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions mk/run_test.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/sh

set -u
set -eu -o pipefail

red=""
green=""
Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ define run-install-test
endef

.PHONY: check installcheck

print-top-help += \
echo " installcheck: Run functional tests";
8 changes: 5 additions & 3 deletions tests/binary-cache.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
source common.sh

needLocalStore "“--no-require-sigs” can’t be used with the daemon"

clearStore
clearCache

Expand Down Expand Up @@ -60,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

Expand Down Expand Up @@ -108,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
Expand Down
2 changes: 1 addition & 1 deletion tests/build-dry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 5 additions & 5 deletions tests/check-refs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions tests/check-reqs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
3 changes: 3 additions & 0 deletions tests/check.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
source common.sh

# XXX: This shouldn’t be, but #4813 cause this test to fail
buggyNeedLocalStore "see #4813"

clearStore

nix-build dependencies.nix --no-out-link
Expand Down
158 changes: 145 additions & 13 deletions tests/common.sh.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
set -e
set -eu -o pipefail

if [[ -z "${COMMON_SH_SOURCED-}" ]]; then

COMMON_SH_SOURCED=1

export PS4='+(${BASH_SOURCE[0]}:$LINENO) '

export TEST_ROOT=$(realpath ${TMPDIR:-/tmp}/nix-test)/${TEST_NAME:-default}
export NIX_STORE_DIR
Expand All @@ -18,14 +24,21 @@ 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
unset XDG_CACHE_HOME
mkdir -p $TEST_HOME

export PATH=@bindir@:$PATH
if [[ -n "${NIX_CLIENT_PACKAGE:-}" ]]; then
export PATH="$NIX_CLIENT_PACKAGE/bin":$PATH
fi
DAEMON_PATH="$PATH"
if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then
DAEMON_PATH="${NIX_DAEMON_PACKAGE}/bin:$DAEMON_PATH"
fi
coreutils=@coreutils@

export dot=@dot@
Expand All @@ -37,6 +50,9 @@ export HAVE_SODIUM="@HAVE_SODIUM@"
export version=@PACKAGE_VERSION@
export system=@system@

export IMPURE_VAR1=foo
export IMPURE_VAR2=bar

cacheDir=$TEST_ROOT/binary-cache

readLink() {
Expand All @@ -55,7 +71,6 @@ clearStore() {
mkdir "$NIX_STORE_DIR"
rm -rf "$NIX_STATE_DIR"
mkdir "$NIX_STATE_DIR"
nix-store --init
clearProfiles
}

Expand All @@ -68,31 +83,73 @@ clearCacheCache() {
}

startDaemon() {
# Don’t start the daemon twice, as this would just make it loop indefinitely
if [[ "$NIX_REMOTE" == daemon ]]; then
return
fi
# Start the daemon, wait for the socket to appear. !!!
# ‘nix-daemon’ should have an option to fork into the background.
rm -f $NIX_STATE_DIR/daemon-socket/socket
nix-daemon &
rm -f $NIX_DAEMON_SOCKET_PATH
PATH=$DAEMON_PATH nix-daemon &
pidDaemon=$!
for ((i = 0; i < 30; i++)); do
if [ -e $NIX_DAEMON_SOCKET_PATH ]; then break; fi
if [[ -S $NIX_DAEMON_SOCKET_PATH ]]; then break; fi
sleep 1
done
pidDaemon=$!
trap "kill -9 $pidDaemon" EXIT
trap "killDaemon" EXIT
# Save for if daemon is killed
NIX_REMOTE_OLD=$NIX_REMOTE
export NIX_REMOTE=daemon
}

killDaemon() {
kill -9 $pidDaemon
kill $pidDaemon
for i in {0.10}; do
kill -0 $pidDaemon || break
sleep 1
done
kill -9 $pidDaemon || true
wait $pidDaemon || true
# Restore old nix remote
NIX_REMOTE=$NIX_REMOTE_OLD
trap "" EXIT
}

restartDaemon() {
[[ -z "${pidDaemon:-}" ]] && return 0

killDaemon
startDaemon
}

if [[ $(uname) == Linux ]] && [[ -L /proc/self/ns/user ]] && unshare --user true; then
_canUseSandbox=1
fi

isDaemonOlder () {
[[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0
local requiredVersion="$1"
local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3)
[[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''$requiredVersion''") -lt 0 ]]
}

isDaemonNewer () {
[[ -n "${NIX_DAEMON_PACKAGE:-}" ]] || return 0
local requiredVersion="$1"
local daemonVersion=$($NIX_DAEMON_PACKAGE/bin/nix-daemon --version | cut -d' ' -f3)
[[ $(nix eval --expr "builtins.compareVersions ''$daemonVersion'' ''$requiredVersion''") -ge 0 ]]
}

requireDaemonOlderThan () {
isDaemonOlder "$1" || exit 99
}

requireDaemonNewerThan () {
isDaemonNewer "$1" || exit 99
}

canUseSandbox() {
if [[ ! $_canUseSandbox ]]; then
if [[ ! ${_canUseSandbox-} ]]; then
echo "Sandboxing not supported, skipping this test..."
return 1
fi
Expand All @@ -105,15 +162,90 @@ 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() {
if [[ "$NIX_REMOTE" == "daemon" ]]; then
echo "Can’t run through the daemon ($1), skipping this test..."
return 99
fi
}

# Just to make it easy to find which tests should be fixed
buggyNeedLocalStore () {
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

if [[ -n "${NIX_DAEMON_PACKAGE:-}" ]]; then
startDaemon
fi

fi # COMMON_SH_SOURCED
8 changes: 4 additions & 4 deletions tests/dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand All @@ -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")
Expand All @@ -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"
2 changes: 2 additions & 0 deletions tests/dump-db.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
source common.sh

needLocalStore "--dump-db requires a local store"

clearStore

path=$(nix-build dependencies.nix -o $TEST_ROOT/result)
Expand Down
2 changes: 1 addition & 1 deletion tests/export-graph.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion tests/fetchurl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 0 additions & 3 deletions tests/fixed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ source common.sh

clearStore

export IMPURE_VAR1=foo
export IMPURE_VAR2=bar

path=$(nix-store -q $(nix-instantiate fixed.nix -A good.0))

echo 'testing bad...'
Expand Down
Loading
Loading