epiphany w/ gtk4 and webkitgtk 2.38
[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.
a67b8247 58 sh -c "$*"
c6c0d5a2
LC
59 fi
60}
b07014f5 61
bfe82fe2
LC
62# Wait for the given file to show up. Error out if it doesn't show up in a
63# timely fashion.
64wait_for_file ()
65{
66 i=0
67 while ! test -f "$1" && test $i -lt 20
68 do
69 sleep 0.3
70 i=`expr $i + 1`
71 done
72 test -f "$1"
73}
74
b07014f5
LC
75test_directory="`mktemp -d`"
76export test_directory
77trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT
78
c6c0d5a2 79if unshare -r true
8deb65c3 80then
c6c0d5a2
LC
81 # Test the 'userns' execution engine.
82 tarball="`guix pack -R -S /Bin=bin sed`"
83 (cd "$test_directory"; tar xvf "$tarball")
84
85 run_without_store "$test_directory/Bin/sed" --version > "$test_directory/output"
86 grep 'GNU sed' "$test_directory/output"
87
88 # Same with an explicit engine.
89 run_without_store GUIX_EXECUTION_ENGINE="userns" \
90 "$test_directory/Bin/sed" --version > "$test_directory/output"
91 grep 'GNU sed' "$test_directory/output"
2520059b
LC
92
93 # Check whether the exit code is preserved.
d8934360 94 ! run_without_store "$test_directory/Bin/sed" --does-not-exist
c6c0d5a2
LC
95
96 chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
8deb65c3 97else
c6c0d5a2 98 echo "'userns' execution tests skipped" >&2
8deb65c3 99fi
b908fcd8 100
fde2aec3
LC
101case "`uname -m`" in
102 x86_64|i?86)
103 # Try '-RR' and PRoot.
104 tarball="`guix pack -RR -S /Bin=bin sed`"
105 tar tvf "$tarball" | grep /bin/proot
c088aa29 106 (cd "$test_directory"; tar xf "$tarball")
c6c0d5a2 107 run_without_store GUIX_EXECUTION_ENGINE="proot" \
fde2aec3
LC
108 "$test_directory/Bin/sed" --version > "$test_directory/output"
109 grep 'GNU sed' "$test_directory/output"
64562321
LC
110
111 # Now with fakechroot.
c6c0d5a2 112 run_without_store GUIX_EXECUTION_ENGINE="fakechroot" \
64562321
LC
113 "$test_directory/Bin/sed" --version > "$test_directory/output"
114 grep 'GNU sed' "$test_directory/output"
4184998c 115 unset GUIX_EXECUTION_ENGINE
64562321 116
fde2aec3 117 chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
c088aa29
LC
118
119 if unshare -r true
120 then
121 # Check whether the store contains everything it should. Check
122 # once when erasing $STORE_PARENT ("/gnu") and once when erasing
123 # $NIX_STORE_DIR ("/gnu/store").
124 tarball="`guix pack -RR -S /bin=bin bash-minimal`"
125 (cd "$test_directory"; tar xf "$tarball")
126
127 STORE_PARENT="`dirname $NIX_STORE_DIR`"
128 export STORE_PARENT
129
130 for engine in userns proot fakechroot
131 do
132 for i in $(guix gc -R $(guix build bash-minimal | grep -v -e '-doc$'))
133 do
134 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)
135 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)
136 done
137 done
138
139 chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
140 fi
fde2aec3
LC
141 ;;
142 *)
c6c0d5a2 143 echo "skipping PRoot and Fakechroot tests" >&2
fde2aec3
LC
144 ;;
145esac
146
bfe82fe2
LC
147if unshare -r true
148then
149 # Check what happens if the wrapped binary forks and leaves child
150 # processes behind, like a daemon. The root file system should remain
151 # available to those child processes. See <https://bugs.gnu.org/44261>.
152 cat > "$test_directory/manifest.scm" <<EOF
153(use-modules (guix))
154
155(define daemon
156 (program-file "daemon"
157 #~(begin
158 (use-modules (ice-9 match)
159 (ice-9 ftw))
160
161 (call-with-output-file "parent-store"
162 (lambda (port)
163 (write (scandir (ungexp (%store-prefix)))
164 port)))
165
166 (match (primitive-fork)
167 (0 (sigaction SIGHUP (const #t))
168 (call-with-output-file "pid"
169 (lambda (port)
170 (display (getpid) port)))
171 (pause)
172 (call-with-output-file "child-store"
173 (lambda (port)
174 (write (scandir (ungexp (%store-prefix)))
175 port))))
176 (_ #t)))))
177
178(define package
179 (computed-file "package"
180 #~(let ((out (ungexp output)))
181 (mkdir out)
182 (mkdir (string-append out "/bin"))
183 (symlink (ungexp daemon)
184 (string-append out "/bin/daemon")))))
185
186(manifest (list (manifest-entry
187 (name "daemon")
188 (version "0")
189 (item package))))
190EOF
191
192 tarball="$(guix pack -S /bin=bin -R -m "$test_directory/manifest.scm")"
193 (cd "$test_directory"; tar xf "$tarball")
194
195 # Run '/bin/daemon', which forks, then wait for the child, send it SIGHUP
196 # so that it dumps its view of the store, and make sure the child and
197 # parent both see the same store contents.
198 (cd "$test_directory"; run_without_store ./bin/daemon)
199 wait_for_file "$test_directory/pid"
200 kill -HUP $(cat "$test_directory/pid")
201 wait_for_file "$test_directory/child-store"
202 diff -u "$test_directory/parent-store" "$test_directory/child-store"
203
204 chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
205fi
206
b908fcd8
LC
207# Ensure '-R' works with outputs other than "out".
208tarball="`guix pack -R -S /share=share groff:doc`"
c088aa29 209(cd "$test_directory"; tar xf "$tarball")
b908fcd8 210test -d "$test_directory/share/doc/groff/html"
4184998c 211chmod -Rf +w "$test_directory"; rm -rf "$test_directory"/*
a5538922
LC
212
213# Ensure '-R' applies to propagated inputs. Failing to do that, it would fail
214# with a profile collision error in this case because 'python-scipy'
215# propagates 'python-numpy'. See <https://bugs.gnu.org/42510>.
216guix pack -RR python-numpy python-scipy --no-grafts -n
4184998c
EB
217
218# Check that packages that mix executable and support files (e.g. git) in the
219# "binary" directories still work after wrapped.
220cat >"$test_directory/manifest.scm" <<'EOF'
221(use-modules (guix) (guix profiles) (guix search-paths)
222 (gnu packages bootstrap))
223(manifest
224 (list (manifest-entry
225 (name "test") (version "0")
226 (item (file-union "test"
227 `(("bin/hello"
228 ,(program-file
229 "hello"
230 #~(begin
231 (add-to-load-path (getenv "HELLO_EXEC_PATH"))
232 (display (load-from-path "msg"))(newline))
233 #:guile %bootstrap-guile))
234 ("libexec/hello/msg"
235 ,(plain-file "msg" "42")))))
236 (search-paths
237 (list (search-path-specification
238 (variable "HELLO_EXEC_PATH")
239 (files '("libexec/hello"))
240 (separator #f)))))))
241EOF
242tarball="`guix pack -RR -S /opt= -m $test_directory/manifest.scm`"
243(cd "$test_directory"; tar xvf "$tarball")
244( export GUIX_PROFILE=$test_directory/opt
245 . $GUIX_PROFILE/etc/profile
246 run_without_store "$test_directory/opt/bin/hello" > "$test_directory/output" )
247cat "$test_directory/output"
248test "`cat $test_directory/output`" = "42"