Commit | Line | Data |
---|---|---|
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 | ||
24 | guix 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 | 31 | storedir="`guile -c '(use-modules (guix config))(display %storedir)'`" |
b07014f5 | 32 | localstatedir="`guile -c '(use-modules (guix config))(display %localstatedir)'`" |
baab87ac | 33 | NIX_STORE_DIR="$storedir" |
b07014f5 LC |
34 | GUIX_DAEMON_SOCKET="$localstatedir/guix/daemon-socket/socket" |
35 | export NIX_STORE_DIR GUIX_DAEMON_SOCKET | |
36 | ||
37 | if ! guile -c '(use-modules (guix)) (exit (false-if-exception (open-connection)))' | |
38 | then | |
39 | exit 77 | |
40 | fi | |
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. | |
45 | run_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 | |
62 | test_directory="`mktemp -d`" | |
63 | export test_directory | |
64 | trap 'chmod -Rf +w "$test_directory"; rm -rf "$test_directory"' EXIT | |
65 | ||
c6c0d5a2 | 66 | if unshare -r true |
8deb65c3 | 67 | then |
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 | 84 | else |
c6c0d5a2 | 85 | echo "'userns' execution tests skipped" >&2 |
8deb65c3 | 86 | fi |
b908fcd8 | 87 | |
fde2aec3 LC |
88 | case "`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 | ;; |
132 | esac | |
133 | ||
b908fcd8 LC |
134 | # Ensure '-R' works with outputs other than "out". |
135 | tarball="`guix pack -R -S /share=share groff:doc`" | |
c088aa29 | 136 | (cd "$test_directory"; tar xf "$tarball") |
b908fcd8 | 137 | test -d "$test_directory/share/doc/groff/html" |
4184998c | 138 | chmod -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>. | |
143 | guix 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. | |
147 | cat >"$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))))))) | |
168 | EOF | |
169 | tarball="`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" ) | |
174 | cat "$test_directory/output" | |
175 | test "`cat $test_directory/output`" = "42" |