derivations.scm 56 KB

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