derivations.scm 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
  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. (unsetenv "http_proxy")
  19. (define-module (test-derivations)
  20. #:use-module (guix derivations)
  21. #:use-module (guix grafts)
  22. #:use-module (guix store)
  23. #:use-module (guix utils)
  24. #:use-module (guix hash)
  25. #:use-module (guix base32)
  26. #:use-module (guix tests)
  27. #:use-module (guix tests http)
  28. #:use-module ((guix packages) #:select (package-derivation base32))
  29. #:use-module ((guix build utils) #:select (executable-file?))
  30. #:use-module ((gnu packages) #:select (search-bootstrap-binary))
  31. #:use-module (gnu packages bootstrap)
  32. #:use-module ((gnu packages guile) #:select (guile-1.8))
  33. #:use-module (srfi srfi-1)
  34. #:use-module (srfi srfi-11)
  35. #:use-module (srfi srfi-26)
  36. #:use-module (srfi srfi-34)
  37. #:use-module (srfi srfi-64)
  38. #:use-module (rnrs io ports)
  39. #:use-module (rnrs bytevectors)
  40. #:use-module (web uri)
  41. #:use-module (ice-9 rdelim)
  42. #:use-module (ice-9 regex)
  43. #:use-module (ice-9 ftw)
  44. #:use-module (ice-9 match))
  45. (define %store
  46. (open-connection-for-tests))
  47. ;; Globally disable grafts because they can trigger early builds.
  48. (%graft? #f)
  49. (define (bootstrap-binary name)
  50. (let ((bin (search-bootstrap-binary name (%current-system))))
  51. (and %store
  52. (add-to-store %store name #t "sha256" bin))))
  53. (define %bash
  54. (bootstrap-binary "bash"))
  55. (define %mkdir
  56. (bootstrap-binary "mkdir"))
  57. (define* (directory-contents dir #:optional (slurp get-bytevector-all))
  58. "Return an alist representing the contents of DIR."
  59. (define prefix-len (string-length dir))
  60. (sort (file-system-fold (const #t) ; enter?
  61. (lambda (path stat result) ; leaf
  62. (alist-cons (string-drop path prefix-len)
  63. (call-with-input-file path slurp)
  64. result))
  65. (lambda (path stat result) result) ; down
  66. (lambda (path stat result) result) ; up
  67. (lambda (path stat result) result) ; skip
  68. (lambda (path stat errno result) result) ; error
  69. '()
  70. dir)
  71. (lambda (e1 e2)
  72. (string<? (car e1) (car e2)))))
  73. ;; Avoid collisions with other tests.
  74. (%http-server-port 10500)
  75. (test-begin "derivations")
  76. (test-assert "parse & export"
  77. (let* ((f (search-path %load-path "tests/test.drv"))
  78. (b1 (call-with-input-file f get-bytevector-all))
  79. (d1 (read-derivation (open-bytevector-input-port b1)))
  80. (b2 (call-with-bytevector-output-port (cut write-derivation d1 <>)))
  81. (d2 (read-derivation (open-bytevector-input-port b2))))
  82. (and (equal? b1 b2)
  83. (equal? d1 d2))))
  84. (test-skip (if %store 0 12))
  85. (test-assert "add-to-store, flat"
  86. (let* ((file (search-path %load-path "language/tree-il/spec.scm"))
  87. (drv (add-to-store %store "flat-test" #f "sha256" file)))
  88. (and (eq? 'regular (stat:type (stat drv)))
  89. (valid-path? %store drv)
  90. (equal? (call-with-input-file file get-bytevector-all)
  91. (call-with-input-file drv get-bytevector-all)))))
  92. (test-assert "add-to-store, recursive"
  93. (let* ((dir (dirname (search-path %load-path "language/tree-il/spec.scm")))
  94. (drv (add-to-store %store "dir-tree-test" #t "sha256" dir)))
  95. (and (eq? 'directory (stat:type (stat drv)))
  96. (valid-path? %store drv)
  97. (equal? (directory-contents dir)
  98. (directory-contents drv)))))
  99. (test-assert "derivation with no inputs"
  100. (let* ((builder (add-text-to-store %store "my-builder.sh"
  101. "echo hello, world\n"
  102. '()))
  103. (drv (derivation %store "foo"
  104. %bash `("-e" ,builder)
  105. #:env-vars '(("HOME" . "/homeless")))))
  106. (and (store-path? (derivation-file-name drv))
  107. (valid-path? %store (derivation-file-name drv)))))
  108. (test-assert "build derivation with 1 source"
  109. (let* ((builder (add-text-to-store %store "my-builder.sh"
  110. "echo hello, world > \"$out\"\n"
  111. '()))
  112. (drv (derivation %store "foo"
  113. %bash `(,builder)
  114. #:env-vars '(("HOME" . "/homeless")
  115. ("zzz" . "Z!")
  116. ("AAA" . "A!"))
  117. #:inputs `((,%bash) (,builder))))
  118. (succeeded?
  119. (build-derivations %store (list drv))))
  120. (and succeeded?
  121. (let ((path (derivation->output-path drv)))
  122. (and (valid-path? %store path)
  123. (string=? (call-with-input-file path read-line)
  124. "hello, world"))))))
  125. (test-assert "derivation with local file as input"
  126. (let* ((builder (add-text-to-store
  127. %store "my-builder.sh"
  128. "(while read line ; do echo \"$line\" ; done) < $in > $out"
  129. '()))
  130. (input (search-path %load-path "ice-9/boot-9.scm"))
  131. (input* (add-to-store %store (basename input)
  132. #t "sha256" input))
  133. (drv (derivation %store "derivation-with-input-file"
  134. %bash `(,builder)
  135. ;; Cheat to pass the actual file name to the
  136. ;; builder.
  137. #:env-vars `(("in" . ,input*))
  138. #:inputs `((,%bash)
  139. (,builder)
  140. (,input))))) ; ← local file name
  141. (and (build-derivations %store (list drv))
  142. ;; Note: we can't compare the files because the above trick alters
  143. ;; the contents.
  144. (valid-path? %store (derivation->output-path drv)))))
  145. (test-assert "derivation fails but keep going"
  146. ;; In keep-going mode, 'build-derivations' should fail because of D1, but it
  147. ;; must return only after D2 has succeeded.
  148. (with-store store
  149. (let* ((d1 (derivation %store "fails"
  150. %bash `("-c" "false")
  151. #:inputs `((,%bash))))
  152. (d2 (build-expression->derivation %store "sleep-then-succeed"
  153. `(begin
  154. ,(random-text)
  155. ;; XXX: Hopefully that's long
  156. ;; enough that D1 has already
  157. ;; failed.
  158. (sleep 2)
  159. (mkdir %output)))))
  160. (set-build-options %store
  161. #:use-substitutes? #f
  162. #:keep-going? #t)
  163. (guard (c ((nix-protocol-error? c)
  164. (and (= 100 (nix-protocol-error-status c))
  165. (string-contains (nix-protocol-error-message c)
  166. (derivation-file-name d1))
  167. (not (valid-path? %store (derivation->output-path d1)))
  168. (valid-path? %store (derivation->output-path d2)))))
  169. (build-derivations %store (list d1 d2))
  170. #f))))
  171. (test-assert "identical files are deduplicated"
  172. (let* ((build1 (add-text-to-store %store "one.sh"
  173. "echo hello, world > \"$out\"\n"
  174. '()))
  175. (build2 (add-text-to-store %store "two.sh"
  176. "# Hey!\necho hello, world > \"$out\"\n"
  177. '()))
  178. (drv1 (derivation %store "foo"
  179. %bash `(,build1)
  180. #:inputs `((,%bash) (,build1))))
  181. (drv2 (derivation %store "bar"
  182. %bash `(,build2)
  183. #:inputs `((,%bash) (,build2)))))
  184. (and (build-derivations %store (list drv1 drv2))
  185. (let ((file1 (derivation->output-path drv1))
  186. (file2 (derivation->output-path drv2)))
  187. (and (valid-path? %store file1) (valid-path? %store file2)
  188. (string=? (call-with-input-file file1 get-string-all)
  189. "hello, world\n")
  190. (= (stat:ino (lstat file1))
  191. (stat:ino (lstat file2))))))))
  192. (test-equal "built-in-builders"
  193. '("download")
  194. (built-in-builders %store))
  195. (test-assert "unknown built-in builder"
  196. (let ((drv (derivation %store "ohoh" "builtin:does-not-exist" '())))
  197. (guard (c ((nix-protocol-error? c)
  198. (string-contains (nix-protocol-error-message c) "failed")))
  199. (build-derivations %store (list drv))
  200. #f)))
  201. (unless (http-server-can-listen?)
  202. (test-skip 1))
  203. (test-assert "'download' built-in builder"
  204. (let ((text (random-text)))
  205. (with-http-server 200 text
  206. (let* ((drv (derivation %store "world"
  207. "builtin:download" '()
  208. #:env-vars `(("url"
  209. . ,(object->string (%local-url))))
  210. #:hash-algo 'sha256
  211. #:hash (sha256 (string->utf8 text)))))
  212. (and (build-derivations %store (list drv))
  213. (string=? (call-with-input-file (derivation->output-path drv)
  214. get-string-all)
  215. text))))))
  216. (unless (http-server-can-listen?)
  217. (test-skip 1))
  218. (test-assert "'download' built-in builder, invalid hash"
  219. (with-http-server 200 "hello, world!"
  220. (let* ((drv (derivation %store "world"
  221. "builtin:download" '()
  222. #:env-vars `(("url"
  223. . ,(object->string (%local-url))))
  224. #:hash-algo 'sha256
  225. #:hash (sha256 (random-bytevector 100))))) ;wrong
  226. (guard (c ((nix-protocol-error? c)
  227. (string-contains (nix-protocol-error-message c) "failed")))
  228. (build-derivations %store (list drv))
  229. #f))))
  230. (unless (http-server-can-listen?)
  231. (test-skip 1))
  232. (test-assert "'download' built-in builder, not found"
  233. (with-http-server 404 "not found"
  234. (let* ((drv (derivation %store "will-never-be-found"
  235. "builtin:download" '()
  236. #:env-vars `(("url"
  237. . ,(object->string (%local-url))))
  238. #:hash-algo 'sha256
  239. #:hash (sha256 (random-bytevector 100)))))
  240. (guard (c ((nix-protocol-error? c)
  241. (string-contains (nix-protocol-error-message (pk c)) "failed")))
  242. (build-derivations %store (list drv))
  243. #f))))
  244. (test-assert "'download' built-in builder, not fixed-output"
  245. (let* ((source (add-text-to-store %store "hello" "hi!"))
  246. (url (string-append "file://" source))
  247. (drv (derivation %store "world"
  248. "builtin:download" '()
  249. #:env-vars `(("url" . ,(object->string url))))))
  250. (guard (c ((nix-protocol-error? c)
  251. (string-contains (nix-protocol-error-message c) "failed")))
  252. (build-derivations %store (list drv))
  253. #f)))
  254. (unless (http-server-can-listen?)
  255. (test-skip 1))
  256. (test-assert "'download' built-in builder, check mode"
  257. ;; Make sure rebuilding the 'builtin:download' derivation in check mode
  258. ;; works. See <http://bugs.gnu.org/25089>.
  259. (let* ((text (random-text))
  260. (drv (derivation %store "world"
  261. "builtin:download" '()
  262. #:env-vars `(("url"
  263. . ,(object->string (%local-url))))
  264. #:hash-algo 'sha256
  265. #:hash (sha256 (string->utf8 text)))))
  266. (and (with-http-server 200 text
  267. (build-derivations %store (list drv)))
  268. (with-http-server 200 text
  269. (build-derivations %store (list drv)
  270. (build-mode check)))
  271. (string=? (call-with-input-file (derivation->output-path drv)
  272. get-string-all)
  273. text))))
  274. (test-equal "derivation-name"
  275. "foo-0.0"
  276. (let ((drv (derivation %store "foo-0.0" %bash '())))
  277. (derivation-name drv)))
  278. (test-equal "derivation-output-names"
  279. '(("out") ("bar" "chbouib"))
  280. (let ((drv1 (derivation %store "foo-0.0" %bash '()))
  281. (drv2 (derivation %store "foo-0.0" %bash '()
  282. #:outputs '("bar" "chbouib"))))
  283. (list (derivation-output-names drv1)
  284. (derivation-output-names drv2))))
  285. (test-assert "offloadable-derivation?"
  286. (and (offloadable-derivation? (derivation %store "foo" %bash '()))
  287. (offloadable-derivation? ;see <http://bugs.gnu.org/18747>
  288. (derivation %store "foo" %bash '()
  289. #:substitutable? #f))
  290. (not (offloadable-derivation?
  291. (derivation %store "foo" %bash '()
  292. #:local-build? #t)))))
  293. (test-assert "substitutable-derivation?"
  294. (and (substitutable-derivation? (derivation %store "foo" %bash '()))
  295. (substitutable-derivation? ;see <http://bugs.gnu.org/18747>
  296. (derivation %store "foo" %bash '()
  297. #:local-build? #t))
  298. (not (substitutable-derivation?
  299. (derivation %store "foo" %bash '()
  300. #:substitutable? #f)))))
  301. (test-assert "fixed-output-derivation?"
  302. (let* ((builder (add-text-to-store %store "my-fixed-builder.sh"
  303. "echo -n hello > $out" '()))
  304. (hash (sha256 (string->utf8 "hello")))
  305. (drv (derivation %store "fixed"
  306. %bash `(,builder)
  307. #:inputs `((,builder))
  308. #:hash hash #:hash-algo 'sha256)))
  309. (fixed-output-derivation? drv)))
  310. (test-assert "fixed-output derivation"
  311. (let* ((builder (add-text-to-store %store "my-fixed-builder.sh"
  312. "echo -n hello > $out" '()))
  313. (hash (sha256 (string->utf8 "hello")))
  314. (drv (derivation %store "fixed"
  315. %bash `(,builder)
  316. #:inputs `((,builder)) ; optional
  317. #:hash hash #:hash-algo 'sha256))
  318. (succeeded? (build-derivations %store (list drv))))
  319. (and succeeded?
  320. (let ((p (derivation->output-path drv)))
  321. (and (equal? (string->utf8 "hello")
  322. (call-with-input-file p get-bytevector-all))
  323. (bytevector? (query-path-hash %store p)))))))
  324. (test-assert "fixed-output derivation: output paths are equal"
  325. (let* ((builder1 (add-text-to-store %store "fixed-builder1.sh"
  326. "echo -n hello > $out" '()))
  327. (builder2 (add-text-to-store %store "fixed-builder2.sh"
  328. "echo hey; echo -n hello > $out" '()))
  329. (hash (sha256 (string->utf8 "hello")))
  330. (drv1 (derivation %store "fixed"
  331. %bash `(,builder1)
  332. #:hash hash #:hash-algo 'sha256))
  333. (drv2 (derivation %store "fixed"
  334. %bash `(,builder2)
  335. #:hash hash #:hash-algo 'sha256))
  336. (succeeded? (build-derivations %store (list drv1 drv2))))
  337. (and succeeded?
  338. (equal? (derivation->output-path drv1)
  339. (derivation->output-path drv2)))))
  340. (test-assert "fixed-output derivation, recursive"
  341. (let* ((builder (add-text-to-store %store "my-fixed-builder.sh"
  342. "echo -n hello > $out" '()))
  343. (hash (sha256 (string->utf8 "hello")))
  344. (drv (derivation %store "fixed-rec"
  345. %bash `(,builder)
  346. #:inputs `((,builder))
  347. #:hash (base32 "0sg9f58l1jj88w6pdrfdpj5x9b1zrwszk84j81zvby36q9whhhqa")
  348. #:hash-algo 'sha256
  349. #:recursive? #t))
  350. (succeeded? (build-derivations %store (list drv))))
  351. (and succeeded?
  352. (let ((p (derivation->output-path drv)))
  353. (and (equal? (string->utf8 "hello")
  354. (call-with-input-file p get-bytevector-all))
  355. (bytevector? (query-path-hash %store p)))))))
  356. (test-assert "derivation with a fixed-output input"
  357. ;; A derivation D using a fixed-output derivation F doesn't has the same
  358. ;; output path when passed F or F', as long as F and F' have the same output
  359. ;; path.
  360. (let* ((builder1 (add-text-to-store %store "fixed-builder1.sh"
  361. "echo -n hello > $out" '()))
  362. (builder2 (add-text-to-store %store "fixed-builder2.sh"
  363. "echo hey; echo -n hello > $out" '()))
  364. (hash (sha256 (string->utf8 "hello")))
  365. (fixed1 (derivation %store "fixed"
  366. %bash `(,builder1)
  367. #:hash hash #:hash-algo 'sha256))
  368. (fixed2 (derivation %store "fixed"
  369. %bash `(,builder2)
  370. #:hash hash #:hash-algo 'sha256))
  371. (fixed-out (derivation->output-path fixed1))
  372. (builder3 (add-text-to-store
  373. %store "final-builder.sh"
  374. ;; Use Bash hackery to avoid Coreutils.
  375. "echo $in ; (read -u 3 c; echo $c) 3< $in > $out" '()))
  376. (final1 (derivation %store "final"
  377. %bash `(,builder3)
  378. #:env-vars `(("in" . ,fixed-out))
  379. #:inputs `((,%bash) (,builder3) (,fixed1))))
  380. (final2 (derivation %store "final"
  381. %bash `(,builder3)
  382. #:env-vars `(("in" . ,fixed-out))
  383. #:inputs `((,%bash) (,builder3) (,fixed2))))
  384. (succeeded? (build-derivations %store
  385. (list final1 final2))))
  386. (and succeeded?
  387. (equal? (derivation->output-path final1)
  388. (derivation->output-path final2)))))
  389. (test-assert "multiple-output derivation"
  390. (let* ((builder (add-text-to-store %store "my-fixed-builder.sh"
  391. "echo one > $out ; echo two > $second"
  392. '()))
  393. (drv (derivation %store "fixed"
  394. %bash `(,builder)
  395. #:env-vars '(("HOME" . "/homeless")
  396. ("zzz" . "Z!")
  397. ("AAA" . "A!"))
  398. #:inputs `((,%bash) (,builder))
  399. #:outputs '("out" "second")))
  400. (succeeded? (build-derivations %store (list drv))))
  401. (and succeeded?
  402. (let ((one (derivation->output-path drv "out"))
  403. (two (derivation->output-path drv "second")))
  404. (and (lset= equal?
  405. (derivation->output-paths drv)
  406. `(("out" . ,one) ("second" . ,two)))
  407. (eq? 'one (call-with-input-file one read))
  408. (eq? 'two (call-with-input-file two read)))))))
  409. (test-assert "multiple-output derivation, non-alphabetic order"
  410. ;; Here, the outputs are not listed in alphabetic order. Yet, the store
  411. ;; path computation must reorder them first.
  412. (let* ((builder (add-text-to-store %store "my-fixed-builder.sh"
  413. "echo one > $out ; echo two > $AAA"
  414. '()))
  415. (drv (derivation %store "fixed"
  416. %bash `(,builder)
  417. #:inputs `((,%bash) (,builder))
  418. #:outputs '("out" "AAA")))
  419. (succeeded? (build-derivations %store (list drv))))
  420. (and succeeded?
  421. (let ((one (derivation->output-path drv "out"))
  422. (two (derivation->output-path drv "AAA")))
  423. (and (eq? 'one (call-with-input-file one read))
  424. (eq? 'two (call-with-input-file two read)))))))
  425. (test-assert "read-derivation vs. derivation"
  426. ;; Make sure 'derivation' and 'read-derivation' return objects that are
  427. ;; identical.
  428. (let* ((sources (unfold (cut >= <> 10)
  429. (lambda (n)
  430. (add-text-to-store %store
  431. (format #f "input~a" n)
  432. (random-text)))
  433. 1+
  434. 0))
  435. (inputs (map (lambda (file)
  436. (derivation %store "derivation-input"
  437. %bash '()
  438. #:inputs `((,%bash) (,file))))
  439. sources))
  440. (builder (add-text-to-store %store "builder.sh"
  441. "echo one > $one ; echo two > $two"
  442. '()))
  443. (drv (derivation %store "derivation"
  444. %bash `(,builder)
  445. #:inputs `((,%bash) (,builder)
  446. ,@(map list (append sources inputs)))
  447. #:outputs '("two" "one")))
  448. (drv* (call-with-input-file (derivation-file-name drv)
  449. read-derivation)))
  450. (equal? drv* drv)))
  451. (test-assert "multiple-output derivation, derivation-path->output-path"
  452. (let* ((builder (add-text-to-store %store "builder.sh"
  453. "echo one > $out ; echo two > $second"
  454. '()))
  455. (drv (derivation %store "multiple"
  456. %bash `(,builder)
  457. #:outputs '("out" "second")))
  458. (drv-file (derivation-file-name drv))
  459. (one (derivation->output-path drv "out"))
  460. (two (derivation->output-path drv "second"))
  461. (first (derivation-path->output-path drv-file "out"))
  462. (second (derivation-path->output-path drv-file "second")))
  463. (and (not (string=? one two))
  464. (string-suffix? "-second" two)
  465. (string=? first one)
  466. (string=? second two))))
  467. (test-assert "user of multiple-output derivation"
  468. ;; Check whether specifying several inputs coming from the same
  469. ;; multiple-output derivation works.
  470. (let* ((builder1 (add-text-to-store %store "my-mo-builder.sh"
  471. "echo one > $out ; echo two > $two"
  472. '()))
  473. (mdrv (derivation %store "multiple-output"
  474. %bash `(,builder1)
  475. #:inputs `((,%bash) (,builder1))
  476. #:outputs '("out" "two")))
  477. (builder2 (add-text-to-store %store "my-mo-user-builder.sh"
  478. "read x < $one;
  479. read y < $two;
  480. echo \"($x $y)\" > $out"
  481. '()))
  482. (udrv (derivation %store "multiple-output-user"
  483. %bash `(,builder2)
  484. #:env-vars `(("one"
  485. . ,(derivation->output-path
  486. mdrv "out"))
  487. ("two"
  488. . ,(derivation->output-path
  489. mdrv "two")))
  490. #:inputs `((,%bash)
  491. (,builder2)
  492. ;; two occurrences of MDRV:
  493. (,mdrv)
  494. (,mdrv "two")))))
  495. (and (build-derivations %store (list (pk 'udrv udrv)))
  496. (let ((p (derivation->output-path udrv)))
  497. (and (valid-path? %store p)
  498. (equal? '(one two) (call-with-input-file p read)))))))
  499. (test-assert "derivation with #:references-graphs"
  500. (let* ((input1 (add-text-to-store %store "foo" "hello"
  501. (list %bash)))
  502. (input2 (add-text-to-store %store "bar"
  503. (number->string (random 7777))
  504. (list input1)))
  505. (builder (add-text-to-store %store "build-graph"
  506. (format #f "
  507. ~a $out
  508. (while read l ; do echo $l ; done) < bash > $out/bash
  509. (while read l ; do echo $l ; done) < input1 > $out/input1
  510. (while read l ; do echo $l ; done) < input2 > $out/input2"
  511. %mkdir)
  512. (list %mkdir)))
  513. (drv (derivation %store "closure-graphs"
  514. %bash `(,builder)
  515. #:references-graphs
  516. `(("bash" . ,%bash)
  517. ("input1" . ,input1)
  518. ("input2" . ,input2))
  519. #:inputs `((,%bash) (,builder))))
  520. (out (derivation->output-path drv)))
  521. (define (deps path . deps)
  522. (let ((count (length deps)))
  523. (string-append path "\n\n" (number->string count) "\n"
  524. (string-join (sort deps string<?) "\n")
  525. (if (zero? count) "" "\n"))))
  526. (and (build-derivations %store (list drv))
  527. (equal? (directory-contents out get-string-all)
  528. `(("/bash" . ,(string-append %bash "\n\n0\n"))
  529. ("/input1" . ,(if (string>? input1 %bash)
  530. (string-append (deps %bash)
  531. (deps input1 %bash))
  532. (string-append (deps input1 %bash)
  533. (deps %bash))))
  534. ("/input2" . ,(string-concatenate
  535. (map cdr
  536. (sort
  537. (map (lambda (p d)
  538. (cons p (apply deps p d)))
  539. (list %bash input1 input2)
  540. (list '() (list %bash) (list input1)))
  541. (lambda (x y)
  542. (match x
  543. ((p1 . _)
  544. (match y
  545. ((p2 . _)
  546. (string<? p1 p2)))))))))))))))
  547. (test-assert "derivation #:allowed-references, ok"
  548. (let ((drv (derivation %store "allowed" %bash
  549. '("-c" "echo hello > $out")
  550. #:inputs `((,%bash))
  551. #:allowed-references '())))
  552. (build-derivations %store (list drv))))
  553. (test-assert "derivation #:allowed-references, not allowed"
  554. (let* ((txt (add-text-to-store %store "foo" "Hello, world."))
  555. (drv (derivation %store "disallowed" %bash
  556. `("-c" ,(string-append "echo " txt "> $out"))
  557. #:inputs `((,%bash) (,txt))
  558. #:allowed-references '())))
  559. (guard (c ((nix-protocol-error? c)
  560. ;; There's no specific error message to check for.
  561. #t))
  562. (build-derivations %store (list drv))
  563. #f)))
  564. (test-assert "derivation #:allowed-references, self allowed"
  565. (let ((drv (derivation %store "allowed" %bash
  566. '("-c" "echo $out > $out")
  567. #:inputs `((,%bash))
  568. #:allowed-references '("out"))))
  569. (build-derivations %store (list drv))))
  570. (test-assert "derivation #:allowed-references, self not allowed"
  571. (let ((drv (derivation %store "disallowed" %bash
  572. `("-c" ,"echo $out > $out")
  573. #:inputs `((,%bash))
  574. #:allowed-references '())))
  575. (guard (c ((nix-protocol-error? c)
  576. ;; There's no specific error message to check for.
  577. #t))
  578. (build-derivations %store (list drv))
  579. #f)))
  580. (test-assert "derivation #:disallowed-references, ok"
  581. (let ((drv (derivation %store "disallowed" %bash
  582. '("-c" "echo hello > $out")
  583. #:inputs `((,%bash))
  584. #:disallowed-references '("out"))))
  585. (build-derivations %store (list drv))))
  586. (test-assert "derivation #:disallowed-references, not ok"
  587. (let* ((txt (add-text-to-store %store "foo" "Hello, world."))
  588. (drv (derivation %store "disdisallowed" %bash
  589. `("-c" ,(string-append "echo " txt "> $out"))
  590. #:inputs `((,%bash) (,txt))
  591. #:disallowed-references (list txt))))
  592. (guard (c ((nix-protocol-error? c)
  593. ;; There's no specific error message to check for.
  594. #t))
  595. (build-derivations %store (list drv))
  596. #f)))
  597. ;; Here we should get the value of $NIX_STATE_DIR that the daemon sees, which
  598. ;; is a unique value for each test process; this value is the same as the one
  599. ;; we see in the process executing this file since it is set by 'test-env'.
  600. (test-equal "derivation #:leaked-env-vars"
  601. (getenv "NIX_STATE_DIR")
  602. (let* ((value (getenv "NIX_STATE_DIR"))
  603. (drv (derivation %store "leaked-env-vars" %bash
  604. '("-c" "echo -n $NIX_STATE_DIR > $out")
  605. #:hash (sha256 (string->utf8 value))
  606. #:hash-algo 'sha256
  607. #:inputs `((,%bash))
  608. #:leaked-env-vars '("NIX_STATE_DIR"))))
  609. (and (build-derivations %store (list drv))
  610. (call-with-input-file (derivation->output-path drv)
  611. get-string-all))))
  612. (define %coreutils
  613. (false-if-exception
  614. (and (network-reachable?)
  615. (package-derivation %store %bootstrap-coreutils&co))))
  616. (test-skip (if %coreutils 0 1))
  617. (test-assert "build derivation with coreutils"
  618. (let* ((builder
  619. (add-text-to-store %store "build-with-coreutils.sh"
  620. "echo $PATH ; mkdir --version ; mkdir $out ; touch $out/good"
  621. '()))
  622. (drv
  623. (derivation %store "foo"
  624. %bash `(,builder)
  625. #:env-vars `(("PATH" .
  626. ,(string-append
  627. (derivation->output-path %coreutils)
  628. "/bin")))
  629. #:inputs `((,builder)
  630. (,%coreutils))))
  631. (succeeded?
  632. (build-derivations %store (list drv))))
  633. (and succeeded?
  634. (let ((p (derivation->output-path drv)))
  635. (and (valid-path? %store p)
  636. (file-exists? (string-append p "/good")))))))
  637. (test-skip (if (%guile-for-build) 0 8))
  638. (test-equal "build-expression->derivation and invalid module name"
  639. '(file-search-error "guix/module/that/does/not/exist.scm")
  640. (guard (c ((file-search-error? c)
  641. (list 'file-search-error
  642. (file-search-error-file-name c))))
  643. (build-expression->derivation %store "foo" #t
  644. #:modules '((guix module that
  645. does not exist)))))
  646. (test-equal "build-expression->derivation and builder encoding"
  647. '("UTF-8" #t)
  648. (let* ((exp '(λ (α) (+ α 1)))
  649. (drv (build-expression->derivation %store "foo" exp)))
  650. (match (derivation-builder-arguments drv)
  651. ((... builder)
  652. (with-fluids ((%default-port-encoding "UTF-8"))
  653. (call-with-input-file builder
  654. (lambda (port)
  655. (list (port-encoding port)
  656. (->bool
  657. (string-contains (get-string-all port)
  658. "(λ (α) (+ α 1))"))))))))))
  659. (test-assert "build-expression->derivation and derivation-prerequisites"
  660. (let ((drv (build-expression->derivation %store "fail" #f)))
  661. (any (match-lambda
  662. (($ <derivation-input> path)
  663. (string=? path (derivation-file-name (%guile-for-build)))))
  664. (derivation-prerequisites drv))))
  665. (test-assert "derivation-prerequisites and valid-derivation-input?"
  666. (let* ((a (build-expression->derivation %store "a" '(mkdir %output)))
  667. (b (build-expression->derivation %store "b" `(list ,(random-text))))
  668. (c (build-expression->derivation %store "c" `(mkdir %output)
  669. #:inputs `(("a" ,a) ("b" ,b)))))
  670. ;; Make sure both A and %BOOTSTRAP-GUILE are built (the latter could have
  671. ;; be removed by tests/guix-gc.sh.)
  672. (build-derivations %store
  673. (list a (package-derivation %store %bootstrap-guile)))
  674. (match (derivation-prerequisites c
  675. (cut valid-derivation-input? %store
  676. <>))
  677. ((($ <derivation-input> file ("out")))
  678. (string=? file (derivation-file-name b)))
  679. (x
  680. (pk 'fail x #f)))))
  681. (test-assert "build-expression->derivation without inputs"
  682. (let* ((builder '(begin
  683. (mkdir %output)
  684. (call-with-output-file (string-append %output "/test")
  685. (lambda (p)
  686. (display '(hello guix) p)))))
  687. (drv (build-expression->derivation %store "goo" builder))
  688. (succeeded? (build-derivations %store (list drv))))
  689. (and succeeded?
  690. (let ((p (derivation->output-path drv)))
  691. (equal? '(hello guix)
  692. (call-with-input-file (string-append p "/test") read))))))
  693. (test-assert "build-expression->derivation and max-silent-time"
  694. (let* ((store (let ((s (open-connection)))
  695. (set-build-options s #:max-silent-time 1)
  696. s))
  697. (builder '(begin (sleep 100) (mkdir %output) #t))
  698. (drv (build-expression->derivation store "silent" builder))
  699. (out-path (derivation->output-path drv)))
  700. (guard (c ((nix-protocol-error? c)
  701. (and (string-contains (nix-protocol-error-message c)
  702. "failed")
  703. (not (valid-path? store out-path)))))
  704. (build-derivations store (list drv))
  705. #f)))
  706. (test-assert "build-expression->derivation and timeout"
  707. (let* ((store (let ((s (open-connection)))
  708. (set-build-options s #:timeout 1)
  709. s))
  710. (builder '(begin (sleep 100) (mkdir %output) #t))
  711. (drv (build-expression->derivation store "slow" builder))
  712. (out-path (derivation->output-path drv)))
  713. (guard (c ((nix-protocol-error? c)
  714. (and (string-contains (nix-protocol-error-message c)
  715. "failed")
  716. (not (valid-path? store out-path)))))
  717. (build-derivations store (list drv))
  718. #f)))
  719. (test-assert "build-expression->derivation and derivation-prerequisites-to-build"
  720. (let ((drv (build-expression->derivation %store "fail" #f)))
  721. ;; The only direct dependency is (%guile-for-build) and it's already
  722. ;; built.
  723. (null? (derivation-prerequisites-to-build %store drv))))
  724. (test-assert "derivation-prerequisites-to-build when outputs already present"
  725. (let* ((builder '(begin (mkdir %output) #t))
  726. (input-drv (build-expression->derivation %store "input" builder))
  727. (input-path (derivation-output-path
  728. (assoc-ref (derivation-outputs input-drv)
  729. "out")))
  730. (drv (build-expression->derivation %store "something" builder
  731. #:inputs
  732. `(("i" ,input-drv))))
  733. (output (derivation->output-path drv)))
  734. ;; Make sure these things are not already built.
  735. (when (valid-path? %store input-path)
  736. (delete-paths %store (list input-path)))
  737. (when (valid-path? %store output)
  738. (delete-paths %store (list output)))
  739. (and (equal? (map derivation-input-path
  740. (derivation-prerequisites-to-build %store drv))
  741. (list (derivation-file-name input-drv)))
  742. ;; Build DRV and delete its input.
  743. (build-derivations %store (list drv))
  744. (delete-paths %store (list input-path))
  745. (not (valid-path? %store input-path))
  746. ;; Now INPUT-PATH is missing, yet it shouldn't be listed as a
  747. ;; prerequisite to build because DRV itself is already built.
  748. (null? (derivation-prerequisites-to-build %store drv)))))
  749. (test-assert "derivation-prerequisites-to-build and substitutes"
  750. (let* ((store (open-connection))
  751. (drv (build-expression->derivation store "prereq-subst"
  752. (random 1000)))
  753. (output (derivation->output-path drv)))
  754. ;; Make sure substitutes are usable.
  755. (set-build-options store #:use-substitutes? #t
  756. #:substitute-urls (%test-substitute-urls))
  757. (with-derivation-narinfo drv
  758. (let-values (((build download)
  759. (derivation-prerequisites-to-build store drv))
  760. ((build* download*)
  761. (derivation-prerequisites-to-build store drv
  762. #:substitutable-info
  763. (const #f))))
  764. (and (null? build)
  765. (equal? (map substitutable-path download) (list output))
  766. (null? download*)
  767. (null? build*))))))
  768. (test-assert "derivation-prerequisites-to-build and substitutes, non-substitutable build"
  769. (let* ((store (open-connection))
  770. (drv (build-expression->derivation store "prereq-no-subst"
  771. (random 1000)
  772. #:substitutable? #f))
  773. (output (derivation->output-path drv)))
  774. ;; Make sure substitutes are usable.
  775. (set-build-options store #:use-substitutes? #t
  776. #:substitute-urls (%test-substitute-urls))
  777. (with-derivation-narinfo drv
  778. (let-values (((build download)
  779. (derivation-prerequisites-to-build store drv)))
  780. ;; Despite being available as a substitute, DRV will be built locally
  781. ;; due to #:substitutable? #f.
  782. (and (null? download)
  783. (match build
  784. (((? derivation-input? input))
  785. (string=? (derivation-input-path input)
  786. (derivation-file-name drv)))))))))
  787. (test-assert "derivation-prerequisites-to-build and substitutes, local build"
  788. (with-store store
  789. (let* ((drv (build-expression->derivation store "prereq-subst-local"
  790. (random 1000)
  791. #:local-build? #t))
  792. (output (derivation->output-path drv)))
  793. ;; Make sure substitutes are usable.
  794. (set-build-options store #:use-substitutes? #t
  795. #:substitute-urls (%test-substitute-urls))
  796. (with-derivation-narinfo drv
  797. (let-values (((build download)
  798. (derivation-prerequisites-to-build store drv)))
  799. ;; #:local-build? is *not* synonymous with #:substitutable?, so we
  800. ;; must be able to substitute DRV's output.
  801. ;; See <http://bugs.gnu.org/18747>.
  802. (and (null? build)
  803. (match download
  804. (((= substitutable-path item))
  805. (string=? item (derivation->output-path drv))))))))))
  806. (test-assert "derivation-prerequisites-to-build in 'check' mode"
  807. (with-store store
  808. (let* ((dep (build-expression->derivation store "dep"
  809. `(begin ,(random-text)
  810. (mkdir %output))))
  811. (drv (build-expression->derivation store "to-check"
  812. '(mkdir %output)
  813. #:inputs `(("dep" ,dep)))))
  814. (build-derivations store (list drv))
  815. (delete-paths store (list (derivation->output-path dep)))
  816. ;; In 'check' mode, DEP must be rebuilt.
  817. (and (null? (derivation-prerequisites-to-build store drv))
  818. (match (derivation-prerequisites-to-build store drv
  819. #:mode (build-mode
  820. check))
  821. ((input)
  822. (string=? (derivation-input-path input)
  823. (derivation-file-name dep))))))))
  824. (test-assert "substitution-oracle and #:substitute? #f"
  825. (with-store store
  826. (let* ((dep (build-expression->derivation store "dep"
  827. `(begin ,(random-text)
  828. (mkdir %output))))
  829. (drv (build-expression->derivation store "not-subst"
  830. `(begin ,(random-text)
  831. (mkdir %output))
  832. #:substitutable? #f
  833. #:inputs `(("dep" ,dep))))
  834. (query #f))
  835. (define (record-substitutable-path-query store paths)
  836. (when query
  837. (error "already called!" query))
  838. (set! query paths)
  839. '())
  840. (mock ((guix store) substitutable-path-info
  841. record-substitutable-path-query)
  842. (let ((pred (substitution-oracle store (list drv))))
  843. (pred (derivation->output-path drv))))
  844. ;; Make sure the oracle didn't try to get substitute info for DRV since
  845. ;; DRV is mark as non-substitutable. Assume that GUILE-FOR-BUILD is
  846. ;; already in store and thus not part of QUERY.
  847. (equal? (pk 'query query)
  848. (list (derivation->output-path dep))))))
  849. (test-assert "build-expression->derivation with expression returning #f"
  850. (let* ((builder '(begin
  851. (mkdir %output)
  852. #f)) ; fail!
  853. (drv (build-expression->derivation %store "fail" builder))
  854. (out-path (derivation->output-path drv)))
  855. (guard (c ((nix-protocol-error? c)
  856. ;; Note that the output path may exist at this point, but it
  857. ;; is invalid.
  858. (and (string-match "build .* failed"
  859. (nix-protocol-error-message c))
  860. (not (valid-path? %store out-path)))))
  861. (build-derivations %store (list drv))
  862. #f)))
  863. (test-assert "build-expression->derivation with two outputs"
  864. (let* ((builder '(begin
  865. (call-with-output-file (assoc-ref %outputs "out")
  866. (lambda (p)
  867. (display '(hello) p)))
  868. (call-with-output-file (assoc-ref %outputs "second")
  869. (lambda (p)
  870. (display '(world) p)))))
  871. (drv (build-expression->derivation %store "double" builder
  872. #:outputs '("out"
  873. "second")))
  874. (succeeded? (build-derivations %store (list drv))))
  875. (and succeeded?
  876. (let ((one (derivation->output-path drv))
  877. (two (derivation->output-path drv "second")))
  878. (and (equal? '(hello) (call-with-input-file one read))
  879. (equal? '(world) (call-with-input-file two read)))))))
  880. (test-skip (if %coreutils 0 1))
  881. (test-assert "build-expression->derivation with one input"
  882. (let* ((builder '(call-with-output-file %output
  883. (lambda (p)
  884. (let ((cu (assoc-ref %build-inputs "cu")))
  885. (close 1)
  886. (dup2 (port->fdes p) 1)
  887. (execl (string-append cu "/bin/uname")
  888. "uname" "-a")))))
  889. (drv (build-expression->derivation %store "uname" builder
  890. #:inputs
  891. `(("cu" ,%coreutils))))
  892. (succeeded? (build-derivations %store (list drv))))
  893. (and succeeded?
  894. (let ((p (derivation->output-path drv)))
  895. (string-contains (call-with-input-file p read-line) "GNU")))))
  896. (test-assert "build-expression->derivation with modules"
  897. (let* ((builder `(begin
  898. (use-modules (guix build utils))
  899. (let ((out (assoc-ref %outputs "out")))
  900. (mkdir-p (string-append out "/guile/guix/nix"))
  901. #t)))
  902. (drv (build-expression->derivation %store "test-with-modules"
  903. builder
  904. #:modules
  905. '((guix build utils)))))
  906. (and (build-derivations %store (list drv))
  907. (let* ((p (derivation->output-path drv))
  908. (s (stat (string-append p "/guile/guix/nix"))))
  909. (eq? (stat:type s) 'directory)))))
  910. (test-assert "build-expression->derivation: same fixed-output path"
  911. (let* ((builder1 '(call-with-output-file %output
  912. (lambda (p)
  913. (write "hello" p))))
  914. (builder2 '(call-with-output-file (pk 'difference-here! %output)
  915. (lambda (p)
  916. (write "hello" p))))
  917. (hash (sha256 (string->utf8 "hello")))
  918. (input1 (build-expression->derivation %store "fixed" builder1
  919. #:hash hash
  920. #:hash-algo 'sha256))
  921. (input2 (build-expression->derivation %store "fixed" builder2
  922. #:hash hash
  923. #:hash-algo 'sha256))
  924. (succeeded? (build-derivations %store (list input1 input2))))
  925. (and succeeded?
  926. (not (string=? (derivation-file-name input1)
  927. (derivation-file-name input2)))
  928. (string=? (derivation->output-path input1)
  929. (derivation->output-path input2)))))
  930. (test-assert "build-expression->derivation with a fixed-output input"
  931. (let* ((builder1 '(call-with-output-file %output
  932. (lambda (p)
  933. (write "hello" p))))
  934. (builder2 '(call-with-output-file (pk 'difference-here! %output)
  935. (lambda (p)
  936. (write "hello" p))))
  937. (hash (sha256 (string->utf8 "hello")))
  938. (input1 (build-expression->derivation %store "fixed" builder1
  939. #:hash hash
  940. #:hash-algo 'sha256))
  941. (input2 (build-expression->derivation %store "fixed" builder2
  942. #:hash hash
  943. #:hash-algo 'sha256))
  944. (builder3 '(let ((input (assoc-ref %build-inputs "input")))
  945. (call-with-output-file %output
  946. (lambda (out)
  947. (format #f "My input is ~a.~%" input)))))
  948. (final1 (build-expression->derivation %store "final" builder3
  949. #:inputs
  950. `(("input" ,input1))))
  951. (final2 (build-expression->derivation %store "final" builder3
  952. #:inputs
  953. `(("input" ,input2)))))
  954. (and (string=? (derivation->output-path final1)
  955. (derivation->output-path final2))
  956. (string=? (derivation->output-path final1)
  957. (derivation-path->output-path
  958. (derivation-file-name final1)))
  959. (build-derivations %store (list final1 final2)))))
  960. (test-assert "build-expression->derivation produces recursive fixed-output"
  961. (let* ((builder '(begin
  962. (use-modules (srfi srfi-26))
  963. (mkdir %output)
  964. (chdir %output)
  965. (call-with-output-file "exe"
  966. (cut display "executable" <>))
  967. (chmod "exe" #o777)
  968. (symlink "exe" "symlink")
  969. (mkdir "subdir")))
  970. (drv (build-expression->derivation %store "fixed-rec" builder
  971. #:hash-algo 'sha256
  972. #:hash (base32
  973. "10k1lw41wyrjf9mxydi0is5nkpynlsvgslinics4ppir13g7d74p")
  974. #:recursive? #t)))
  975. (and (build-derivations %store (list drv))
  976. (let* ((dir (derivation->output-path drv))
  977. (exe (string-append dir "/exe"))
  978. (link (string-append dir "/symlink"))
  979. (subdir (string-append dir "/subdir")))
  980. (and (executable-file? exe)
  981. (string=? "executable"
  982. (call-with-input-file exe get-string-all))
  983. (string=? "exe" (readlink link))
  984. (file-is-directory? subdir))))))
  985. (test-assert "build-expression->derivation uses recursive fixed-output"
  986. (let* ((builder '(call-with-output-file %output
  987. (lambda (port)
  988. (display "hello" port))))
  989. (fixed (build-expression->derivation %store "small-fixed-rec"
  990. builder
  991. #:hash-algo 'sha256
  992. #:hash (base32
  993. "0sg9f58l1jj88w6pdrfdpj5x9b1zrwszk84j81zvby36q9whhhqa")
  994. #:recursive? #t))
  995. (in (derivation->output-path fixed))
  996. (builder `(begin
  997. (mkdir %output)
  998. (chdir %output)
  999. (symlink ,in "symlink")))
  1000. (drv (build-expression->derivation %store "fixed-rec-user"
  1001. builder
  1002. #:inputs `(("fixed" ,fixed)))))
  1003. (and (build-derivations %store (list drv))
  1004. (let ((out (derivation->output-path drv)))
  1005. (string=? (readlink (string-append out "/symlink")) in)))))
  1006. (test-assert "build-expression->derivation with #:references-graphs"
  1007. (let* ((input (add-text-to-store %store "foo" "hello"
  1008. (list %bash %mkdir)))
  1009. (builder '(copy-file "input" %output))
  1010. (drv (build-expression->derivation %store "references-graphs"
  1011. builder
  1012. #:references-graphs
  1013. `(("input" . ,input))))
  1014. (out (derivation->output-path drv)))
  1015. (define (deps path . deps)
  1016. (let ((count (length deps)))
  1017. (string-append path "\n\n" (number->string count) "\n"
  1018. (string-join (sort deps string<?) "\n")
  1019. (if (zero? count) "" "\n"))))
  1020. (and (build-derivations %store (list drv))
  1021. (equal? (call-with-input-file out get-string-all)
  1022. (string-concatenate
  1023. (map cdr
  1024. (sort (map (lambda (p d)
  1025. (cons p (apply deps p d)))
  1026. (list input %bash %mkdir)
  1027. (list (list %bash %mkdir)
  1028. '() '()))
  1029. (lambda (x y)
  1030. (match x
  1031. ((p1 . _)
  1032. (match y
  1033. ((p2 . _)
  1034. (string<? p1 p2)))))))))))))
  1035. (test-equal "map-derivation"
  1036. "hello"
  1037. (let* ((joke (package-derivation %store guile-1.8))
  1038. (good (package-derivation %store %bootstrap-guile))
  1039. (drv1 (build-expression->derivation %store "original-drv1"
  1040. #f ; systematically fail
  1041. #:guile-for-build joke))
  1042. (drv2 (build-expression->derivation %store "original-drv2"
  1043. '(call-with-output-file %output
  1044. (lambda (p)
  1045. (display "hello" p)))))
  1046. (drv3 (build-expression->derivation %store "drv-to-remap"
  1047. '(let ((in (assoc-ref
  1048. %build-inputs "in")))
  1049. (copy-file in %output))
  1050. #:inputs `(("in" ,drv1))
  1051. #:guile-for-build joke))
  1052. (drv4 (map-derivation %store drv3 `((,drv1 . ,drv2)
  1053. (,joke . ,good))))
  1054. (out (derivation->output-path drv4)))
  1055. (and (build-derivations %store (list (pk 'remapped drv4)))
  1056. (call-with-input-file out get-string-all))))
  1057. (test-equal "map-derivation, sources"
  1058. "hello"
  1059. (let* ((script1 (add-text-to-store %store "fail.sh" "exit 1"))
  1060. (script2 (add-text-to-store %store "hi.sh" "echo -n hello > $out"))
  1061. (bash-full (package-derivation %store (@ (gnu packages bash) bash)))
  1062. (drv1 (derivation %store "drv-to-remap"
  1063. ;; XXX: This wouldn't work in practice, but if
  1064. ;; we append "/bin/bash" then we can't replace
  1065. ;; it with the bootstrap bash, which is a
  1066. ;; single file.
  1067. (derivation->output-path bash-full)
  1068. `("-e" ,script1)
  1069. #:inputs `((,bash-full) (,script1))))
  1070. (drv2 (map-derivation %store drv1
  1071. `((,bash-full . ,%bash)
  1072. (,script1 . ,script2))))
  1073. (out (derivation->output-path drv2)))
  1074. (and (build-derivations %store (list (pk 'remapped* drv2)))
  1075. (call-with-input-file out get-string-all))))
  1076. (test-end)
  1077. ;; Local Variables:
  1078. ;; eval: (put 'with-http-server 'scheme-indent-function 2)
  1079. ;; End: