doc: Add "Defining Package Variants" section.
[jackhill/guix/guix.git] / tests / guix-pack-relocatable.sh
CommitLineData
b07014f5 1# GNU Guix --- Functional package management for GNU
2520059b 2# Copyright © 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org>
4184998c 3# Copyright © 2020 Eric Bavier <bavier@posteo.net>
b07014f5
LC
4#
5# This file is part of GNU Guix.
6#
7# GNU Guix is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or (at
10# your option) any later version.
11#
12# GNU Guix is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
19
20#
21# Test the 'guix pack --relocatable' using the external store, if any.
22#
23
24guix pack --version
25
26# 'guix pack --relocatable' requires a C compiler and libc.a, which our
27# bootstrap binaries don't provide. To make the test relatively inexpensive,
28# run it on the user's global store if possible, on the grounds that binaries
29# may already be there or can be built or downloaded inexpensively.
30
baab87ac 31storedir="`guile -c '(use-modules (guix config))(display %storedir)'`"
b07014f5 32localstatedir="`guile -c '(use-modules (guix config))(display %localstatedir)'`"
baab87ac 33NIX_STORE_DIR="$storedir"
b07014f5
LC
34GUIX_DAEMON_SOCKET="$localstatedir/guix/daemon-socket/socket"
35export NIX_STORE_DIR GUIX_DAEMON_SOCKET
36
37if ! guile -c '(use-modules (guix)) (exit (false-if-exception (open-connection)))'
38then
39 exit 77
40fi
41
c6c0d5a2
LC
42# Attempt to run the given command in a namespace where the store is
43# invisible. This makes sure the presence of the store does not hide
44# problems.
45run_without_store ()
46{
47 if unshare -r true # Are user namespaces supported?
48 then
49 # Run that relocatable executable in a user namespace where we "erase"
50 # the store by mounting an empty file system on top of it. That way,
51 # we exercise the wrapper code that creates the user namespace and
52 # bind-mounts the store.
53 unshare -mrf sh -c 'mount -t tmpfs -o ro none "$NIX_STORE_DIR"; '"$*"
54 else
55 # Run the relocatable program in the current namespaces. This is a
56 # weak test because we're going to access store items from the host
57 # store.
58 $*
59 fi
60}
b07014f5
LC
61
62test_directory="`mktemp -d`"
63export test_directory
64trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT
65
c6c0d5a2 66if unshare -r true
8deb65c3 67then
c6c0d5a2
LC
68 # Test the 'userns' execution engine.
69 tarball="`guix pack -R -S /Bin=bin sed`"
70 (cd "$test_directory"; tar xvf "$tarball")
71
72 run_without_store "$test_directory/Bin/sed" --version > "$test_directory/output"
73 grep 'GNU sed' "$test_directory/output"
74
75 # Same with an explicit engine.
76 run_without_store GUIX_EXECUTION_ENGINE="userns" \
77 "$test_directory/Bin/sed" --version > "$test_directory/output"
78 grep 'GNU sed' "$test_directory/output"
2520059b
LC
79
80 # Check whether the exit code is preserved.
d8934360 81 ! run_without_store "$test_directory/Bin/sed" --does-not-exist
c6c0d5a2
LC
82
83 chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
8deb65c3 84else
c6c0d5a2 85 echo "'userns' execution tests skipped" >&2
8deb65c3 86fi
b908fcd8 87
fde2aec3
LC
88case "`uname -m`" in
89 x86_64|i?86)
90 # Try '-RR' and PRoot.
91 tarball="`guix pack -RR -S /Bin=bin sed`"
92 tar tvf "$tarball" | grep /bin/proot
c088aa29 93 (cd "$test_directory"; tar xf "$tarball")
c6c0d5a2 94 run_without_store GUIX_EXECUTION_ENGINE="proot" \
fde2aec3
LC
95 "$test_directory/Bin/sed" --version > "$test_directory/output"
96 grep 'GNU sed' "$test_directory/output"
64562321
LC
97
98 # Now with fakechroot.
c6c0d5a2 99 run_without_store GUIX_EXECUTION_ENGINE="fakechroot" \
64562321
LC
100 "$test_directory/Bin/sed" --version > "$test_directory/output"
101 grep 'GNU sed' "$test_directory/output"
4184998c 102 unset GUIX_EXECUTION_ENGINE
64562321 103
fde2aec3 104 chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
c088aa29
LC
105
106 if unshare -r true
107 then
108 # Check whether the store contains everything it should. Check
109 # once when erasing $STORE_PARENT ("/gnu") and once when erasing
110 # $NIX_STORE_DIR ("/gnu/store").
111 tarball="`guix pack -RR -S /bin=bin bash-minimal`"
112 (cd "$test_directory"; tar xf "$tarball")
113
114 STORE_PARENT="`dirname $NIX_STORE_DIR`"
115 export STORE_PARENT
116
117 for engine in userns proot fakechroot
118 do
119 for i in $(guix gc -R $(guix build bash-minimal | grep -v -e '-doc$'))
120 do
121 unshare -mrf sh -c "mount -t tmpfs none \"$NIX_STORE_DIR\"; GUIX_EXECUTION_ENGINE=$engine $test_directory/bin/sh -c 'echo $NIX_STORE_DIR/*'" | grep $(basename $i)
122 unshare -mrf sh -c "mount -t tmpfs none \"$STORE_PARENT\"; GUIX_EXECUTION_ENGINE=$engine $test_directory/bin/sh -c 'echo $NIX_STORE_DIR/*'" | grep $(basename $i)
123 done
124 done
125
126 chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
127 fi
fde2aec3
LC
128 ;;
129 *)
c6c0d5a2 130 echo "skipping PRoot and Fakechroot tests" >&2
fde2aec3
LC
131 ;;
132esac
133
b908fcd8
LC
134# Ensure '-R' works with outputs other than "out".
135tarball="`guix pack -R -S /share=share groff:doc`"
c088aa29 136(cd "$test_directory"; tar xf "$tarball")
b908fcd8 137test -d "$test_directory/share/doc/groff/html"
4184998c 138chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
a5538922
LC
139
140# Ensure '-R' applies to propagated inputs. Failing to do that, it would fail
141# with a profile collision error in this case because 'python-scipy'
142# propagates 'python-numpy'. See <https://bugs.gnu.org/42510>.
143guix pack -RR python-numpy python-scipy --no-grafts -n
4184998c
EB
144
145# Check that packages that mix executable and support files (e.g. git) in the
146# "binary" directories still work after wrapped.
147cat >"$test_directory/manifest.scm" <<'EOF'
148(use-modules (guix) (guix profiles) (guix search-paths)
149 (gnu packages bootstrap))
150(manifest
151 (list (manifest-entry
152 (name "test") (version "0")
153 (item (file-union "test"
154 `(("bin/hello"
155 ,(program-file
156 "hello"
157 #~(begin
158 (add-to-load-path (getenv "HELLO_EXEC_PATH"))
159 (display (load-from-path "msg"))(newline))
160 #:guile %bootstrap-guile))
161 ("libexec/hello/msg"
162 ,(plain-file "msg" "42")))))
163 (search-paths
164 (list (search-path-specification
165 (variable "HELLO_EXEC_PATH")
166 (files '("libexec/hello"))
167 (separator #f)))))))
168EOF
169tarball="`guix pack -RR -S /opt= -m $test_directory/manifest.scm`"
170(cd "$test_directory"; tar xvf "$tarball")
171( export GUIX_PROFILE=$test_directory/opt
172 . $GUIX_PROFILE/etc/profile
173 run_without_store "$test_directory/opt/bin/hello" > "$test_directory/output" )
174cat "$test_directory/output"
175test "`cat $test_directory/output`" = "42"