summaryrefslogtreecommitdiff
path: root/gnu/tests/base.scm
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/tests/base.scm')
-rw-r--r--gnu/tests/base.scm468
1 files changed, 315 insertions, 153 deletions
diff --git a/gnu/tests/base.scm b/gnu/tests/base.scm
index 4fe779802ba..479403e5c1a 100644
--- a/gnu/tests/base.scm
+++ b/gnu/tests/base.scm
@@ -22,10 +22,15 @@
22 #:use-module (gnu system grub) 22 #:use-module (gnu system grub)
23 #:use-module (gnu system file-systems) 23 #:use-module (gnu system file-systems)
24 #:use-module (gnu system shadow) 24 #:use-module (gnu system shadow)
25 #:use-module (gnu system nss)
25 #:use-module (gnu system vm) 26 #:use-module (gnu system vm)
26 #:use-module (gnu services) 27 #:use-module (gnu services)
28 #:use-module (gnu services base)
29 #:use-module (gnu services dbus)
30 #:use-module (gnu services avahi)
27 #:use-module (gnu services mcron) 31 #:use-module (gnu services mcron)
28 #:use-module (gnu services shepherd) 32 #:use-module (gnu services shepherd)
33 #:use-module (gnu services networking)
29 #:use-module (guix gexp) 34 #:use-module (guix gexp)
30 #:use-module (guix store) 35 #:use-module (guix store)
31 #:use-module (guix monads) 36 #:use-module (guix monads)
@@ -33,7 +38,8 @@
33 #:use-module (srfi srfi-1) 38 #:use-module (srfi srfi-1)
34 #:export (run-basic-test 39 #:export (run-basic-test
35 %test-basic-os 40 %test-basic-os
36 %test-mcron)) 41 %test-mcron
42 %test-nss-mdns))
37 43
38(define %simple-os 44(define %simple-os
39 (operating-system 45 (operating-system
@@ -64,104 +70,123 @@
64using COMMAND, a gexp that evaluates to a list of strings. Compare some 70using COMMAND, a gexp that evaluates to a list of strings. Compare some
65properties of running system to what's declared in OS, an <operating-system>." 71properties of running system to what's declared in OS, an <operating-system>."
66 (define test 72 (define test
67 #~(begin 73 (with-imported-modules '((gnu build marionette))
68 (use-modules (gnu build marionette) 74 #~(begin
69 (srfi srfi-1) 75 (use-modules (gnu build marionette)
70 (srfi srfi-26) 76 (srfi srfi-64)
71 (srfi srfi-64) 77 (ice-9 match))
72 (ice-9 match)) 78
73 79 (define marionette
74 (define marionette 80 (make-marionette #$command))
75 (make-marionette #$command)) 81
76 82 (mkdir #$output)
77 (mkdir #$output) 83 (chdir #$output)
78 (chdir #$output) 84
79 85 (test-begin "mcron")
80 (test-begin "basic") 86
81 87 (test-assert "uname"
82 (test-assert "uname" 88 (match (marionette-eval '(uname) marionette)
83 (match (marionette-eval '(uname) marionette) 89 (#("Linux" host-name version _ architecture)
84 (#("Linux" host-name version _ architecture) 90 (and (string=? host-name
85 (and (string=? host-name 91 #$(operating-system-host-name os))
86 #$(operating-system-host-name os)) 92 (string-prefix? #$(package-version
87 (string-prefix? #$(package-version 93 (operating-system-kernel os))
88 (operating-system-kernel os)) 94 version)
89 version) 95 (string-prefix? architecture %host-type)))))
90 (string-prefix? architecture %host-type))))) 96
91 97 (test-assert "shell and user commands"
92 (test-assert "shell and user commands" 98 ;; Is everything in $PATH?
93 ;; Is everything in $PATH? 99 (zero? (marionette-eval '(system "
94 (zero? (marionette-eval '(system "
95. /etc/profile 100. /etc/profile
96set -e -x 101set -e -x
97guix --version 102guix --version
98ls --version 103ls --version
99grep --version 104grep --version
100info --version") 105info --version")
101 marionette))) 106 marionette)))
102 107
103 (test-assert "accounts" 108 (test-assert "accounts"
104 (let ((users (marionette-eval '(begin 109 (let ((users (marionette-eval '(begin
105 (use-modules (ice-9 match)) 110 (use-modules (ice-9 match))
106 (let loop ((result '())) 111 (let loop ((result '()))
107 (match (getpw) 112 (match (getpw)
108 (#f (reverse result)) 113 (#f (reverse result))
109 (x (loop (cons x result)))))) 114 (x (loop (cons x result))))))
110 marionette))) 115 marionette)))
111 (lset= string=? 116 (lset= string=?
112 (map passwd:name users) 117 (map passwd:name users)
113 (list 118 (list
114 #$@(map user-account-name 119 #$@(map user-account-name
115 (operating-system-user-accounts os)))))) 120 (operating-system-user-accounts os))))))
116 121
117 (test-assert "shepherd services" 122 (test-assert "shepherd services"
118 (let ((services (marionette-eval '(begin 123 (let ((services (marionette-eval '(begin
119 (use-modules (gnu services herd)) 124 (use-modules (gnu services herd))
120 (call-with-values current-services 125 (call-with-values current-services
121 append)) 126 append))
122 marionette))) 127 marionette)))
123 (lset= eq? 128 (lset= eq?
124 (pk 'services services) 129 (pk 'services services)
125 '(root #$@(operating-system-shepherd-service-names os))))) 130 '(root #$@(operating-system-shepherd-service-names os)))))
126 131
127 (test-equal "login on tty1" 132 (test-equal "login on tty1"
128 "root\n" 133 "root\n"
129 (begin 134 (begin
130 (marionette-control "sendkey ctrl-alt-f1" marionette) 135 (marionette-control "sendkey ctrl-alt-f1" marionette)
131 ;; Wait for the 'term-tty1' service to be running (using 136 ;; Wait for the 'term-tty1' service to be running (using
132 ;; 'start-service' is the simplest and most reliable way to do 137 ;; 'start-service' is the simplest and most reliable way to do
133 ;; that.) 138 ;; that.)
139 (marionette-eval
140 '(begin
141 (use-modules (gnu services herd))
142 (start-service 'term-tty1))
143 marionette)
144
145 ;; Now we can type.
146 (marionette-type "root\n\nid -un > logged-in\n" marionette)
147
148 ;; It can take a while before the shell commands are executed.
149 (let loop ((i 0))
150 (unless (or (file-exists? "/root/logged-in") (> i 15))
151 (sleep 1)
152 (loop (+ i 1))))
153 (marionette-eval '(use-modules (rnrs io ports)) marionette)
154 (marionette-eval '(call-with-input-file "/root/logged-in"
155 get-string-all)
156 marionette)))
157
158 (test-assert "host name resolution"
159 (match (marionette-eval
160 '(begin
161 ;; Wait for nscd or our requests go through it.
162 (use-modules (gnu services herd))
163 (start-service 'nscd)
164
165 (list (getaddrinfo "localhost")
166 (getaddrinfo #$(operating-system-host-name os))))
167 marionette)
168 ((((? vector?) ..1) ((? vector?) ..1))
169 #t)
170 (x
171 (pk 'failure x #f))))
172
173 (test-equal "host not found"
174 #f
134 (marionette-eval 175 (marionette-eval
135 '(begin 176 '(false-if-exception (getaddrinfo "does-not-exist"))
136 (use-modules (gnu services herd)) 177 marionette))
137 (start-service 'term-tty1)) 178
138 marionette) 179 (test-assert "screendump"
139 180 (begin
140 ;; Now we can type. 181 (marionette-control (string-append "screendump " #$output
141 (marionette-type "root\n\nid -un > logged-in\n" marionette) 182 "/tty1.ppm")
142 183 marionette)
143 ;; It can take a while before the shell commands are executed. 184 (file-exists? "tty1.ppm")))
144 (let loop ((i 0)) 185
145 (unless (or (file-exists? "/root/logged-in") (> i 15)) 186 (test-end)
146 (sleep 1) 187 (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
147 (loop (+ i 1)))) 188
148 (marionette-eval '(use-modules (rnrs io ports)) marionette) 189 (gexp->derivation name test))
149 (marionette-eval '(call-with-input-file "/root/logged-in"
150 get-string-all)
151 marionette)))
152
153 (test-assert "screendump"
154 (begin
155 (marionette-control (string-append "screendump " #$output
156 "/tty1.ppm")
157 marionette)
158 (file-exists? "tty1.ppm")))
159
160 (test-end)
161 (exit (= (test-runner-fail-count (test-runner-current)) 0))))
162
163 (gexp->derivation name test
164 #:modules '((gnu build marionette))))
165 190
166(define %test-basic-os 191(define %test-basic-os
167 (system-test 192 (system-test
@@ -216,70 +241,207 @@ functionality tests.")
216 (command (system-qemu-image/shared-store-script 241 (command (system-qemu-image/shared-store-script
217 os #:graphic? #f))) 242 os #:graphic? #f)))
218 (define test 243 (define test
219 #~(begin 244 (with-imported-modules '((gnu build marionette))
220 (use-modules (gnu build marionette) 245 #~(begin
221 (srfi srfi-64) 246 (use-modules (gnu build marionette)
222 (ice-9 match)) 247 (srfi srfi-64)
223 248 (ice-9 match))
224 (define marionette 249
225 (make-marionette (list #$command))) 250 (define marionette
226 251 (make-marionette (list #$command)))
227 (define (wait-for-file file) 252
228 ;; Wait until FILE exists in the guest; 'read' its content and 253 (define (wait-for-file file)
229 ;; return it. 254 ;; Wait until FILE exists in the guest; 'read' its content and
230 (marionette-eval 255 ;; return it.
231 `(let loop ((i 10)) 256 (marionette-eval
232 (cond ((file-exists? ,file) 257 `(let loop ((i 10))
233 (call-with-input-file ,file read)) 258 (cond ((file-exists? ,file)
234 ((> i 0) 259 (call-with-input-file ,file read))
235 (sleep 1) 260 ((> i 0)
236 (loop (- i 1))) 261 (sleep 1)
237 (else 262 (loop (- i 1)))
238 (error "file didn't show up" ,file)))) 263 (else
239 marionette)) 264 (error "file didn't show up" ,file))))
240 265 marionette))
241 (mkdir #$output) 266
242 (chdir #$output) 267 (mkdir #$output)
243 268 (chdir #$output)
244 (test-begin "mcron") 269
245 270 (test-begin "mcron")
246 (test-eq "service running" 271
247 'running! 272 (test-eq "service running"
248 (marionette-eval 273 'running!
249 '(begin 274 (marionette-eval
250 (use-modules (gnu services herd)) 275 '(begin
251 (start-service 'mcron) 276 (use-modules (gnu services herd))
252 'running!) 277 (start-service 'mcron)
253 marionette)) 278 'running!)
254 279 marionette))
255 ;; Make sure root's mcron job runs, has its cwd set to "/root", and 280
256 ;; runs with the right UID/GID. 281 ;; Make sure root's mcron job runs, has its cwd set to "/root", and
257 (test-equal "root's job" 282 ;; runs with the right UID/GID.
258 '(0 0) 283 (test-equal "root's job"
259 (wait-for-file "/root/witness")) 284 '(0 0)
260 285 (wait-for-file "/root/witness"))
261 ;; Likewise for Alice's job. We cannot know what its GID is since 286
262 ;; it's chosen by 'groupadd', but it's strictly positive. 287 ;; Likewise for Alice's job. We cannot know what its GID is since
263 (test-assert "alice's job" 288 ;; it's chosen by 'groupadd', but it's strictly positive.
264 (match (wait-for-file "/home/alice/witness") 289 (test-assert "alice's job"
265 ((1000 gid) 290 (match (wait-for-file "/home/alice/witness")
266 (>= gid 100)))) 291 ((1000 gid)
267 292 (>= gid 100))))
268 ;; Last, the job that uses a command; allows us to test whether 293
269 ;; $PATH is sane. (Note that 'marionette-eval' stringifies objects 294 ;; Last, the job that uses a command; allows us to test whether
270 ;; that don't have a read syntax, hence the string.) 295 ;; $PATH is sane. (Note that 'marionette-eval' stringifies objects
271 (test-equal "root's job with command" 296 ;; that don't have a read syntax, hence the string.)
272 "#<eof>" 297 (test-equal "root's job with command"
273 (wait-for-file "/root/witness-touch")) 298 "#<eof>"
274 299 (wait-for-file "/root/witness-touch"))
275 (test-end) 300
276 (exit (= (test-runner-fail-count (test-runner-current)) 0)))) 301 (test-end)
277 302 (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
278 (gexp->derivation name test 303
279 #:modules '((gnu build marionette))))) 304 (gexp->derivation name test)))
280 305
281(define %test-mcron 306(define %test-mcron
282 (system-test 307 (system-test
283 (name "mcron") 308 (name "mcron")
284 (description "Make sure the mcron service works as advertised.") 309 (description "Make sure the mcron service works as advertised.")
285 (value (run-mcron-test name)))) 310 (value (run-mcron-test name))))
311
312
313;;;
314;;; Avahi and NSS-mDNS.
315;;;
316
317(define %avahi-os
318 (operating-system
319 (inherit %simple-os)
320 (name-service-switch %mdns-host-lookup-nss)
321 (services (cons* (avahi-service #:debug? #t)
322 (dbus-service)
323 (dhcp-client-service) ;needed for multicast
324
325 ;; Enable heavyweight debugging output.
326 (modify-services (operating-system-user-services
327 %simple-os)
328 (nscd-service-type config
329 => (nscd-configuration
330 (inherit config)
331 (debug-level 3)
332 (log-file "/dev/console")))
333 (syslog-service-type config
334 =>
335 (plain-file
336 "syslog.conf"
337 "*.* /dev/console\n")))))))
338
339(define (run-nss-mdns-test)
340 ;; Test resolution of '.local' names via libc. Start the marionette service
341 ;; *after* nscd. Failing to do that, libc will try to connect to nscd,
342 ;; fail, then never try again (see '__nss_not_use_nscd_hosts' in libc),
343 ;; leading to '.local' resolution failures.
344 (mlet* %store-monad ((os -> (marionette-operating-system
345 %avahi-os
346 #:requirements '(nscd)
347 #:imported-modules '((gnu services herd)
348 (guix combinators))))
349 (run (system-qemu-image/shared-store-script
350 os #:graphic? #f)))
351 (define mdns-host-name
352 (string-append (operating-system-host-name os)
353 ".local"))
354
355 (define test
356 (with-imported-modules '((gnu build marionette))
357 #~(begin
358 (use-modules (gnu build marionette)
359 (srfi srfi-1)
360 (srfi srfi-64)
361 (ice-9 match))
362
363 (define marionette
364 (make-marionette (list #$run)))
365
366 (mkdir #$output)
367 (chdir #$output)
368
369 (test-begin "avahi")
370
371 (test-assert "wait for services"
372 (marionette-eval
373 '(begin
374 (use-modules (gnu services herd))
375
376 (start-service 'nscd)
377
378 ;; XXX: Work around a race condition in nscd: nscd creates its
379 ;; PID file before it is listening on its socket.
380 (let ((sock (socket PF_UNIX SOCK_STREAM 0)))
381 (let try ()
382 (catch 'system-error
383 (lambda ()
384 (connect sock AF_UNIX "/var/run/nscd/socket")
385 (close-port sock)
386 (format #t "nscd is ready~%"))
387 (lambda args
388 (format #t "waiting for nscd...~%")
389 (usleep 500000)
390 (try)))))
391
392 ;; Wait for the other useful things.
393 (start-service 'avahi-daemon)
394 (start-service 'networking)
395
396 #t)
397 marionette))
398
399 (test-equal "avahi-resolve-host-name"
400 0
401 (marionette-eval
402 '(system*
403 "/run/current-system/profile/bin/avahi-resolve-host-name"
404 "-v" #$mdns-host-name)
405 marionette))
406
407 (test-equal "avahi-browse"
408 0
409 (marionette-eval
410 '(system* "avahi-browse" "-avt")
411 marionette))
412
413 (test-assert "getaddrinfo .local"
414 ;; Wait for the 'avahi-daemon' service and perform a resolution.
415 (match (marionette-eval
416 '(getaddrinfo #$mdns-host-name)
417 marionette)
418 (((? vector? addrinfos) ..1)
419 (pk 'getaddrinfo addrinfos)
420 (and (any (lambda (ai)
421 (= AF_INET (addrinfo:fam ai)))
422 addrinfos)
423 (any (lambda (ai)
424 (= AF_INET6 (addrinfo:fam ai)))
425 addrinfos)))))
426
427 (test-assert "gethostbyname .local"
428 (match (pk 'gethostbyname
429 (marionette-eval '(gethostbyname #$mdns-host-name)
430 marionette))
431 ((? vector? result)
432 (and (string=? (hostent:name result) #$mdns-host-name)
433 (= (hostent:addrtype result) AF_INET)))))
434
435
436 (test-end)
437 (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
438
439 (gexp->derivation "nss-mdns" test)))
440
441(define %test-nss-mdns
442 (system-test
443 (name "nss-mdns")
444 (description
445 "Test Avahi's multicast-DNS implementation, and in particular, test its
446glibc name service switch (NSS) module.")
447 (value (run-nss-mdns-test))))