packages: Default origin 'patch-flags' is a gexp.
[jackhill/guix/guix.git] / tests / gexp.scm
CommitLineData
21b679f6 1;;; GNU Guix --- Functional package management for GNU
fc6d6aee 2;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
21b679f6
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-gexp)
20 #:use-module (guix store)
21 #:use-module (guix monads)
22 #:use-module (guix gexp)
ef8de985 23 #:use-module (guix grafts)
21b679f6 24 #:use-module (guix derivations)
79c0c8cd 25 #:use-module (guix packages)
838e17d8 26 #:use-module (guix build-system trivial)
c1bc358f 27 #:use-module (guix tests)
4ff76a0a 28 #:use-module ((guix build utils) #:select (with-directory-excursion))
1ae16033 29 #:use-module ((guix utils) #:select (call-with-temporary-directory))
21b679f6
LC
30 #:use-module (gnu packages)
31 #:use-module (gnu packages base)
32 #:use-module (gnu packages bootstrap)
ca465a9c 33 #:use-module ((guix diagnostics) #:select (guix-warning-port))
21b679f6 34 #:use-module (srfi srfi-1)
c8351d9a 35 #:use-module (srfi srfi-34)
21b679f6
LC
36 #:use-module (srfi srfi-64)
37 #:use-module (rnrs io ports)
38 #:use-module (ice-9 match)
2cf0ea0d 39 #:use-module (ice-9 regex)
0687fc9c
LC
40 #:use-module (ice-9 popen)
41 #:use-module (ice-9 ftw))
21b679f6
LC
42
43;; Test the (guix gexp) module.
44
45(define %store
c1bc358f 46 (open-connection-for-tests))
21b679f6 47
ef8de985
LC
48;; Globally disable grafts because they can trigger early builds.
49(%graft? #f)
50
21b679f6 51;; For white-box testing.
1f976033
LC
52(define (gexp-inputs x)
53 ((@@ (guix gexp) gexp-inputs) x))
1f976033
LC
54(define (gexp-outputs x)
55 ((@@ (guix gexp) gexp-outputs) x))
56(define (gexp->sexp . x)
57 (apply (@@ (guix gexp) gexp->sexp) x))
21b679f6 58
667b2508 59(define* (gexp->sexp* exp #:optional target)
b57de6fe 60 (run-with-store %store (gexp->sexp exp (%current-system) target)
c1bc358f 61 #:guile-for-build (%guile-for-build)))
21b679f6 62
fc6d6aee 63(define (gexp-input->tuple input)
4fa9d48f
LC
64 (list (gexp-input-thing input) (gexp-input-output input)
65 (gexp-input-native? input)))
fc6d6aee 66
838e17d8
LC
67(define %extension-package
68 ;; Example of a package to use when testing 'with-extensions'.
69 (dummy-package "extension"
70 (build-system trivial-build-system)
71 (arguments
72 `(#:guile ,%bootstrap-guile
73 #:modules ((guix build utils))
74 #:builder
75 (begin
76 (use-modules (guix build utils))
77 (let* ((out (string-append (assoc-ref %outputs "out")
78 "/share/guile/site/"
79 (effective-version))))
80 (mkdir-p out)
81 (call-with-output-file (string-append out "/hg2g.scm")
82 (lambda (port)
e033700f
LC
83 (define defmod 'define-module) ;fool Geiser
84 (write `(,defmod (hg2g)
838e17d8
LC
85 #:export (the-answer))
86 port)
87 (write '(define the-answer 42) port)))))))))
88
21b679f6
LC
89\f
90(test-begin "gexp")
91
92(test-equal "no refs"
93 '(display "hello!")
94 (let ((exp (gexp (display "hello!"))))
95 (and (gexp? exp)
96 (null? (gexp-inputs exp))
97 (gexp->sexp* exp))))
98
99(test-equal "unquote"
100 '(display `(foo ,(+ 2 3)))
101 (let ((exp (gexp (display `(foo ,(+ 2 3))))))
102 (and (gexp? exp)
103 (null? (gexp-inputs exp))
104 (gexp->sexp* exp))))
105
106(test-assert "one input package"
107 (let ((exp (gexp (display (ungexp coreutils)))))
108 (and (gexp? exp)
109 (match (gexp-inputs exp)
fc6d6aee
LC
110 ((input)
111 (eq? (gexp-input-thing input) coreutils)))
21b679f6
LC
112 (equal? `(display ,(derivation->output-path
113 (package-derivation %store coreutils)))
114 (gexp->sexp* exp)))))
5e2e4a51
LC
115
116(test-assert "one input package, dotted list"
117 (let ((exp (gexp (coreutils . (ungexp coreutils)))))
118 (and (gexp? exp)
119 (match (gexp-inputs exp)
fc6d6aee
LC
120 ((input)
121 (eq? (gexp-input-thing input) coreutils)))
5e2e4a51
LC
122 (equal? `(coreutils . ,(derivation->output-path
123 (package-derivation %store coreutils)))
124 (gexp->sexp* exp)))))
21b679f6 125
79c0c8cd
LC
126(test-assert "one input origin"
127 (let ((exp (gexp (display (ungexp (package-source coreutils))))))
128 (and (gexp? exp)
129 (match (gexp-inputs exp)
fc6d6aee
LC
130 ((input)
131 (and (eq? (gexp-input-thing input) (package-source coreutils))
132 (string=? (gexp-input-output input) "out"))))
79c0c8cd
LC
133 (equal? `(display ,(derivation->output-path
134 (package-source-derivation
135 %store (package-source coreutils))))
136 (gexp->sexp* exp)))))
137
d9ae938f
LC
138(test-assert "one local file"
139 (let* ((file (search-path %load-path "guix.scm"))
140 (local (local-file file))
141 (exp (gexp (display (ungexp local))))
020f3e41 142 (intd (add-to-store %store (basename file) #f
d9ae938f
LC
143 "sha256" file)))
144 (and (gexp? exp)
145 (match (gexp-inputs exp)
fc6d6aee
LC
146 ((input)
147 (and (eq? (gexp-input-thing input) local)
148 (string=? (gexp-input-output input) "out"))))
d9ae938f
LC
149 (equal? `(display ,intd) (gexp->sexp* exp)))))
150
7833db1f
LC
151(test-assert "one local file, symlink"
152 (let ((file (search-path %load-path "guix.scm"))
153 (link (tmpnam)))
154 (dynamic-wind
155 (const #t)
156 (lambda ()
157 (symlink (canonicalize-path file) link)
158 (let* ((local (local-file link "my-file" #:recursive? #f))
159 (exp (gexp (display (ungexp local))))
160 (intd (add-to-store %store "my-file" #f
161 "sha256" file)))
162 (and (gexp? exp)
163 (match (gexp-inputs exp)
fc6d6aee
LC
164 ((input)
165 (and (eq? (gexp-input-thing input) local)
166 (string=? (gexp-input-output input) "out"))))
7833db1f
LC
167 (equal? `(display ,intd) (gexp->sexp* exp)))))
168 (lambda ()
169 (false-if-exception (delete-file link))))))
170
4ff76a0a
LC
171(test-equal "local-file, relative file name"
172 (canonicalize-path (search-path %load-path "guix/base32.scm"))
173 (let ((directory (dirname (search-path %load-path
174 "guix/build-system/gnu.scm"))))
175 (with-directory-excursion directory
176 (let ((file (local-file "../guix/base32.scm")))
177 (local-file-absolute-file-name file)))))
178
99c45877
LC
179(test-equal "local-file, non-literal relative file name"
180 (canonicalize-path (search-path %load-path "guix/base32.scm"))
181 (let ((directory (dirname (search-path %load-path
182 "guix/build-system/gnu.scm"))))
183 (with-directory-excursion directory
184 (let ((file (local-file (string-copy "../base32.scm"))))
185 (local-file-absolute-file-name file)))))
186
0687fc9c
LC
187(test-assertm "local-file, #:select?"
188 (mlet* %store-monad ((select? -> (lambda (file stat)
189 (member (basename file)
190 '("guix.scm" "tests"
191 "gexp.scm"))))
192 (file -> (local-file ".." "directory"
193 #:recursive? #t
194 #:select? select?))
195 (dir (lower-object file)))
196 (return (and (store-path? dir)
197 (equal? (scandir dir)
198 '("." ".." "guix.scm" "tests"))
199 (equal? (scandir (string-append dir "/tests"))
200 '("." ".." "gexp.scm"))))))
201
558e8b11
LC
202(test-assert "one plain file"
203 (let* ((file (plain-file "hi" "Hello, world!"))
204 (exp (gexp (display (ungexp file))))
205 (expected (add-text-to-store %store "hi" "Hello, world!")))
206 (and (gexp? exp)
207 (match (gexp-inputs exp)
fc6d6aee
LC
208 ((input)
209 (and (eq? (gexp-input-thing input) file)
210 (string=? (gexp-input-output input) "out"))))
558e8b11
LC
211 (equal? `(display ,expected) (gexp->sexp* exp)))))
212
21b679f6
LC
213(test-assert "same input twice"
214 (let ((exp (gexp (begin
215 (display (ungexp coreutils))
216 (display (ungexp coreutils))))))
217 (and (gexp? exp)
218 (match (gexp-inputs exp)
fc6d6aee
LC
219 ((input)
220 (and (eq? (gexp-input-thing input) coreutils)
221 (string=? (gexp-input-output input) "out"))))
21b679f6
LC
222 (let ((e `(display ,(derivation->output-path
223 (package-derivation %store coreutils)))))
224 (equal? `(begin ,e ,e) (gexp->sexp* exp))))))
225
226(test-assert "two input packages, one derivation, one file"
227 (let* ((drv (build-expression->derivation
228 %store "foo" 'bar
229 #:guile-for-build (package-derivation %store %bootstrap-guile)))
230 (txt (add-text-to-store %store "foo" "Hello, world!"))
231 (exp (gexp (begin
232 (display (ungexp coreutils))
233 (display (ungexp %bootstrap-guile))
234 (display (ungexp drv))
235 (display (ungexp txt))))))
236 (define (match-input thing)
fc6d6aee
LC
237 (lambda (input)
238 (eq? (gexp-input-thing input) thing)))
21b679f6
LC
239
240 (and (gexp? exp)
241 (= 4 (length (gexp-inputs exp)))
242 (every (lambda (input)
243 (find (match-input input) (gexp-inputs exp)))
244 (list drv coreutils %bootstrap-guile txt))
245 (let ((e0 `(display ,(derivation->output-path
246 (package-derivation %store coreutils))))
247 (e1 `(display ,(derivation->output-path
248 (package-derivation %store %bootstrap-guile))))
249 (e2 `(display ,(derivation->output-path drv)))
250 (e3 `(display ,txt)))
251 (equal? `(begin ,e0 ,e1 ,e2 ,e3) (gexp->sexp* exp))))))
252
a9e5e92f
LC
253(test-assert "file-append"
254 (let* ((drv (package-derivation %store %bootstrap-guile))
255 (fa (file-append %bootstrap-guile "/bin/guile"))
256 (exp #~(here we go #$fa)))
257 (and (match (gexp->sexp* exp)
258 (('here 'we 'go (? string? result))
259 (string=? result
260 (string-append (derivation->output-path drv)
261 "/bin/guile"))))
262 (match (gexp-inputs exp)
fc6d6aee
LC
263 ((input)
264 (and (eq? (gexp-input-thing input) fa)
265 (string=? (gexp-input-output input) "out")))))))
a9e5e92f
LC
266
267(test-assert "file-append, output"
268 (let* ((drv (package-derivation %store glibc))
269 (fa (file-append glibc "/lib" "/debug"))
270 (exp #~(foo #$fa:debug)))
271 (and (match (gexp->sexp* exp)
272 (('foo (? string? result))
273 (string=? result
274 (string-append (derivation->output-path drv "debug")
275 "/lib/debug"))))
276 (match (gexp-inputs exp)
fc6d6aee
LC
277 ((input)
278 (and (eq? (gexp-input-thing input) fa)
279 (string=? (gexp-input-output input) "debug")))))))
a9e5e92f
LC
280
281(test-assert "file-append, nested"
282 (let* ((drv (package-derivation %store glibc))
283 (dir (file-append glibc "/bin"))
284 (slash (file-append dir "/"))
285 (file (file-append slash "getent"))
286 (exp #~(foo #$file)))
287 (and (match (gexp->sexp* exp)
288 (('foo (? string? result))
289 (string=? result
290 (string-append (derivation->output-path drv)
291 "/bin/getent"))))
292 (match (gexp-inputs exp)
fc6d6aee
LC
293 ((input)
294 (eq? (gexp-input-thing input) file))))))
a9e5e92f 295
abf43d45
LC
296(test-assert "file-append, raw store item"
297 (let* ((obj (plain-file "example.txt" "Hello!"))
298 (a (file-append obj "/a"))
299 (b (file-append a "/b"))
300 (c (file-append b "/c"))
301 (exp #~(list #$c))
302 (item (run-with-store %store (lower-object obj)))
303 (lexp (run-with-store %store (lower-gexp exp))))
304 (and (equal? (lowered-gexp-sexp lexp)
305 `(list ,(string-append item "/a/b/c")))
306 (equal? (lowered-gexp-sources lexp)
307 (list item))
308 (null? (lowered-gexp-inputs lexp)))))
309
cf2ac04f
LC
310(test-assertm "with-parameters for %current-system"
311 (mlet* %store-monad ((system -> (match (%current-system)
312 ("aarch64-linux" "x86_64-linux")
313 (_ "aarch64-linux")))
314 (drv (package->derivation coreutils system))
315 (obj -> (with-parameters ((%current-system system))
316 coreutils))
317 (result (lower-object obj)))
318 (return (string=? (derivation-file-name drv)
319 (derivation-file-name result)))))
320
321(test-assertm "with-parameters for %current-target-system"
322 (mlet* %store-monad ((target -> "riscv64-linux-gnu")
323 (drv (package->cross-derivation coreutils target))
324 (obj -> (with-parameters
325 ((%current-target-system target))
326 coreutils))
327 (result (lower-object obj)))
328 (return (string=? (derivation-file-name drv)
329 (derivation-file-name result)))))
330
331(test-assert "with-parameters + file-append"
332 (let* ((system (match (%current-system)
333 ("aarch64-linux" "x86_64-linux")
334 (_ "aarch64-linux")))
335 (drv (package-derivation %store coreutils system))
336 (param (make-parameter 7))
337 (exp #~(here we go #$(with-parameters ((%current-system system)
338 (param 42))
339 (if (= (param) 42)
340 (file-append coreutils "/bin/touch")
341 %bootstrap-guile)))))
342 (match (gexp->sexp* exp)
343 (('here 'we 'go (? string? result))
344 (string=? result
345 (string-append (derivation->output-path drv)
346 "/bin/touch"))))))
644cb40c 347(test-equal "let-system"
4fa9d48f 348 (list `(begin ,(%current-system) #t) '(system-binding)
644cb40c
LC
349 'low '() '())
350 (let* ((exp #~(begin
351 #$(let-system system system)
352 #t))
353 (low (run-with-store %store (lower-gexp exp))))
354 (list (lowered-gexp-sexp low)
355 (match (gexp-inputs exp)
fc6d6aee
LC
356 ((input)
357 (and (eq? (struct-vtable (gexp-input-thing input))
358 (@@ (guix gexp) <system-binding>))
359 (string=? (gexp-input-output input) "out")
360 '(system-binding)))
644cb40c 361 (x x))
644cb40c
LC
362 'low
363 (lowered-gexp-inputs low)
364 (lowered-gexp-sources low))))
365
366(test-equal "let-system, target"
367 (list `(list ,(%current-system) #f)
368 `(list ,(%current-system) "aarch64-linux-gnu"))
369 (let ((exp #~(list #$@(let-system (system target)
370 (list system target)))))
371 (list (gexp->sexp* exp)
372 (gexp->sexp* exp "aarch64-linux-gnu"))))
373
374(test-equal "let-system, ungexp-native, target"
375 `(here it is: ,(%current-system) #f)
376 (let ((exp #~(here it is: #+@(let-system (system target)
377 (list system target)))))
378 (gexp->sexp* exp "aarch64-linux-gnu")))
379
380(test-equal "let-system, nested"
381 (list `(system* ,(string-append "qemu-system-" (%current-system))
382 "-m" "256")
644cb40c
LC
383 '(system-binding))
384 (let ((exp #~(system*
385 #+(let-system (system target)
386 (file-append (@@ (gnu packages virtualization)
387 qemu)
388 "/bin/qemu-system-"
389 system))
390 "-m" "256")))
391 (list (match (gexp->sexp* exp)
392 (('system* command rest ...)
393 `(system* ,(and (string-prefix? (%store-prefix) command)
394 (basename command))
395 ,@rest))
396 (x x))
4fa9d48f 397 (match (gexp-inputs exp)
fc6d6aee
LC
398 ((input)
399 (and (eq? (struct-vtable (gexp-input-thing input))
400 (@@ (guix gexp) <system-binding>))
401 (string=? (gexp-input-output input) "out")
4fa9d48f 402 (gexp-input-native? input)
fc6d6aee 403 '(system-binding)))
644cb40c 404 (x x)))))
cf2ac04f 405
667b2508
LC
406(test-assert "ungexp + ungexp-native"
407 (let* ((exp (gexp (list (ungexp-native %bootstrap-guile)
408 (ungexp coreutils)
409 (ungexp-native glibc)
410 (ungexp binutils))))
411 (target "mips64el-linux")
412 (guile (derivation->output-path
413 (package-derivation %store %bootstrap-guile)))
414 (cu (derivation->output-path
415 (package-cross-derivation %store coreutils target)))
416 (libc (derivation->output-path
417 (package-derivation %store glibc)))
418 (bu (derivation->output-path
419 (package-cross-derivation %store binutils target))))
420 (and (lset= equal?
4fa9d48f
LC
421 `((,%bootstrap-guile "out" #t)
422 (,coreutils "out" #f)
423 (,glibc "out" #t)
424 (,binutils "out" #f))
fc6d6aee 425 (map gexp-input->tuple (gexp-inputs exp)))
667b2508
LC
426 (equal? `(list ,guile ,cu ,libc ,bu)
427 (gexp->sexp* exp target)))))
428
1123759b 429(test-equal "ungexp + ungexp-native, nested"
4fa9d48f 430 `((,%bootstrap-guile "out" #f) (,coreutils "out" #t))
1123759b
LC
431 (let* ((exp (gexp (list (ungexp-native (gexp (ungexp coreutils)))
432 (ungexp %bootstrap-guile)))))
4fa9d48f 433 (map gexp-input->tuple (gexp-inputs exp))))
1123759b 434
5b14a790 435(test-equal "ungexp + ungexp-native, nested, special mixture"
4fa9d48f 436 `((,coreutils "out" #t))
5b14a790 437
5b14a790
LC
438 (let* ((foo (gexp (foo (ungexp-native coreutils))))
439 (exp (gexp (bar (ungexp foo)))))
4fa9d48f 440 (map gexp-input->tuple (gexp-inputs exp))))
5b14a790 441
21b679f6
LC
442(test-assert "input list"
443 (let ((exp (gexp (display
444 '(ungexp (list %bootstrap-guile coreutils)))))
445 (guile (derivation->output-path
446 (package-derivation %store %bootstrap-guile)))
447 (cu (derivation->output-path
448 (package-derivation %store coreutils))))
449 (and (lset= equal?
4fa9d48f 450 `((,%bootstrap-guile "out" #f) (,coreutils "out" #f))
fc6d6aee 451 (map gexp-input->tuple (gexp-inputs exp)))
21b679f6
LC
452 (equal? `(display '(,guile ,cu))
453 (gexp->sexp* exp)))))
454
667b2508
LC
455(test-assert "input list + ungexp-native"
456 (let* ((target "mips64el-linux")
457 (exp (gexp (display
458 (cons '(ungexp-native (list %bootstrap-guile coreutils))
459 '(ungexp (list glibc binutils))))))
460 (guile (derivation->output-path
461 (package-derivation %store %bootstrap-guile)))
462 (cu (derivation->output-path
463 (package-derivation %store coreutils)))
464 (xlibc (derivation->output-path
465 (package-cross-derivation %store glibc target)))
466 (xbu (derivation->output-path
467 (package-cross-derivation %store binutils target))))
468 (and (lset= equal?
4fa9d48f
LC
469 `((,%bootstrap-guile "out" #t) (,coreutils "out" #t)
470 (,glibc "out" #f) (,binutils "out" #f))
fc6d6aee 471 (map gexp-input->tuple (gexp-inputs exp)))
667b2508
LC
472 (equal? `(display (cons '(,guile ,cu) '(,xlibc ,xbu)))
473 (gexp->sexp* exp target)))))
474
21b679f6 475(test-assert "input list splicing"
a482cfdc 476 (let* ((inputs (list (gexp-input glibc "debug") %bootstrap-guile))
21b679f6
LC
477 (outputs (list (derivation->output-path
478 (package-derivation %store glibc)
479 "debug")
480 (derivation->output-path
481 (package-derivation %store %bootstrap-guile))))
482 (exp (gexp (list (ungexp-splicing (cons (+ 2 3) inputs))))))
483 (and (lset= equal?
4fa9d48f 484 `((,glibc "debug" #f) (,%bootstrap-guile "out" #f))
fc6d6aee 485 (map gexp-input->tuple (gexp-inputs exp)))
21b679f6
LC
486 (equal? (gexp->sexp* exp)
487 `(list ,@(cons 5 outputs))))))
488
667b2508 489(test-assert "input list splicing + ungexp-native-splicing"
5b14a790
LC
490 (let* ((inputs (list (gexp-input glibc "debug" #:native? #t)
491 %bootstrap-guile))
0dbea56b
LC
492 (exp (gexp (list (ungexp-native-splicing (cons (+ 2 3) inputs))))))
493 (and (lset= equal?
4fa9d48f
LC
494 `((,glibc "debug" #t) (,%bootstrap-guile "out" #t))
495 (map gexp-input->tuple (gexp-inputs exp)))
0dbea56b
LC
496 (equal? (gexp->sexp* exp) ;native
497 (gexp->sexp* exp "mips64el-linux")))))
498
578dfbe0
LC
499(test-assert "gexp list splicing + ungexp-splicing"
500 (let* ((inner (gexp (ungexp-native glibc)))
501 (exp (gexp (list (ungexp-splicing (list inner))))))
4fa9d48f
LC
502 (and (equal? `((,glibc "out" #t))
503 (map gexp-input->tuple (gexp-inputs exp)))
578dfbe0
LC
504 (equal? (gexp->sexp* exp) ;native
505 (gexp->sexp* exp "mips64el-linux")))))
506
4b23c466
LC
507(test-equal "output list"
508 2
509 (let ((exp (gexp (begin (mkdir (ungexp output))
510 (mkdir (ungexp output "bar"))))))
511 (length (gexp-outputs exp)))) ;XXX: <output-ref> is private
512
513(test-assert "output list, combined gexps"
514 (let* ((exp0 (gexp (mkdir (ungexp output))))
515 (exp1 (gexp (mkdir (ungexp output "foo"))))
516 (exp2 (gexp (begin (display "hi!") (ungexp exp0) (ungexp exp1)))))
517 (and (lset= equal?
518 (append (gexp-outputs exp0) (gexp-outputs exp1))
519 (gexp-outputs exp2))
520 (= 2 (length (gexp-outputs exp2))))))
521
7e75a673
LC
522(test-equal "output list, combined gexps, duplicate output"
523 1
524 (let* ((exp0 (gexp (mkdir (ungexp output))))
525 (exp1 (gexp (begin (mkdir (ungexp output)) (ungexp exp0))))
526 (exp2 (gexp (begin (mkdir (ungexp output)) (ungexp exp1)))))
527 (length (gexp-outputs exp2))))
528
f9efe568
LC
529(test-assert "output list + ungexp-splicing list, combined gexps"
530 (let* ((exp0 (gexp (mkdir (ungexp output))))
531 (exp1 (gexp (mkdir (ungexp output "foo"))))
532 (exp2 (gexp (begin (display "hi!")
533 (ungexp-splicing (list exp0 exp1))))))
534 (and (lset= equal?
535 (append (gexp-outputs exp0) (gexp-outputs exp1))
536 (gexp-outputs exp2))
537 (= 2 (length (gexp-outputs exp2))))))
538
21b679f6
LC
539(test-assertm "gexp->file"
540 (mlet* %store-monad ((exp -> (gexp (display (ungexp %bootstrap-guile))))
541 (guile (package-file %bootstrap-guile))
b57de6fe 542 (sexp (gexp->sexp exp (%current-system) #f))
21b679f6
LC
543 (drv (gexp->file "foo" exp))
544 (out -> (derivation->output-path drv))
545 (done (built-derivations (list drv)))
e74f64b9 546 (refs (references* out)))
21b679f6
LC
547 (return (and (equal? sexp (call-with-input-file out read))
548 (equal? (list guile) refs)))))
549
a9e5e92f
LC
550(test-assertm "gexp->file + file-append"
551 (mlet* %store-monad ((exp -> #~#$(file-append %bootstrap-guile
552 "/bin/guile"))
553 (guile (package-file %bootstrap-guile))
554 (drv (gexp->file "foo" exp))
555 (out -> (derivation->output-path drv))
556 (done (built-derivations (list drv)))
e74f64b9 557 (refs (references* out)))
a9e5e92f
LC
558 (return (and (equal? (string-append guile "/bin/guile")
559 (call-with-input-file out read))
560 (equal? (list guile) refs)))))
561
4fbd1a2b
LC
562(test-assertm "gexp->file + #:splice?"
563 (mlet* %store-monad ((exp -> (list
564 #~(define foo 'bar)
565 #~(define guile #$%bootstrap-guile)))
566 (guile (package-file %bootstrap-guile))
567 (drv (gexp->file "splice" exp #:splice? #t))
568 (out -> (derivation->output-path drv))
569 (done (built-derivations (list drv)))
570 (refs (references* out)))
571 (pk 'splice out)
572 (return (and (equal? `((define foo 'bar)
573 (define guile ,guile)
574 ,(call-with-input-string "" read))
575 (call-with-input-file out
576 (lambda (port)
577 (list (read port) (read port) (read port)))))
578 (equal? (list guile) refs)))))
579
21b679f6
LC
580(test-assertm "gexp->derivation"
581 (mlet* %store-monad ((file (text-file "foo" "Hello, world!"))
582 (exp -> (gexp
583 (begin
584 (mkdir (ungexp output))
585 (chdir (ungexp output))
586 (symlink
587 (string-append (ungexp %bootstrap-guile)
588 "/bin/guile")
589 "foo")
590 (symlink (ungexp file)
591 (ungexp output "2nd")))))
592 (drv (gexp->derivation "foo" exp))
593 (out -> (derivation->output-path drv))
594 (out2 -> (derivation->output-path drv "2nd"))
595 (done (built-derivations (list drv)))
e74f64b9
LC
596 (refs (references* out))
597 (refs2 (references* out2))
21b679f6
LC
598 (guile (package-file %bootstrap-guile "bin/guile")))
599 (return (and (string=? (readlink (string-append out "/foo")) guile)
600 (string=? (readlink out2) file)
601 (equal? refs (list (dirname (dirname guile))))
8856f409
LC
602 (equal? refs2 (list file))
603 (null? (derivation-properties drv))))))
604
605(test-assertm "gexp->derivation properties"
606 (mlet %store-monad ((drv (gexp->derivation "foo"
607 #~(mkdir #$output)
608 #:properties '((type . test)))))
609 (return (equal? '((type . test))
610 (derivation-properties drv)))))
21b679f6 611
ce45eb4c 612(test-assertm "gexp->derivation vs. grafts"
ef8de985
LC
613 (mlet* %store-monad ((graft? (set-grafting #f))
614 (p0 -> (dummy-package "dummy"
ce45eb4c
LC
615 (arguments
616 '(#:implicit-inputs? #f))))
617 (r -> (package (inherit p0) (name "DuMMY")))
618 (p1 -> (package (inherit p0) (replacement r)))
619 (exp0 -> (gexp (frob (ungexp p0) (ungexp output))))
620 (exp1 -> (gexp (frob (ungexp p1) (ungexp output))))
621 (void (set-guile-for-build %bootstrap-guile))
ef8de985
LC
622 (drv0 (gexp->derivation "t" exp0 #:graft? #t))
623 (drv1 (gexp->derivation "t" exp1 #:graft? #t))
624 (drv1* (gexp->derivation "t" exp1 #:graft? #f))
625 (_ (set-grafting graft?)))
ce45eb4c
LC
626 (return (and (not (string=? (derivation->output-path drv0)
627 (derivation->output-path drv1)))
628 (string=? (derivation->output-path drv0)
629 (derivation->output-path drv1*))))))
630
21b679f6
LC
631(test-assertm "gexp->derivation, composed gexps"
632 (mlet* %store-monad ((exp0 -> (gexp (begin
633 (mkdir (ungexp output))
634 (chdir (ungexp output)))))
635 (exp1 -> (gexp (symlink
636 (string-append (ungexp %bootstrap-guile)
637 "/bin/guile")
638 "foo")))
639 (exp -> (gexp (begin (ungexp exp0) (ungexp exp1))))
640 (drv (gexp->derivation "foo" exp))
641 (out -> (derivation->output-path drv))
642 (done (built-derivations (list drv)))
643 (guile (package-file %bootstrap-guile "bin/guile")))
644 (return (string=? (readlink (string-append out "/foo"))
645 guile))))
646
5d098459
LC
647(test-assertm "gexp->derivation, default system"
648 ;; The default system should be the one at '>>=' time, not the one at
649 ;; invocation time. See <http://bugs.gnu.org/18002>.
650 (let ((system (%current-system))
651 (mdrv (parameterize ((%current-system "foobar64-linux"))
652 (gexp->derivation "foo"
653 (gexp
654 (mkdir (ungexp output)))))))
655 (mlet %store-monad ((drv mdrv))
656 (return (string=? system (derivation-system drv))))))
657
d9ae938f
LC
658(test-assertm "gexp->derivation, local-file"
659 (mlet* %store-monad ((file -> (search-path %load-path "guix.scm"))
020f3e41 660 (intd (interned-file file #:recursive? #f))
d9ae938f
LC
661 (local -> (local-file file))
662 (exp -> (gexp (begin
663 (stat (ungexp local))
664 (symlink (ungexp local)
665 (ungexp output)))))
666 (drv (gexp->derivation "local-file" exp)))
667 (mbegin %store-monad
668 (built-derivations (list drv))
669 (return (string=? (readlink (derivation->output-path drv))
670 intd)))))
671
68a61e9f
LC
672(test-assertm "gexp->derivation, cross-compilation"
673 (mlet* %store-monad ((target -> "mips64el-linux")
674 (exp -> (gexp (list (ungexp coreutils)
675 (ungexp output))))
676 (xdrv (gexp->derivation "foo" exp
677 #:target target))
e74f64b9 678 (refs (references*
68a61e9f
LC
679 (derivation-file-name xdrv)))
680 (xcu (package->cross-derivation coreutils
681 target))
682 (cu (package->derivation coreutils)))
683 (return (and (member (derivation-file-name xcu) refs)
684 (not (member (derivation-file-name cu) refs))))))
685
667b2508
LC
686(test-assertm "gexp->derivation, ungexp-native"
687 (mlet* %store-monad ((target -> "mips64el-linux")
688 (exp -> (gexp (list (ungexp-native coreutils)
689 (ungexp output))))
690 (xdrv (gexp->derivation "foo" exp
691 #:target target))
692 (drv (gexp->derivation "foo" exp)))
693 (return (string=? (derivation-file-name drv)
694 (derivation-file-name xdrv)))))
695
696(test-assertm "gexp->derivation, ungexp + ungexp-native"
697 (mlet* %store-monad ((target -> "mips64el-linux")
698 (exp -> (gexp (list (ungexp-native coreutils)
699 (ungexp glibc)
700 (ungexp output))))
701 (xdrv (gexp->derivation "foo" exp
702 #:target target))
e74f64b9 703 (refs (references*
667b2508
LC
704 (derivation-file-name xdrv)))
705 (xglibc (package->cross-derivation glibc target))
706 (cu (package->derivation coreutils)))
707 (return (and (member (derivation-file-name cu) refs)
708 (member (derivation-file-name xglibc) refs)))))
709
710(test-assertm "gexp->derivation, ungexp-native + composed gexps"
711 (mlet* %store-monad ((target -> "mips64el-linux")
712 (exp0 -> (gexp (list 1 2
713 (ungexp coreutils))))
714 (exp -> (gexp (list 0 (ungexp-native exp0))))
715 (xdrv (gexp->derivation "foo" exp
716 #:target target))
717 (drv (gexp->derivation "foo" exp)))
718 (return (string=? (derivation-file-name drv)
719 (derivation-file-name xdrv)))))
720
6fd1a796
LC
721(test-assertm "gexp->derivation, store copy"
722 (let ((build-one #~(call-with-output-file #$output
723 (lambda (port)
724 (display "This is the one." port))))
725 (build-two (lambda (one)
726 #~(begin
727 (mkdir #$output)
728 (symlink #$one (string-append #$output "/one"))
729 (call-with-output-file (string-append #$output "/two")
730 (lambda (port)
731 (display "This is the second one." port))))))
b53833b2 732 (build-drv #~(begin
7b8d239e
LC
733 (use-modules (guix build store-copy)
734 (guix build utils)
735 (srfi srfi-1))
736
737 (define (canonical-file? file)
738 ;; Copied from (guix tests).
739 (let ((st (lstat file)))
740 (or (not (string-prefix? (%store-directory) file))
741 (eq? 'symlink (stat:type st))
742 (and (= 1 (stat:mtime st))
743 (zero? (logand #o222 (stat:mode st)))))))
6fd1a796 744
b53833b2 745 (mkdir #$output)
6a060ff2
LC
746 (populate-store '("graph") #$output
747 #:deduplicate? #f)
7b8d239e
LC
748
749 ;; Check whether 'populate-store' canonicalizes
750 ;; permissions and timestamps.
751 (unless (every canonical-file? (find-files #$output))
752 (error "not canonical!" #$output)))))
6fd1a796
LC
753 (mlet* %store-monad ((one (gexp->derivation "one" build-one))
754 (two (gexp->derivation "two" (build-two one)))
b53833b2 755 (drv (gexp->derivation "store-copy" build-drv
6fd1a796 756 #:references-graphs
b53833b2 757 `(("graph" ,two))
6fd1a796
LC
758 #:modules
759 '((guix build store-copy)
d4e9317b
LC
760 (guix progress)
761 (guix records)
6892f0a2 762 (guix sets)
6fd1a796
LC
763 (guix build utils))))
764 (ok? (built-derivations (list drv)))
765 (out -> (derivation->output-path drv)))
766 (let ((one (derivation->output-path one))
767 (two (derivation->output-path two)))
768 (return (and ok?
769 (file-exists? (string-append out "/" one))
770 (file-exists? (string-append out "/" two))
771 (file-exists? (string-append out "/" two "/two"))
772 (string=? (readlink (string-append out "/" two "/one"))
773 one)))))))
774
aa72d9af
LC
775(test-assertm "imported-files"
776 (mlet* %store-monad
777 ((files -> `(("x" . ,(search-path %load-path "ice-9/q.scm"))
778 ("a/b/c" . ,(search-path %load-path
779 "guix/derivations.scm"))
780 ("p/q" . ,(search-path %load-path "guix.scm"))
781 ("p/z" . ,(search-path %load-path "guix/store.scm"))))
8df2eca6 782 (dir (imported-files files)))
aa72d9af 783 (mbegin %store-monad
8df2eca6
LC
784 (return
785 (every (match-lambda
786 ((path . source)
787 (equal? (call-with-input-file (string-append dir "/" path)
788 get-bytevector-all)
789 (call-with-input-file source
790 get-bytevector-all))))
791 files)))))
aa72d9af 792
d938a58b
LC
793(test-assertm "imported-files with file-like objects"
794 (mlet* %store-monad ((plain -> (plain-file "foo" "bar!"))
795 (q-scm -> (search-path %load-path "ice-9/q.scm"))
796 (files -> `(("a/b/c" . ,q-scm)
797 ("p/q" . ,plain)))
798 (drv (imported-files files)))
e529d468
LC
799 (define (file=? file1 file2)
800 ;; Assume deduplication is in place.
8c7bebd6
LC
801 (= (stat:ino (stat file1))
802 (stat:ino (stat file2))))
e529d468 803
d938a58b 804 (mbegin %store-monad
8c7bebd6 805 (built-derivations (list (pk 'drv drv)))
d938a58b
LC
806 (mlet %store-monad ((dir -> (derivation->output-path drv))
807 (plain* (text-file "foo" "bar!"))
808 (q-scm* (interned-file q-scm "c")))
809 (return
e529d468
LC
810 (and (file=? (string-append dir "/a/b/c") q-scm*)
811 (file=? (string-append dir "/p/q") plain*)))))))
d938a58b 812
0bb9929e
LC
813(test-equal "gexp-modules & ungexp"
814 '((bar) (foo))
815 ((@@ (guix gexp) gexp-modules)
816 #~(foo #$(with-imported-modules '((foo)) #~+)
817 #+(with-imported-modules '((bar)) #~-))))
818
819(test-equal "gexp-modules & ungexp-splicing"
820 '((foo) (bar))
821 ((@@ (guix gexp) gexp-modules)
822 #~(foo #$@(list (with-imported-modules '((foo)) #~+)
823 (with-imported-modules '((bar)) #~-)))))
824
932d1600
LC
825(test-assert "gexp-modules deletes duplicates" ;<https://bugs.gnu.org/32966>
826 (let ((make-file (lambda ()
827 ;; Use 'eval' to make sure we get an object that's not
828 ;; 'eq?' nor 'equal?' due to the closures it embeds.
829 (eval '(scheme-file "bar.scm" #~(define-module (bar)))
830 (current-module)))))
831 (define result
832 ((@@ (guix gexp) gexp-modules)
833 (with-imported-modules `(((bar) => ,(make-file))
834 ((bar) => ,(make-file))
835 (foo) (foo))
836 #~+)))
837
838 (match result
839 (((('bar) '=> (? scheme-file?)) ('foo)) #t))))
840
2363bdd7
LC
841(test-equal "gexp-modules and literal Scheme object"
842 '()
843 (gexp-modules #t))
844
ca465a9c
LC
845(test-assert "gexp-modules, warning"
846 (string-match "tests/gexp.scm:[0-9]+:[0-9]+: warning: \
847importing.* \\(guix config\\) from the host"
848 (call-with-output-string
849 (lambda (port)
850 (parameterize ((guix-warning-port port))
851 (let* ((x (with-imported-modules '((guix config))
852 #~(+ 1 2 3)))
853 (y #~(+ 39 #$x)))
854 (gexp-modules y)))))))
855
aa72d9af
LC
856(test-assertm "gexp->derivation #:modules"
857 (mlet* %store-monad
858 ((build -> #~(begin
859 (use-modules (guix build utils))
860 (mkdir-p (string-append #$output "/guile/guix/nix"))
861 #t))
862 (drv (gexp->derivation "test-with-modules" build
863 #:modules '((guix build utils)))))
864 (mbegin %store-monad
865 (built-derivations (list drv))
866 (let* ((p (derivation->output-path drv))
867 (s (stat (string-append p "/guile/guix/nix"))))
868 (return (eq? (stat:type s) 'directory))))))
869
0bb9929e
LC
870(test-assertm "gexp->derivation & with-imported-modules"
871 ;; Same test as above, but using 'with-imported-modules'.
872 (mlet* %store-monad
873 ((build -> (with-imported-modules '((guix build utils))
874 #~(begin
875 (use-modules (guix build utils))
876 (mkdir-p (string-append #$output "/guile/guix/nix"))
877 #t)))
878 (drv (gexp->derivation "test-with-modules" build)))
879 (mbegin %store-monad
880 (built-derivations (list drv))
881 (let* ((p (derivation->output-path drv))
882 (s (stat (string-append p "/guile/guix/nix"))))
883 (return (eq? (stat:type s) 'directory))))))
884
885(test-assertm "gexp->derivation & nested with-imported-modules"
886 (mlet* %store-monad
887 ((build1 -> (with-imported-modules '((guix build utils))
888 #~(begin
889 (use-modules (guix build utils))
890 (mkdir-p (string-append #$output "/guile/guix/nix"))
891 #t)))
892 (build2 -> (with-imported-modules '((guix build bournish))
893 #~(begin
894 (use-modules (guix build bournish)
895 (system base compile))
896 #+build1
897 (call-with-output-file (string-append #$output "/b")
898 (lambda (port)
899 (write
900 (read-and-compile (open-input-string "cd /foo")
901 #:from %bournish-language
902 #:to 'scheme)
903 port))))))
904 (drv (gexp->derivation "test-with-modules" build2)))
905 (mbegin %store-monad
906 (built-derivations (list drv))
907 (let* ((p (derivation->output-path drv))
908 (s (stat (string-append p "/guile/guix/nix")))
909 (b (string-append p "/b")))
910 (return (and (eq? (stat:type s) 'directory)
911 (equal? '(chdir "/foo")
912 (call-with-input-file b read))))))))
913
d938a58b
LC
914(test-assertm "gexp->derivation & with-imported-module & computed module"
915 (mlet* %store-monad
4fbd1a2b 916 ((module -> (scheme-file "x" #~(;; splice!
d938a58b
LC
917 (define-module (foo bar)
918 #:export (the-answer))
919
4fbd1a2b
LC
920 (define the-answer 42))
921 #:splice? #t))
d938a58b
LC
922 (build -> (with-imported-modules `(((foo bar) => ,module)
923 (guix build utils))
924 #~(begin
925 (use-modules (guix build utils)
926 (foo bar))
927 mkdir-p
928 (call-with-output-file #$output
929 (lambda (port)
930 (write the-answer port))))))
931 (drv (gexp->derivation "thing" build))
932 (out -> (derivation->output-path drv)))
933 (mbegin %store-monad
934 (built-derivations (list drv))
935 (return (= 42 (call-with-input-file out read))))))
936
838e17d8
LC
937(test-equal "gexp-extensions & ungexp"
938 (list sed grep)
939 ((@@ (guix gexp) gexp-extensions)
940 #~(foo #$(with-extensions (list grep) #~+)
941 #+(with-extensions (list sed) #~-))))
942
943(test-equal "gexp-extensions & ungexp-splicing"
944 (list grep sed)
945 ((@@ (guix gexp) gexp-extensions)
946 #~(foo #$@(list (with-extensions (list grep) #~+)
947 (with-imported-modules '((foo))
948 (with-extensions (list sed) #~-))))))
949
950(test-equal "gexp-extensions and literal Scheme object"
951 '()
952 ((@@ (guix gexp) gexp-extensions) #t))
953
954(test-assertm "gexp->derivation & with-extensions"
955 ;; Create a fake Guile extension and make sure it is accessible both to the
956 ;; imported modules and to the derivation build script.
957 (mlet* %store-monad
958 ((extension -> %extension-package)
959 (module -> (scheme-file "x" #~( ;; splice!
960 (define-module (foo)
961 #:use-module (hg2g)
962 #:export (multiply))
963
964 (define (multiply x)
965 (* the-answer x)))
966 #:splice? #t))
967 (build -> (with-extensions (list extension)
968 (with-imported-modules `((guix build utils)
969 ((foo) => ,module))
970 #~(begin
971 (use-modules (guix build utils)
972 (hg2g) (foo))
973 (call-with-output-file #$output
974 (lambda (port)
975 (write (list the-answer (multiply 2))
976 port)))))))
977 (drv (gexp->derivation "thingie" build
978 ;; %BOOTSTRAP-GUILE is 2.0.
979 #:effective-version "2.0"))
980 (out -> (derivation->output-path drv)))
981 (mbegin %store-monad
982 (built-derivations (list drv))
983 (return (equal? '(42 84) (call-with-input-file out read))))))
984
2ca41030
LC
985(test-assertm "lower-gexp"
986 (mlet* %store-monad
987 ((extension -> %extension-package)
988 (extension-drv (package->derivation %extension-package))
989 (coreutils-drv (package->derivation coreutils))
990 (exp -> (with-extensions (list extension)
991 (with-imported-modules `((guix build utils))
992 #~(begin
993 (use-modules (guix build utils)
994 (hg2g))
995 #$coreutils:debug
996 mkdir-p
997 the-answer))))
998 (lexp (lower-gexp exp
999 #:effective-version "2.0")))
1000 (define (matching-input drv output)
1001 (lambda (input)
38685774
LC
1002 (and (eq? (derivation-input-derivation input) drv)
1003 (equal? (derivation-input-sub-derivations input)
1004 (list output)))))
2ca41030
LC
1005
1006 (mbegin %store-monad
1007 (return (and (find (matching-input extension-drv "out")
1008 (lowered-gexp-inputs (pk 'lexp lexp)))
1009 (find (matching-input coreutils-drv "debug")
1010 (lowered-gexp-inputs lexp))
1011 (member (string-append
1012 (derivation->output-path extension-drv)
1013 "/share/guile/site/2.0")
1014 (lowered-gexp-load-path lexp))
1015 (= 2 (length (lowered-gexp-load-path lexp)))
1016 (member (string-append
1017 (derivation->output-path extension-drv)
1018 "/lib/guile/2.0/site-ccache")
1019 (lowered-gexp-load-compiled-path lexp))
1020 (= 2 (length (lowered-gexp-load-compiled-path lexp)))
b9373e26
LC
1021 (eq? (derivation-input-derivation (lowered-gexp-guile lexp))
1022 (%guile-for-build)))))))
2ca41030 1023
d63ee94d
LC
1024(test-assertm "lower-gexp, raw-derivation-file"
1025 (mlet* %store-monad ((thing -> (program-file "prog" #~(display "hi!")))
1026 (exp -> #~(list #$(raw-derivation-file thing)))
1027 (drv (lower-object thing))
1028 (lexp (lower-gexp exp #:effective-version "2.0")))
1029 (return (and (equal? `(list ,(derivation-file-name drv))
1030 (lowered-gexp-sexp lexp))
1031 (equal? (list (derivation-file-name drv))
1032 (lowered-gexp-sources lexp))
1033 (null? (lowered-gexp-inputs lexp))))))
1034
24ab804c
LC
1035(test-eq "lower-gexp, non-self-quoting input"
1036 +
1037 (guard (c ((gexp-input-error? c)
1038 (gexp-error-invalid-input c)))
1039 (run-with-store %store
1040 (lower-gexp #~(foo #$+)))))
1041
ab7010af
MB
1042(test-equal "lower-gexp, character literal"
1043 '(#\+)
1044 (lowered-gexp-sexp
1045 (run-with-store %store
1046 (lower-gexp #~(#\+)))))
1047
b53833b2
LC
1048(test-assertm "gexp->derivation #:references-graphs"
1049 (mlet* %store-monad
72cd8ec0 1050 ((one (text-file "one" (random-text)))
b53833b2
LC
1051 (two (gexp->derivation "two"
1052 #~(symlink #$one #$output:chbouib)))
66a35ceb 1053 (build -> (with-imported-modules '((guix build store-copy)
d4e9317b
LC
1054 (guix progress)
1055 (guix records)
6892f0a2 1056 (guix sets)
66a35ceb
LC
1057 (guix build utils))
1058 #~(begin
1059 (use-modules (guix build store-copy))
1060 (with-output-to-file #$output
1061 (lambda ()
6892f0a2
LC
1062 (write (map store-info-item
1063 (call-with-input-file "guile"
1064 read-reference-graph)))))
66a35ceb
LC
1065 (with-output-to-file #$output:one
1066 (lambda ()
6892f0a2
LC
1067 (write (map store-info-item
1068 (call-with-input-file "one"
1069 read-reference-graph)))))
66a35ceb
LC
1070 (with-output-to-file #$output:two
1071 (lambda ()
6892f0a2
LC
1072 (write (map store-info-item
1073 (call-with-input-file "two"
1074 read-reference-graph))))))))
66a35ceb 1075 (drv (gexp->derivation "ref-graphs" build
b53833b2
LC
1076 #:references-graphs `(("one" ,one)
1077 ("two" ,two "chbouib")
66a35ceb 1078 ("guile" ,%bootstrap-guile))))
b53833b2
LC
1079 (ok? (built-derivations (list drv)))
1080 (guile-drv (package->derivation %bootstrap-guile))
686784d0
LC
1081 (bash (interned-file (search-bootstrap-binary "bash"
1082 (%current-system))
1083 "bash" #:recursive? #t))
b53833b2
LC
1084 (g-one -> (derivation->output-path drv "one"))
1085 (g-two -> (derivation->output-path drv "two"))
1086 (g-guile -> (derivation->output-path drv)))
1087 (return (and ok?
1088 (equal? (call-with-input-file g-one read) (list one))
72cd8ec0
LC
1089 (lset= string=?
1090 (call-with-input-file g-two read)
1091 (list one (derivation->output-path two "chbouib")))
686784d0
LC
1092
1093 ;; Note: %BOOTSTRAP-GUILE depends on the bootstrap Bash.
72cd8ec0
LC
1094 (lset= string=?
1095 (call-with-input-file g-guile read)
1096 (list (derivation->output-path guile-drv) bash))))))
b53833b2 1097
9fc4e949
LC
1098(test-assertm "gexp->derivation #:references-graphs cross-compilation"
1099 ;; The objects passed in #:references-graphs implicitly refer to
1100 ;; cross-compiled derivations. Make sure this is the case.
1101 (mlet* %store-monad ((drv1 (lower-object coreutils (%current-system)
1102 #:target "i586-pc-gnu"))
1103 (drv2 (lower-object coreutils (%current-system)
1104 #:target #f))
1105 (drv3 (gexp->derivation "three"
1106 #~(symlink #$coreutils #$output)
1107 #:target "i586-pc-gnu"
1108 #:references-graphs
1109 `(("coreutils" ,coreutils))))
1110 (refs (references* (derivation-file-name drv3))))
1111 (return (and (member (derivation-file-name drv1) refs)
1112 (not (member (derivation-file-name drv2) refs))))))
1113
c8351d9a
LC
1114(test-assertm "gexp->derivation #:allowed-references"
1115 (mlet %store-monad ((drv (gexp->derivation "allowed-refs"
1116 #~(begin
1117 (mkdir #$output)
1118 (chdir #$output)
1119 (symlink #$output "self")
1120 (symlink #$%bootstrap-guile
1121 "guile"))
1122 #:allowed-references
1123 (list "out" %bootstrap-guile))))
1124 (built-derivations (list drv))))
1125
accb682c
LC
1126(test-assertm "gexp->derivation #:allowed-references, specific output"
1127 (mlet* %store-monad ((in (gexp->derivation "thing"
1128 #~(begin
1129 (mkdir #$output:ok)
1130 (mkdir #$output:not-ok))))
1131 (drv (gexp->derivation "allowed-refs"
1132 #~(begin
1133 (pk #$in:not-ok)
1134 (mkdir #$output)
1135 (chdir #$output)
1136 (symlink #$output "self")
1137 (symlink #$in:ok "ok"))
1138 #:allowed-references
1139 (list "out"
1140 (gexp-input in "ok")))))
1141 (built-derivations (list drv))))
1142
c8351d9a
LC
1143(test-assert "gexp->derivation #:allowed-references, disallowed"
1144 (let ((drv (run-with-store %store
1145 (gexp->derivation "allowed-refs"
1146 #~(begin
1147 (mkdir #$output)
1148 (chdir #$output)
1149 (symlink #$%bootstrap-guile "guile"))
1150 #:allowed-references '()))))
f9e8a123 1151 (guard (c ((store-protocol-error? c) #t))
c8351d9a
LC
1152 (build-derivations %store (list drv))
1153 #f)))
1154
3f4ecf32
LC
1155(test-assertm "gexp->derivation #:disallowed-references, allowed"
1156 (mlet %store-monad ((drv (gexp->derivation "disallowed-refs"
1157 #~(begin
1158 (mkdir #$output)
1159 (chdir #$output)
1160 (symlink #$output "self")
1161 (symlink #$%bootstrap-guile
1162 "guile"))
1163 #:disallowed-references '())))
1164 (built-derivations (list drv))))
1165
1166
1167(test-assert "gexp->derivation #:disallowed-references"
1168 (let ((drv (run-with-store %store
1169 (gexp->derivation "disallowed-refs"
1170 #~(begin
1171 (mkdir #$output)
1172 (chdir #$output)
1173 (symlink #$%bootstrap-guile "guile"))
1174 #:disallowed-references (list %bootstrap-guile)))))
f9e8a123 1175 (guard (c ((store-protocol-error? c) #t))
3f4ecf32
LC
1176 (build-derivations %store (list drv))
1177 #f)))
1178
c17b5ab4 1179(define shebang
c1bc358f 1180 (string-append "#!" (derivation->output-path (%guile-for-build))
c17b5ab4
LC
1181 "/bin/guile --no-auto-compile"))
1182
1183;; If we're going to hit the silly shebang limit (128 chars on Linux-based
1184;; systems), then skip the following test.
47b3124a 1185(test-skip (if (> (string-length shebang) 127) 2 0))
c17b5ab4 1186
21b679f6
LC
1187(test-assertm "gexp->script"
1188 (mlet* %store-monad ((n -> (random (expt 2 50)))
1189 (exp -> (gexp
1190 (system*
1191 (string-append (ungexp %bootstrap-guile)
1192 "/bin/guile")
1193 "-c" (object->string
1194 '(display (expt (ungexp n) 2))))))
1195 (drv (gexp->script "guile-thing" exp
1196 #:guile %bootstrap-guile))
1197 (out -> (derivation->output-path drv))
1198 (done (built-derivations (list drv))))
1199 (let* ((pipe (open-input-pipe out))
1200 (str (get-string-all pipe)))
1201 (return (and (zero? (close-pipe pipe))
1202 (= (expt n 2) (string->number str)))))))
1203
92bcccc5 1204(test-assert "gexp->script #:module-path"
1ae16033
LC
1205 (call-with-temporary-directory
1206 (lambda (directory)
1207 (define str
1208 "Fake (guix base32) module!")
1209
1210 (mkdir (string-append directory "/guix"))
1211 (call-with-output-file (string-append directory "/guix/base32.scm")
1212 (lambda (port)
1213 (write `(begin (define-module (guix base32))
1214 (define-public %fake! ,str))
1215 port)))
1216
92bcccc5
LF
1217 (run-with-store %store
1218 (mlet* %store-monad ((exp -> (with-imported-modules '((guix base32))
1219 (gexp (begin
1220 (use-modules (guix base32))
1221 (write (list %load-path
1222 %fake!))))))
1223 (drv (gexp->script "guile-thing" exp
1224 #:guile %bootstrap-guile
1225 #:module-path (list directory)))
1226 (out -> (derivation->output-path drv))
1227 (done (built-derivations (list drv))))
1228 (let* ((pipe (open-input-pipe out))
1229 (data (read pipe)))
1230 (return (and (zero? (close-pipe pipe))
1231 (match data
1232 ((load-path str*)
1233 (and (string=? str* str)
1234 (not (member directory load-path)))))))))))))
1ae16033 1235
15a01c72
LC
1236(test-assertm "program-file"
1237 (let* ((n (random (expt 2 50)))
0bb9929e
LC
1238 (exp (with-imported-modules '((guix build utils))
1239 (gexp (begin
1240 (use-modules (guix build utils))
1241 (display (ungexp n))))))
15a01c72 1242 (file (program-file "program" exp
15a01c72
LC
1243 #:guile %bootstrap-guile)))
1244 (mlet* %store-monad ((drv (lower-object file))
1245 (out -> (derivation->output-path drv)))
1246 (mbegin %store-monad
1247 (built-derivations (list drv))
1248 (let* ((pipe (open-input-pipe out))
1249 (str (get-string-all pipe)))
1250 (return (and (zero? (close-pipe pipe))
1251 (= n (string->number str)))))))))
1252
92bcccc5 1253(test-assert "program-file #:module-path"
427ec19e
LC
1254 (call-with-temporary-directory
1255 (lambda (directory)
1256 (define text (random-text))
1257
1258 (call-with-output-file (string-append directory "/stupid-module.scm")
1259 (lambda (port)
1260 (write `(begin (define-module (stupid-module))
1261 (define-public %stupid-thing ,text))
1262 port)))
1263
1264 (let* ((exp (with-imported-modules '((stupid-module))
1265 (gexp (begin
1266 (use-modules (stupid-module))
1267 (display %stupid-thing)))))
1268 (file (program-file "program" exp
1269 #:guile %bootstrap-guile
1270 #:module-path (list directory))))
92bcccc5
LF
1271 (run-with-store %store
1272 (mlet* %store-monad ((drv (lower-object file))
1273 (out -> (derivation->output-path drv)))
1274 (mbegin %store-monad
1275 (built-derivations (list drv))
1276 (let* ((pipe (open-input-pipe out))
1277 (str (get-string-all pipe)))
1278 (return (and (zero? (close-pipe pipe))
1279 (string=? text str)))))))))))
427ec19e 1280
838e17d8
LC
1281(test-assertm "program-file & with-extensions"
1282 (let* ((exp (with-extensions (list %extension-package)
1283 (gexp (begin
1284 (use-modules (hg2g))
1285 (display the-answer)))))
1286 (file (program-file "program" exp
1287 #:guile %bootstrap-guile)))
1288 (mlet* %store-monad ((drv (lower-object file))
1289 (out -> (derivation->output-path drv)))
1290 (mbegin %store-monad
1291 (built-derivations (list drv))
1292 (let* ((pipe (open-input-pipe out))
1293 (str (get-string-all pipe)))
1294 (return (and (zero? (close-pipe pipe))
1295 (= 42 (string->number str)))))))))
1296
2e8cabb8
LC
1297(test-assertm "program-file #:system"
1298 (let* ((exp (with-imported-modules '((guix build utils))
1299 (gexp (begin
1300 (use-modules (guix build utils))
1301 (display "hi!")))))
1302 (system (if (string=? (%current-system) "x86_64-linux")
1303 "armhf-linux"
1304 "x86_64-linux"))
1305 (file (program-file "program" exp)))
1306 (mlet %store-monad ((drv (lower-object file system)))
1307 (return (and (string=? (derivation-system drv) system)
1308 (find (lambda (input)
1309 (let ((drv (pk (derivation-input-derivation input))))
1310 (and (string=? (derivation-name drv)
1311 "module-import-compiled")
1312 (string=? (derivation-system drv)
1313 system))))
1314 (derivation-inputs drv)))))))
1315
e1c153e0
LC
1316(test-assertm "scheme-file"
1317 (let* ((text (plain-file "foo" "Hello, world!"))
1318 (scheme (scheme-file "bar" #~(list "foo" #$text))))
1319 (mlet* %store-monad ((drv (lower-object scheme))
1320 (text (lower-object text))
1321 (out -> (derivation->output-path drv)))
1322 (mbegin %store-monad
1323 (built-derivations (list drv))
e74f64b9 1324 (mlet %store-monad ((refs (references* out)))
e1c153e0
LC
1325 (return (and (equal? refs (list text))
1326 (equal? `(list "foo" ,text)
1327 (call-with-input-file out read)))))))))
1328
d63ee94d
LC
1329(test-assertm "raw-derivation-file"
1330 (let* ((exp #~(let ((drv #$(raw-derivation-file coreutils)))
1331 (when (file-exists? drv)
1332 (symlink drv #$output)))))
1333 (mlet* %store-monad ((dep (lower-object coreutils))
1334 (drv (gexp->derivation "drv-ref" exp))
1335 (out -> (derivation->output-path drv)))
1336 (mbegin %store-monad
1337 (built-derivations (list drv))
1338 (mlet %store-monad ((refs (references* out)))
1339 (return (and (member (derivation-file-name dep)
1340 (derivation-sources drv))
1341 (not (member (derivation-file-name dep)
1342 (map derivation-input-path
1343 (derivation-inputs drv))))
1344 (equal? (readlink out) (derivation-file-name dep))
1345 (equal? refs (list (derivation-file-name dep))))))))))
1346
462a3fa3 1347(test-assert "text-file*"
e74f64b9
LC
1348 (run-with-store %store
1349 (mlet* %store-monad
1350 ((drv (package->derivation %bootstrap-guile))
1351 (guile -> (derivation->output-path drv))
1352 (file (text-file "bar" "This is bar."))
1353 (text (text-file* "foo"
1354 %bootstrap-guile "/bin/guile "
1355 (gexp-input %bootstrap-guile "out") "/bin/guile "
1356 drv "/bin/guile "
1357 file))
1358 (done (built-derivations (list text)))
1359 (out -> (derivation->output-path text))
1360 (refs (references* out)))
1361 ;; Make sure we get the right references and the right content.
1362 (return (and (lset= string=? refs (list guile file))
1363 (equal? (call-with-input-file out get-string-all)
1364 (string-append guile "/bin/guile "
1365 guile "/bin/guile "
1366 guile "/bin/guile "
1367 file)))))
1368 #:guile-for-build (package-derivation %store %bootstrap-guile)))
462a3fa3 1369
b751cde3
LC
1370(test-assertm "mixed-text-file"
1371 (mlet* %store-monad ((file -> (mixed-text-file "mixed"
1372 "export PATH="
1373 %bootstrap-guile "/bin"))
1374 (drv (lower-object file))
1375 (out -> (derivation->output-path drv))
1376 (guile-drv (package->derivation %bootstrap-guile))
1377 (guile -> (derivation->output-path guile-drv)))
1378 (mbegin %store-monad
1379 (built-derivations (list drv))
e74f64b9 1380 (mlet %store-monad ((refs (references* out)))
b751cde3
LC
1381 (return (and (string=? (string-append "export PATH=" guile "/bin")
1382 (call-with-input-file out get-string-all))
1383 (equal? refs (list guile))))))))
1384
5dec93bb
LC
1385(test-assertm "file-union"
1386 (mlet* %store-monad ((union -> (file-union "union"
1387 `(("a" ,(plain-file "a" "1"))
1388 ("b/c/d" ,(plain-file "d" "2"))
1389 ("e" ,(plain-file "e" "3")))))
1390 (drv (lower-object union))
1391 (out -> (derivation->output-path drv)))
1392 (define (contents=? file str)
1393 (string=? (call-with-input-file (string-append out "/" file)
1394 get-string-all)
1395 str))
1396
1397 (mbegin %store-monad
1398 (built-derivations (list drv))
1399 (return (and (contents=? "a" "1")
1400 (contents=? "b/c/d" "2")
1401 (contents=? "e" "3"))))))
1402
a8afb9ae
LC
1403(test-assert "gexp->derivation vs. %current-target-system"
1404 (let ((mval (gexp->derivation "foo"
1405 #~(begin
1406 (mkdir #$output)
1407 (foo #+gnu-make))
1408 #:target #f)))
1409 ;; The value of %CURRENT-TARGET-SYSTEM at bind-time should have no
1410 ;; influence.
1411 (parameterize ((%current-target-system "fooooo"))
1412 (derivation? (run-with-store %store mval)))))
1413
c2b84676
LC
1414(test-assertm "lower-object"
1415 (mlet %store-monad ((drv1 (lower-object %bootstrap-guile))
1416 (drv2 (lower-object (package-source coreutils)))
1417 (item (lower-object (plain-file "foo" "Hello!"))))
1418 (return (and (derivation? drv1) (derivation? drv2)
1419 (store-path? item)))))
1420
91937029
LC
1421(test-assertm "lower-object, computed-file"
1422 (let* ((text (plain-file "foo" "Hello!"))
1423 (exp #~(begin
1424 (mkdir #$output)
1425 (symlink #$%bootstrap-guile
1426 (string-append #$output "/guile"))
1427 (symlink #$text (string-append #$output "/text"))))
1428 (computed (computed-file "computed" exp)))
1429 (mlet* %store-monad ((text (lower-object text))
1430 (guile-drv (lower-object %bootstrap-guile))
1431 (comp-drv (lower-object computed))
1432 (comp -> (derivation->output-path comp-drv)))
1433 (mbegin %store-monad
1434 (built-derivations (list comp-drv))
1435 (return (and (string=? (readlink (string-append comp "/guile"))
1436 (derivation->output-path guile-drv))
1437 (string=? (readlink (string-append comp "/text"))
1438 text)))))))
1439
9ec154f5
LC
1440(test-equal "lower-object, computed-file, #:system"
1441 '("mips64el-linux")
1442 (run-with-store %store
1443 (let* ((exp #~(symlink #$coreutils #$output))
1444 (computed (computed-file "computed" exp
1445 #:guile %bootstrap-guile)))
1446 ;; Make sure that the SYSTEM argument to 'lower-object' is honored.
1447 (mlet* %store-monad ((drv (lower-object computed "mips64el-linux"))
1448 (refs (references* (derivation-file-name drv))))
1449 (return (delete-duplicates
1450 (filter-map (lambda (file)
1451 (and (string-suffix? ".drv" file)
1452 (let ((drv (read-derivation-from-file
1453 file)))
1454 (derivation-system drv))))
1455 (cons (derivation-file-name drv)
1456 refs))))))))
1457
3e43166f
LC
1458(test-assert "lower-object & gexp-input-error?"
1459 (guard (c ((gexp-input-error? c)
1460 (gexp-error-invalid-input c)))
1461 (run-with-store %store
1462 (lower-object (current-module))
1463 #:guile-for-build (%guile-for-build))))
1464
2cf0ea0d
LC
1465(test-assert "printer"
1466 (string-match "^#<gexp \\(string-append .*#<package coreutils.*\
18fc84bc 1467 \"/bin/uname\"\\) [[:graph:]]+tests/gexp\\.scm:[0-9]+:[0-9]+ [[:xdigit:]]+>$"
2cf0ea0d
LC
1468 (with-output-to-string
1469 (lambda ()
1470 (write
1471 (gexp (string-append (ungexp coreutils)
1472 "/bin/uname")))))))
1473
1474(test-assert "printer vs. ungexp-splicing"
1475 (string-match "^#<gexp .* [[:xdigit:]]+>$"
1476 (with-output-to-string
1477 (lambda ()
1478 ;; #~(begin #$@#~())
1479 (write
1480 (gexp (begin (ungexp-splicing (gexp ())))))))))
1481
21b679f6
LC
1482(test-equal "sugar"
1483 '(gexp (foo (ungexp bar) (ungexp baz "out")
1484 (ungexp (chbouib 42))
667b2508
LC
1485 (ungexp-splicing (list x y z))
1486 (ungexp-native foo) (ungexp-native foo "out")
1487 (ungexp-native (chbouib 42))
1488 (ungexp-native-splicing (list x y z))))
1489 '#~(foo #$bar #$baz:out #$(chbouib 42) #$@(list x y z)
1490 #+foo #+foo:out #+(chbouib 42) #+@(list x y z)))
21b679f6 1491
9a2f99f4
MO
1492(test-assertm "gexp->file, cross-compilation"
1493 (mlet* %store-monad ((target -> "aarch64-linux-gnu")
1494 (exp -> (gexp (list (ungexp coreutils))))
1495 (xdrv (gexp->file "foo" exp #:target target))
1496 (refs (references*
1497 (derivation-file-name xdrv)))
1498 (xcu (package->cross-derivation coreutils
1499 target))
1500 (cu (package->derivation coreutils)))
1501 (return (and (member (derivation-file-name xcu) refs)
1502 (not (member (derivation-file-name cu) refs))))))
1503
1504(test-assertm "gexp->file, cross-compilation with default target"
1505 (mlet* %store-monad ((target -> "aarch64-linux-gnu")
1506 (_ (set-current-target target))
1507 (exp -> (gexp (list (ungexp coreutils))))
1508 (xdrv (gexp->file "foo" exp))
1509 (refs (references*
1510 (derivation-file-name xdrv)))
1511 (xcu (package->cross-derivation coreutils
1512 target))
1513 (cu (package->derivation coreutils)))
1514 (return (and (member (derivation-file-name xcu) refs)
1515 (not (member (derivation-file-name cu) refs))))))
1516
1517(test-assertm "gexp->script, cross-compilation"
1518 (mlet* %store-monad ((target -> "aarch64-linux-gnu")
1519 (exp -> (gexp (list (ungexp coreutils))))
1520 (xdrv (gexp->script "foo" exp #:target target))
1521 (refs (references*
1522 (derivation-file-name xdrv)))
1523 (xcu (package->cross-derivation coreutils
1524 target))
1525 (cu (package->derivation coreutils)))
1526 (return (and (member (derivation-file-name xcu) refs)
1527 (not (member (derivation-file-name cu) refs))))))
1528
1529(test-assertm "gexp->script, cross-compilation with default target"
1530 (mlet* %store-monad ((target -> "aarch64-linux-gnu")
1531 (_ (set-current-target target))
1532 (exp -> (gexp (list (ungexp coreutils))))
1533 (xdrv (gexp->script "foo" exp))
1534 (refs (references*
1535 (derivation-file-name xdrv)))
1536 (xcu (package->cross-derivation coreutils
1537 target))
1538 (cu (package->derivation coreutils)))
1539 (return (and (member (derivation-file-name xcu) refs)
1540 (not (member (derivation-file-name cu) refs))))))
1541
21b679f6
LC
1542(test-end "gexp")
1543
21b679f6
LC
1544;; Local Variables:
1545;; eval: (put 'test-assertm 'scheme-indent-function 1)
1546;; End: