ui: Gracefully report '&message' conditions.
[jackhill/guix/guix.git] / tests / services.scm
CommitLineData
0adfe95a 1;;; GNU Guix --- Functional package management for GNU
efe7d19a 2;;; Copyright © 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
0adfe95a
LC
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (test-services)
20 #:use-module (gnu services)
7b44cae5 21 #:use-module (gnu services herd)
0190c1c0 22 #:use-module (gnu services shepherd)
0adfe95a
LC
23 #:use-module (srfi srfi-1)
24 #:use-module (srfi srfi-26)
25 #:use-module (srfi srfi-34)
26 #:use-module (srfi srfi-64))
27
7b44cae5
LC
28(define live-service
29 (@@ (gnu services herd) live-service))
30
31\f
0adfe95a
LC
32(test-begin "services")
33
5152d13b
LC
34(test-assert "service-back-edges"
35 (let* ((t1 (service-type (name 't1) (extensions '())
36 (compose +) (extend *)))
37 (t2 (service-type (name 't2)
38 (extensions
39 (list (service-extension t1 (const '()))))
40 (compose +) (extend *)))
41 (t3 (service-type (name 't3)
42 (extensions
43 (list (service-extension t2 identity)
44 (service-extension t1 list)))))
45 (s1 (service t1 #t))
46 (s2 (service t2 #t))
47 (s3 (service t3 #t))
48 (e (service-back-edges (list s1 s2 s3))))
49 (and (lset= eq? (e s1) (list s2 s3))
50 (lset= eq? (e s2) (list s3))
51 (null? (e s3)))))
52
0adfe95a
LC
53(test-equal "fold-services"
54 ;; Make sure 'fold-services' returns the right result. The numbers come
55 ;; from services of type T3; 'xyz 60' comes from the service of type T2,
56 ;; where 60 = 15 × 4 = (1 + 2 + 3 + 4 + 5) × 4.
57 '(initial-value 5 4 3 2 1 xyz 60)
58 (let* ((t1 (service-type (name 't1) (extensions '())
59 (compose concatenate)
60 (extend cons)))
61 (t2 (service-type (name 't2)
62 (extensions
63 (list (service-extension t1
64 (cut list 'xyz <>))))
65 (compose (cut reduce + 0 <>))
66 (extend *)))
67 (t3 (service-type (name 't3)
68 (extensions
69 (list (service-extension t2 identity)
70 (service-extension t1 list)))))
71 (r (fold-services (cons* (service t1 'initial-value)
72 (service t2 4)
73 (map (lambda (x)
74 (service t3 x))
75 (iota 5 1)))
76 #:target-type t1)))
77 (and (eq? (service-kind r) t1)
efe7d19a 78 (service-value r))))
0adfe95a
LC
79
80(test-assert "fold-services, ambiguity"
81 (let* ((t1 (service-type (name 't1) (extensions '())
82 (compose concatenate)
83 (extend cons)))
84 (t2 (service-type (name 't2)
85 (extensions
86 (list (service-extension t1 list)))))
87 (s (service t2 42)))
88 (guard (c ((ambiguous-target-service-error? c)
89 (and (eq? (ambiguous-target-service-error-target-type c)
90 t1)
91 (eq? (ambiguous-target-service-error-service c)
92 s))))
93 (fold-services (list (service t1 'first)
94 (service t1 'second)
95 s)
96 #:target-type t1)
97 #f)))
98
99(test-assert "fold-services, missing target"
100 (let* ((t1 (service-type (name 't1) (extensions '())))
101 (t2 (service-type (name 't2)
102 (extensions
103 (list (service-extension t1 list)))))
104 (s (service t2 42)))
105 (guard (c ((missing-target-service-error? c)
106 (and (eq? (missing-target-service-error-target-type c)
107 t1)
108 (eq? (missing-target-service-error-service c)
109 s))))
110 (fold-services (list s) #:target-type t1)
111 #f)))
112
a5d78eb6
LC
113(test-assert "shepherd-service-lookup-procedure"
114 (let* ((s1 (shepherd-service (provision '(s1 s1b)) (start #f)))
115 (s2 (shepherd-service (provision '(s2 s2b)) (start #f)))
116 (s3 (shepherd-service (provision '(s3 s3b s3c)) (start #f)))
117 (lookup (shepherd-service-lookup-procedure (list s1 s2 s3))))
118 (and (eq? (lookup 's1) (lookup 's1b) s1)
119 (eq? (lookup 's2) (lookup 's2b) s2)
120 (eq? (lookup 's3) (lookup 's3b) s3))))
121
d4053c71
AK
122(test-assert "shepherd-service-back-edges"
123 (let* ((s1 (shepherd-service (provision '(s1)) (start #f)))
124 (s2 (shepherd-service (provision '(s2))
125 (requirement '(s1))
126 (start #f)))
127 (s3 (shepherd-service (provision '(s3))
128 (requirement '(s1 s2))
129 (start #f)))
130 (e (shepherd-service-back-edges (list s1 s2 s3))))
80a67734
LC
131 (and (lset= eq? (e s1) (list s2 s3))
132 (lset= eq? (e s2) (list s3))
133 (null? (e s3)))))
134
7b44cae5
LC
135(test-equal "shepherd-service-upgrade: nothing to do"
136 '(() ())
137 (call-with-values
138 (lambda ()
139 (shepherd-service-upgrade '() '()))
140 list))
141
142(test-equal "shepherd-service-upgrade: one unchanged, one upgraded, one new"
143 '(((bar)) ;unload
144 ((bar) (baz))) ;load
145 (call-with-values
146 (lambda ()
147 ;; Here 'foo' is not upgraded because it is still running, whereas
148 ;; 'bar' is upgraded because it is not currently running. 'baz' is
149 ;; loaded because it's a new service.
150 (shepherd-service-upgrade
151 (list (live-service '(foo) '() #t)
152 (live-service '(bar) '() #f)
153 (live-service '(root) '() #t)) ;essential!
154 (list (shepherd-service (provision '(foo))
155 (start #t))
156 (shepherd-service (provision '(bar))
157 (start #t))
158 (shepherd-service (provision '(baz))
159 (start #t)))))
160 (lambda (unload load)
161 (list (map live-service-provision unload)
162 (map shepherd-service-provision load)))))
163
164(test-equal "shepherd-service-upgrade: service depended on is not unloaded"
165 '(((baz)) ;unload
166 ()) ;load
167 (call-with-values
168 (lambda ()
169 ;; Service 'bar' is not among the target services; yet, it must not be
170 ;; unloaded because 'foo' depends on it.
171 (shepherd-service-upgrade
172 (list (live-service '(foo) '(bar) #t)
173 (live-service '(bar) '() #t) ;still used!
174 (live-service '(baz) '() #t))
175 (list (shepherd-service (provision '(foo))
176 (start #t)))))
177 (lambda (unload load)
178 (list (map live-service-provision unload)
179 (map shepherd-service-provision load)))))
180
181(test-equal "shepherd-service-upgrade: obsolete services that depend on each other"
182 '(((foo) (bar) (baz)) ;unload
183 ((qux))) ;load
184 (call-with-values
185 (lambda ()
186 ;; 'foo', 'bar', and 'baz' depend on each other, but all of them are
187 ;; obsolete, and thus should be unloaded.
188 (shepherd-service-upgrade
189 (list (live-service '(foo) '(bar) #t) ;obsolete
190 (live-service '(bar) '(baz) #t) ;obsolete
191 (live-service '(baz) '() #t)) ;obsolete
192 (list (shepherd-service (provision '(qux))
193 (start #t)))))
194 (lambda (unload load)
195 (list (map live-service-provision unload)
196 (map shepherd-service-provision load)))))
197
0adfe95a 198(test-end)