doc: Make "Application Setup" more prominent.
[jackhill/guix/guix.git] / tests / syscalls.scm
CommitLineData
29fa45f4 1;;; GNU Guix --- Functional package management for GNU
d35c5e29 2;;; Copyright © 2014, 2015 Ludovic Courtès <ludo@gnu.org>
b4abdeb6 3;;; Copyright © 2015 David Thompson <davet@gnu.org>
29fa45f4
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(define-module (test-syscalls)
df3ce5c1 21 #:use-module (guix utils)
29fa45f4 22 #:use-module (guix build syscalls)
4d54785c 23 #:use-module (srfi srfi-1)
381ac93b 24 #:use-module (srfi srfi-26)
7585016f
LC
25 #:use-module (srfi srfi-64)
26 #:use-module (ice-9 match))
29fa45f4
LC
27
28;; Test the (guix build syscalls) module, although there's not much that can
29;; actually be tested without being root.
30
31(test-begin "syscalls")
32
33(test-equal "mount, ENOENT"
34 ENOENT
35 (catch 'system-error
36 (lambda ()
37 (mount "/dev/null" "/does-not-exist" "ext2")
38 #f)
39 (compose system-error-errno list)))
40
35066aa5 41(test-assert "umount, ENOENT/EPERM"
29fa45f4
LC
42 (catch 'system-error
43 (lambda ()
44 (umount "/does-not-exist")
45 #f)
35066aa5
LC
46 (lambda args
47 ;; Both return values have been encountered in the wild.
48 (memv (system-error-errno args) (list EPERM ENOENT)))))
29fa45f4 49
ccea821b 50(test-assert "mount-points"
381ac93b
LC
51 ;; Reportedly "/" is not always listed as a mount point, so check a few
52 ;; others (see <http://bugs.gnu.org/20261>.)
53 (any (cute member <> (mount-points))
54 '("/" "/proc" "/sys" "/dev")))
ccea821b 55
715fc9d4
LC
56(test-assert "swapon, ENOENT/EPERM"
57 (catch 'system-error
58 (lambda ()
59 (swapon "/does-not-exist")
60 #f)
61 (lambda args
62 (memv (system-error-errno args) (list EPERM ENOENT)))))
63
2793c0fb 64(test-assert "swapoff, ENOENT/EINVAL/EPERM"
715fc9d4
LC
65 (catch 'system-error
66 (lambda ()
67 (swapoff "/does-not-exist")
68 #f)
69 (lambda args
2793c0fb 70 (memv (system-error-errno args) (list EPERM EINVAL ENOENT)))))
715fc9d4 71
b4abdeb6
DT
72(test-assert "mkdtemp!"
73 (let* ((tmp (or (getenv "TMPDIR") "/tmp"))
74 (dir (mkdtemp! (string-append tmp "/guix-test-XXXXXX"))))
75 (and (file-exists? dir)
76 (begin
77 (rmdir dir)
78 #t))))
79
8950ed11
DT
80(define (user-namespace pid)
81 (string-append "/proc/" (number->string pid) "/ns/user"))
82
b62a3ebc
LC
83(unless (file-exists? (user-namespace (getpid)))
84 (test-skip 1))
8950ed11
DT
85(test-assert "clone"
86 (match (clone (logior CLONE_NEWUSER SIGCHLD))
87 (0 (primitive-exit 42))
88 (pid
89 ;; Check if user namespaces are different.
90 (and (not (equal? (readlink (user-namespace pid))
91 (readlink (user-namespace (getpid)))))
92 (match (waitpid pid)
93 ((_ . status)
94 (= 42 (status:exit-val status))))))))
95
b62a3ebc
LC
96(unless (file-exists? (user-namespace (getpid)))
97 (test-skip 1))
43ace6ea
DT
98(test-assert "setns"
99 (match (clone (logior CLONE_NEWUSER SIGCHLD))
100 (0 (primitive-exit 0))
101 (clone-pid
102 (match (pipe)
103 ((in . out)
104 (match (primitive-fork)
105 (0
106 (close in)
107 ;; Join the user namespace.
108 (call-with-input-file (user-namespace clone-pid)
109 (lambda (port)
110 (setns (port->fdes port) 0)))
111 (write 'done out)
112 (close out)
113 (primitive-exit 0))
114 (fork-pid
115 (close out)
116 ;; Wait for the child process to join the namespace.
117 (read in)
118 (let ((result (and (equal? (readlink (user-namespace clone-pid))
119 (readlink (user-namespace fork-pid))))))
120 ;; Clean up.
121 (waitpid clone-pid)
122 (waitpid fork-pid)
123 result))))))))
8950ed11 124
b62a3ebc
LC
125(unless (file-exists? (user-namespace (getpid)))
126 (test-skip 1))
df3ce5c1
DT
127(test-assert "pivot-root"
128 (match (pipe)
129 ((in . out)
130 (match (clone (logior CLONE_NEWUSER CLONE_NEWNS SIGCHLD))
131 (0
132 (close in)
133 (call-with-temporary-directory
134 (lambda (root)
135 (let ((put-old (string-append root "/real-root")))
136 (mount "none" root "tmpfs")
137 (mkdir put-old)
138 (call-with-output-file (string-append root "/test")
139 (lambda (port)
140 (display "testing\n" port)))
141 (pivot-root root put-old)
142 ;; The test file should now be located inside the root directory.
143 (write (file-exists? "/test") out)
144 (close out))))
145 (primitive-exit 0))
146 (pid
147 (close out)
148 (let ((result (read in)))
149 (close in)
150 (and (zero? (match (waitpid pid)
151 ((_ . status)
152 (status:exit-val status))))
153 (eq? #t result))))))))
154
4d54785c
LC
155(test-assert "all-network-interfaces"
156 (match (all-network-interfaces)
157 (((? string? names) ..1)
158 (member "lo" names))))
159
7585016f
LC
160(test-assert "network-interfaces"
161 (match (network-interfaces)
162 (((? string? names) ..1)
4d54785c 163 (lset<= string=? names (all-network-interfaces)))))
7585016f 164
973eea34 165(test-assert "network-interface-flags"
c9bf64d6 166 (let* ((sock (socket AF_INET SOCK_STREAM 0))
973eea34
LC
167 (flags (network-interface-flags sock "lo")))
168 (close-port sock)
169 (and (not (zero? (logand flags IFF_LOOPBACK)))
170 (not (zero? (logand flags IFF_UP))))))
171
172(test-equal "loopback-network-interface?"
173 ENODEV
174 (and (loopback-network-interface? "lo")
175 (catch 'system-error
176 (lambda ()
177 (loopback-network-interface? "nonexistent")
178 #f)
179 (lambda args
180 (system-error-errno args)))))
181
c9bf64d6 182(test-skip (if (zero? (getuid)) 1 0))
d35c5e29 183(test-assert "set-network-interface-flags"
c9bf64d6
LC
184 (let ((sock (socket AF_INET SOCK_STREAM 0)))
185 (catch 'system-error
186 (lambda ()
187 (set-network-interface-flags sock "lo" IFF_UP))
188 (lambda args
189 (close-port sock)
d35c5e29
LC
190 ;; We get EPERM with Linux 3.18ish and EACCES with 2.6.32.
191 (memv (system-error-errno args) (list EPERM EACCES))))))
c9bf64d6
LC
192
193(test-equal "network-interface-address lo"
194 (make-socket-address AF_INET (inet-pton AF_INET "127.0.0.1") 0)
195 (let* ((sock (socket AF_INET SOCK_STREAM 0))
196 (addr (network-interface-address sock "lo")))
197 (close-port sock)
198 addr))
199
d35c5e29 200(test-assert "set-network-interface-address"
c9bf64d6
LC
201 (let ((sock (socket AF_INET SOCK_STREAM 0)))
202 (catch 'system-error
203 (lambda ()
204 (set-network-interface-address sock "nonexistent"
205 (make-socket-address
206 AF_INET
207 (inet-pton AF_INET "127.12.14.15")
208 0)))
209 (lambda args
210 (close-port sock)
d35c5e29
LC
211 ;; We get EPERM with Linux 3.18ish and EACCES with 2.6.32.
212 (memv (system-error-errno args) (list EPERM EACCES))))))
c9bf64d6 213
29fa45f4
LC
214(test-end)
215
216\f
217(exit (= (test-runner-fail-count (test-runner-current)) 0))