guix package: Export generation procedures.
[jackhill/guix/guix.git] / tests / utils.scm
CommitLineData
233e7676 1;;; GNU Guix --- Functional package management for GNU
2cd5c038 2;;; Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
516e3b6f 3;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
e3deeebb 4;;;
233e7676 5;;; This file is part of GNU Guix.
e3deeebb 6;;;
233e7676 7;;; GNU Guix is free software; you can redistribute it and/or modify it
e3deeebb
LC
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;;;
233e7676 12;;; GNU Guix is distributed in the hope that it will be useful, but
e3deeebb
LC
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
233e7676 18;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
e3deeebb 19
e3deeebb 20(define-module (test-utils)
e0fbbc88 21 #:use-module ((guix config) #:select (%gzip))
e3deeebb 22 #:use-module (guix utils)
b980f0f9 23 #:use-module ((guix store) #:select (%store-prefix store-path-package-name))
e3deeebb 24 #:use-module (srfi srfi-1)
98090557 25 #:use-module (srfi srfi-11)
e3deeebb 26 #:use-module (srfi srfi-64)
f9c7080a 27 #:use-module (rnrs bytevectors)
e0fbbc88 28 #:use-module (rnrs io ports)
516e3b6f
EB
29 #:use-module (ice-9 match)
30 #:use-module (ice-9 vlist))
e3deeebb 31
827d5563
LC
32(define temp-file
33 (string-append "t-utils-" (number->string (getpid))))
34
e3deeebb
LC
35(test-begin "utils")
36
6d800a80
LC
37(test-assert "bytevector->base16-string->bytevector"
38 (every (lambda (bv)
39 (equal? (base16-string->bytevector
40 (bytevector->base16-string bv))
41 bv))
42 (map string->utf8 '("" "f" "fo" "foo" "foob" "fooba" "foobar"))))
43
98090557
LC
44(test-assert "gnu-triplet->nix-system"
45 (let ((samples '(("i586-gnu0.3" "i686-gnu")
46 ("x86_64-unknown-linux-gnu" "x86_64-linux")
47 ("i386-pc-linux-gnu" "i686-linux")
48 ("x86_64-unknown-freebsd8.2" "x86_64-freebsd")
49 ("x86_64-apple-darwin10.8.0" "x86_64-darwin")
50 ("i686-pc-cygwin" "i686-cygwin"))))
51 (let-values (((gnu nix) (unzip2 samples)))
52 (every (lambda (gnu nix)
53 (equal? nix (gnu-triplet->nix-system gnu)))
54 gnu nix))))
55
9b48fb88
LC
56(test-assert "package-name->name+version"
57 (every (match-lambda
58 ((name version)
59 (let*-values (((full-name)
60 (if version
61 (string-append name "-" version)
62 name))
63 ((name* version*)
64 (package-name->name+version full-name)))
65 (and (equal? name* name)
66 (equal? version* version)))))
67 '(("foo" "0.9.1b")
68 ("foo-bar" "1.0")
69 ("foo-bar2" #f)
70 ("guile" "2.0.6.65-134c9") ; as produced by `git-version-gen'
71 ("nixpkgs" "1.0pre22125_a28fe19")
72 ("gtk2" "2.38.0"))))
73
7db3ff4a
LC
74(test-assert "guile-version>? 1.8"
75 (guile-version>? "1.8"))
76
77(test-assert "guile-version>? 10.5"
78 (not (guile-version>? "10.5")))
79
2bcfb9e0
LC
80(test-equal "string-tokenize*"
81 '(("foo")
82 ("foo" "bar" "baz")
83 ("foo" "bar" "")
84 ("foo" "bar" "baz"))
85 (list (string-tokenize* "foo" ":")
86 (string-tokenize* "foo;bar;baz" ";")
87 (string-tokenize* "foo!bar!" "!")
88 (string-tokenize* "foo+-+bar+-+baz" "+-+")))
89
56b943de
LC
90(test-equal "string-replace-substring"
91 '("foo BAR! baz"
92 "/gnu/store/chbouib"
93 "")
94 (list (string-replace-substring "foo bar baz" "bar" "BAR!")
95 (string-replace-substring "/nix/store/chbouib" "/nix/" "/gnu/")
96 (string-replace-substring "" "foo" "bar")))
97
04fd96ca
LC
98(test-equal "fold2, 1 list"
99 (list (reverse (iota 5))
100 (map - (reverse (iota 5))))
101 (call-with-values
102 (lambda ()
103 (fold2 (lambda (i r1 r2)
104 (values (cons i r1)
105 (cons (- i) r2)))
106 '() '()
107 (iota 5)))
108 list))
109
110(test-equal "fold2, 2 lists"
111 (list (reverse '((a . 0) (b . 1) (c . 2) (d . 3)))
112 (reverse '((a . 0) (b . -1) (c . -2) (d . -3))))
113 (call-with-values
114 (lambda ()
115 (fold2 (lambda (k v r1 r2)
116 (values (alist-cons k v r1)
117 (alist-cons k (- v) r2)))
118 '() '()
119 '(a b c d)
120 '(0 1 2 3)))
121 list))
122
516e3b6f
EB
123(let* ((tree (alist->vhash
124 '((0 2 3) (1 3 4) (2) (3 5 6) (4 6) (5) (6))
125 hashq))
126 (add-one (lambda (_ r) (1+ r)))
127 (tree-lookup (lambda (n) (cdr (vhash-assq n tree)))))
128 (test-equal "fold-tree, single root"
129 5 (fold-tree add-one 0 tree-lookup '(0)))
130 (test-equal "fold-tree, two roots"
131 7 (fold-tree add-one 0 tree-lookup '(0 1)))
132 (test-equal "fold-tree, sum"
133 16 (fold-tree + 0 tree-lookup '(0)))
134 (test-equal "fold-tree, internal"
135 18 (fold-tree + 0 tree-lookup '(3 4)))
136 (test-equal "fold-tree, cons"
137 '(1 3 4 5 6)
138 (sort (fold-tree cons '() tree-lookup '(1)) <))
139 (test-equal "fold-tree, overlapping paths"
140 '(1 3 4 5 6)
141 (sort (fold-tree cons '() tree-lookup '(1 4)) <))
142 (test-equal "fold-tree, cons, two roots"
143 '(0 2 3 4 5 6)
144 (sort (fold-tree cons '() tree-lookup '(0 4)) <))
145 (test-equal "fold-tree-leaves, single root"
146 2 (fold-tree-leaves add-one 0 tree-lookup '(1)))
147 (test-equal "fold-tree-leaves, single root, sum"
148 11 (fold-tree-leaves + 0 tree-lookup '(1)))
149 (test-equal "fold-tree-leaves, two roots"
150 3 (fold-tree-leaves add-one 0 tree-lookup '(0 1)))
151 (test-equal "fold-tree-leaves, two roots, sum"
152 13 (fold-tree-leaves + 0 tree-lookup '(0 1))))
153
e0fbbc88 154(test-assert "filtered-port, file"
101d9f3f 155 (let* ((file (search-path %load-path "guix.scm"))
b6952cad 156 (input (open-file file "r0b")))
101d9f3f
LC
157 (let*-values (((compressed pids1)
158 (filtered-port `(,%gzip "-c" "--fast") input))
159 ((decompressed pids2)
160 (filtered-port `(,%gzip "-d") compressed)))
161 (and (every (compose zero? cdr waitpid)
162 (append pids1 pids2))
163 (equal? (get-bytevector-all decompressed)
164 (call-with-input-file file get-bytevector-all))))))
e0fbbc88
LC
165
166(test-assert "filtered-port, non-file"
167 (let ((data (call-with-input-file (search-path %load-path "guix.scm")
168 get-bytevector-all)))
169 (let*-values (((compressed pids1)
170 (filtered-port `(,%gzip "-c" "--fast")
171 (open-bytevector-input-port data)))
172 ((decompressed pids2)
173 (filtered-port `(,%gzip "-d") compressed)))
174 (and (pk (every (compose zero? cdr waitpid)
175 (append pids1 pids2)))
176 (equal? (get-bytevector-all decompressed) data)))))
177
443eb4e9
LC
178(test-assert "filtered-port, does not exist"
179 (let* ((file (search-path %load-path "guix.scm"))
180 (input (open-file file "r0b")))
181 (let-values (((port pids)
182 (filtered-port '("/does/not/exist") input)))
183 (any (compose (negate zero?) cdr waitpid)
184 pids))))
185
7a8024a3
LC
186(test-assert "compressed-port, decompressed-port, non-file"
187 (let ((data (call-with-input-file (search-path %load-path "guix.scm")
188 get-bytevector-all)))
189 (let*-values (((compressed pids1)
190 (compressed-port 'xz (open-bytevector-input-port data)))
191 ((decompressed pids2)
192 (decompressed-port 'xz compressed)))
193 (and (every (compose zero? cdr waitpid)
194 (append pids1 pids2))
195 (equal? (get-bytevector-all decompressed) data)))))
196
80dea563 197(false-if-exception (delete-file temp-file))
01ac19dc
LC
198(test-assert "compressed-output-port + decompressed-port"
199 (let* ((file (search-path %load-path "guix/derivations.scm"))
30ce8012
LC
200 (data (call-with-input-file file get-bytevector-all))
201 (port (open-file temp-file "w0b")))
202 (call-with-compressed-output-port 'xz port
01ac19dc
LC
203 (lambda (compressed)
204 (put-bytevector compressed data)))
30ce8012 205 (close-port port)
01ac19dc
LC
206
207 (bytevector=? data
208 (call-with-decompressed-port 'xz (open-file temp-file "r0b")
209 get-bytevector-all))))
80dea563 210
827d5563 211(false-if-exception (delete-file temp-file))
c7445833 212(test-equal "fcntl-flock wait"
827d5563 213 42 ; the child's exit status
68ec0450 214 (let ((file (open-file temp-file "w0b")))
827d5563
LC
215 ;; Acquire an exclusive lock.
216 (fcntl-flock file 'write-lock)
2cd5c038
LC
217 (match (primitive-fork)
218 (0
219 (dynamic-wind
220 (const #t)
221 (lambda ()
827d5563 222 ;; Reopen FILE read-only so we can have a read lock.
68ec0450 223 (let ((file (open-file temp-file "r0b")))
827d5563
LC
224 ;; Wait until we can acquire the lock.
225 (fcntl-flock file 'read-lock)
226 (primitive-exit (read file)))
2cd5c038
LC
227 (primitive-exit 1))
228 (lambda ()
229 (primitive-exit 2))))
230 (pid
827d5563
LC
231 ;; Write garbage and wait.
232 (display "hello, world!" file)
233 (force-output file)
234 (sleep 1)
235
236 ;; Write the real answer.
237 (seek file 0 SEEK_SET)
238 (truncate-file file 0)
239 (write 42 file)
240 (force-output file)
241
242 ;; Unlock, which should let the child continue.
243 (fcntl-flock file 'unlock)
244
2cd5c038
LC
245 (match (waitpid pid)
246 ((_ . status)
247 (let ((result (status:exit-val status)))
2cd5c038
LC
248 (close-port file)
249 result)))))))
250
c7445833
LC
251(test-equal "fcntl-flock non-blocking"
252 EAGAIN ; the child's exit status
253 (match (pipe)
254 ((input . output)
255 (match (primitive-fork)
256 (0
257 (dynamic-wind
258 (const #t)
259 (lambda ()
260 (close-port output)
261
262 ;; Wait for the green light.
263 (read-char input)
264
265 ;; Open FILE read-only so we can have a read lock.
68ec0450 266 (let ((file (open-file temp-file "w0")))
c7445833
LC
267 (catch 'flock-error
268 (lambda ()
269 ;; This attempt should throw EAGAIN.
270 (fcntl-flock file 'write-lock #:wait? #f))
271 (lambda (key errno)
68ec0450 272 (primitive-exit (pk 'errno errno)))))
c7445833
LC
273 (primitive-exit -1))
274 (lambda ()
275 (primitive-exit -2))))
276 (pid
277 (close-port input)
68ec0450 278 (let ((file (open-file temp-file "w0")))
c7445833
LC
279 ;; Acquire an exclusive lock.
280 (fcntl-flock file 'write-lock)
281
282 ;; Tell the child to continue.
283 (write 'green-light output)
284 (force-output output)
285
286 (match (waitpid pid)
287 ((_ . status)
288 (let ((result (status:exit-val status)))
289 (fcntl-flock file 'unlock)
290 (close-port file)
291 result)))))))))
292
e3d74106
LC
293;; This is actually in (guix store).
294(test-equal "store-path-package-name"
295 "bash-4.2-p24"
296 (store-path-package-name
b980f0f9
LC
297 (string-append (%store-prefix)
298 "/qvs2rj2ia5vci3wsdb7qvydrmacig4pg-bash-4.2-p24")))
e3d74106 299
e3deeebb
LC
300(test-end)
301
827d5563
LC
302(false-if-exception (delete-file temp-file))
303
e3deeebb
LC
304\f
305(exit (= (test-runner-fail-count (test-runner-current)) 0))