inferior.scm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2018-2022 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. (define-module (test-inferior)
  19. #:use-module (guix tests)
  20. #:use-module (guix inferior)
  21. #:use-module (guix packages)
  22. #:use-module (guix store)
  23. #:use-module (guix profiles)
  24. #:use-module (guix derivations)
  25. #:use-module (gnu packages)
  26. #:use-module (gnu packages bootstrap)
  27. #:use-module (gnu packages guile)
  28. #:use-module (gnu packages sqlite)
  29. #:use-module (srfi srfi-1)
  30. #:use-module (srfi srfi-34)
  31. #:use-module (srfi srfi-64)
  32. #:use-module (ice-9 match)
  33. #:use-module (ice-9 rdelim))
  34. (define %top-srcdir
  35. (dirname (search-path %load-path "guix.scm")))
  36. (define %top-builddir
  37. (dirname (search-path %load-compiled-path "guix.go")))
  38. (define %store
  39. (open-connection-for-tests))
  40. (define (manifest-entry->list entry)
  41. (list (manifest-entry-name entry)
  42. (manifest-entry-version entry)
  43. (manifest-entry-output entry)
  44. (manifest-entry-search-paths entry)
  45. (map manifest-entry->list (manifest-entry-dependencies entry))))
  46. (test-begin "inferior")
  47. (test-equal "open-inferior"
  48. '(42 #t)
  49. (let ((inferior (open-inferior %top-builddir
  50. #:command "scripts/guix")))
  51. (and (inferior? inferior)
  52. (let ((a (inferior-eval '(apply * '(6 7)) inferior))
  53. (b (inferior-eval '(@ (gnu packages base) coreutils)
  54. inferior)))
  55. (close-inferior inferior)
  56. (list a (inferior-object? b))))))
  57. (test-equal "close-inferior"
  58. '((hello) (world))
  59. (let* ((inferior1 (open-inferior %top-builddir #:command "scripts/guix"))
  60. (lst1 (inferior-eval '(list 'hello) inferior1))
  61. (inferior2 (open-inferior %top-builddir #:command "scripts/guix"))
  62. (lst2 (inferior-eval '(list 'world) inferior2)))
  63. ;; This call succeeds if and only if INFERIOR2 does not also hold a file
  64. ;; descriptor to the socketpair beneath INFERIOR1; otherwise it blocks.
  65. ;; See <https://issues.guix.gnu.org/55441#10>.
  66. (close-inferior inferior1)
  67. (close-inferior inferior2)
  68. (list lst1 lst2)))
  69. (test-equal "&inferior-exception"
  70. '(a b c d)
  71. (let ((inferior (open-inferior %top-builddir
  72. #:command "scripts/guix")))
  73. (guard (c ((inferior-exception? c)
  74. (close-inferior inferior)
  75. (and (eq? inferior (inferior-exception-inferior c))
  76. (match (inferior-exception-stack c)
  77. (((_ (files lines columns)) ..1)
  78. (member "guix/repl.scm" files)))
  79. (inferior-exception-arguments c))))
  80. (inferior-eval '(throw 'a 'b 'c 'd) inferior)
  81. 'badness)))
  82. (test-equal "&inferior-exception, legacy mode"
  83. '(a b c d)
  84. ;; Omit #:command to open an inferior in "legacy" mode, where Guile runs
  85. ;; directly.
  86. (let ((inferior (open-inferior %top-builddir)))
  87. (guard (c ((inferior-exception? c)
  88. (close-inferior inferior)
  89. (and (eq? inferior (inferior-exception-inferior c))
  90. (inferior-exception-arguments c))))
  91. (inferior-eval '(throw 'a 'b 'c 'd) inferior)
  92. 'badness)))
  93. (test-equal "inferior-packages"
  94. (take (sort (fold-packages (lambda (package lst)
  95. (cons (list (package-name package)
  96. (package-version package)
  97. (package-home-page package)
  98. (package-location package))
  99. lst))
  100. '())
  101. (lambda (x y)
  102. (string<? (car x) (car y))))
  103. 10)
  104. (let* ((inferior (open-inferior %top-builddir
  105. #:command "scripts/guix"))
  106. (packages (inferior-packages inferior)))
  107. (and (every string? (map inferior-package-synopsis packages))
  108. (let ()
  109. (define result
  110. (take (sort (map (lambda (package)
  111. (list (inferior-package-name package)
  112. (inferior-package-version package)
  113. (inferior-package-home-page package)
  114. (inferior-package-location package)))
  115. packages)
  116. (lambda (x y)
  117. (string<? (car x) (car y))))
  118. 10))
  119. (close-inferior inferior)
  120. result))))
  121. (test-equal "inferior-available-packages"
  122. (take (sort (fold-available-packages
  123. (lambda* (name version result
  124. #:key supported? deprecated?
  125. #:allow-other-keys)
  126. (if (and supported? (not deprecated?))
  127. (alist-cons name version result)
  128. result))
  129. '())
  130. (lambda (x y)
  131. (string<? (car x) (car y))))
  132. 10)
  133. (let* ((inferior (open-inferior %top-builddir
  134. #:command "scripts/guix"))
  135. (packages (inferior-available-packages inferior)))
  136. (close-inferior inferior)
  137. (take (sort packages (lambda (x y)
  138. (string<? (car x) (car y))))
  139. 10)))
  140. (test-equal "lookup-inferior-packages"
  141. (let ((->list (lambda (package)
  142. (list (package-name package)
  143. (package-version package)
  144. (package-location package)))))
  145. (list (map ->list (find-packages-by-name "guile" #f))
  146. (map ->list (find-packages-by-name "guile" "2.2"))))
  147. (let* ((inferior (open-inferior %top-builddir
  148. #:command "scripts/guix"))
  149. (->list (lambda (package)
  150. (list (inferior-package-name package)
  151. (inferior-package-version package)
  152. (inferior-package-location package))))
  153. (lst1 (map ->list
  154. (lookup-inferior-packages inferior "guile")))
  155. (lst2 (map ->list
  156. (lookup-inferior-packages inferior
  157. "guile" "2.2"))))
  158. (close-inferior inferior)
  159. (list lst1 lst2)))
  160. (test-assert "lookup-inferior-packages and eq?-ness"
  161. (let* ((inferior (open-inferior %top-builddir
  162. #:command "scripts/guix"))
  163. (lst1 (lookup-inferior-packages inferior "guile"))
  164. (lst2 (lookup-inferior-packages inferior "guile")))
  165. (close-inferior inferior)
  166. (every eq? lst1 lst2)))
  167. (test-equal "inferior-package-inputs"
  168. (let ((->list (match-lambda
  169. ((label (? package? package) . rest)
  170. `(,label
  171. (package ,(package-name package)
  172. ,(package-version package)
  173. ,(package-location package))
  174. ,@rest)))))
  175. (list (map ->list (package-inputs guile-3.0-latest))
  176. (map ->list (package-native-inputs guile-3.0-latest))
  177. (map ->list (package-propagated-inputs guile-3.0-latest))))
  178. (let* ((inferior (open-inferior %top-builddir
  179. #:command "scripts/guix"))
  180. (guile (first (lookup-inferior-packages inferior "guile")))
  181. (->list (match-lambda
  182. ((label (? inferior-package? package) . rest)
  183. `(,label
  184. (package ,(inferior-package-name package)
  185. ,(inferior-package-version package)
  186. ,(inferior-package-location package))
  187. ,@rest))))
  188. (result (list (map ->list (inferior-package-inputs guile))
  189. (map ->list
  190. (inferior-package-native-inputs guile))
  191. (map ->list
  192. (inferior-package-propagated-inputs
  193. guile)))))
  194. (close-inferior inferior)
  195. result))
  196. (test-equal "inferior-package-search-paths"
  197. (package-native-search-paths guile-3.0)
  198. (let* ((inferior (open-inferior %top-builddir
  199. #:command "scripts/guix"))
  200. (guile (first (lookup-inferior-packages inferior "guile")))
  201. (result (inferior-package-native-search-paths guile)))
  202. (close-inferior inferior)
  203. result))
  204. (test-equal "inferior-eval-with-store"
  205. (add-text-to-store %store "foo" "Hello, world!")
  206. (let* ((inferior (open-inferior %top-builddir
  207. #:command "scripts/guix")))
  208. (inferior-eval-with-store inferior %store
  209. '(lambda (store)
  210. (add-text-to-store store "foo"
  211. "Hello, world!")))))
  212. (test-assert "inferior-eval-with-store, &store-protocol-error"
  213. (let* ((inferior (open-inferior %top-builddir
  214. #:command "scripts/guix")))
  215. (guard (c ((store-protocol-error? c)
  216. (string-contains (store-protocol-error-message c)
  217. "invalid character")))
  218. (inferior-eval-with-store inferior %store
  219. '(lambda (store)
  220. (add-text-to-store store "we|rd/?!@"
  221. "uh uh")))
  222. #f)))
  223. (test-equal "inferior-eval-with-store, exception"
  224. '(the-answer = 42)
  225. (let ((inferior (open-inferior %top-builddir
  226. #:command "scripts/guix")))
  227. (guard (c ((inferior-exception? c)
  228. (close-inferior inferior)
  229. (inferior-exception-arguments c)))
  230. (inferior-eval-with-store inferior %store
  231. '(lambda (store)
  232. (throw 'the-answer '= 42))))))
  233. (test-equal "inferior-eval-with-store, not a procedure"
  234. 'wrong-type-arg
  235. (let ((inferior (open-inferior %top-builddir
  236. #:command "scripts/guix")))
  237. (guard (c ((inferior-exception? c)
  238. (close-inferior inferior)
  239. (car (inferior-exception-arguments c))))
  240. (inferior-eval-with-store inferior %store '(+ 1 2)))))
  241. (test-equal "inferior-package-derivation"
  242. (map derivation-file-name
  243. (list (package-derivation %store %bootstrap-guile "x86_64-linux")
  244. (package-derivation %store %bootstrap-guile "armhf-linux")))
  245. (let* ((inferior (open-inferior %top-builddir
  246. #:command "scripts/guix"))
  247. (packages (inferior-packages inferior))
  248. (guile (find (lambda (package)
  249. (string=? (package-name %bootstrap-guile)
  250. (inferior-package-name package)))
  251. packages)))
  252. (map derivation-file-name
  253. (list (inferior-package-derivation %store guile "x86_64-linux")
  254. (inferior-package-derivation %store guile "armhf-linux")))))
  255. (unless (package-replacement sqlite)
  256. (test-skip 1))
  257. (test-equal "inferior-package-replacement"
  258. (package-derivation %store
  259. (package-replacement sqlite)
  260. "x86_64-linux")
  261. (let* ((inferior (open-inferior %top-builddir
  262. #:command "scripts/guix"))
  263. (packages (inferior-packages inferior)))
  264. (match (lookup-inferior-packages inferior
  265. (package-name sqlite)
  266. (package-version sqlite))
  267. ((inferior-sqlite rest ...)
  268. (inferior-package-derivation %store
  269. (inferior-package-replacement
  270. inferior-sqlite)
  271. "x86_64-linux")))))
  272. (test-equal "inferior-package->manifest-entry"
  273. (manifest-entry->list (package->manifest-entry
  274. (first (find-best-packages-by-name "guile" #f))))
  275. (let* ((inferior (open-inferior %top-builddir
  276. #:command "scripts/guix"))
  277. (guile (first (lookup-inferior-packages inferior "guile")))
  278. (entry (inferior-package->manifest-entry guile)))
  279. (close-inferior inferior)
  280. (manifest-entry->list entry)))
  281. (test-equal "packages->manifest"
  282. (map manifest-entry->list
  283. (manifest-entries (packages->manifest
  284. (find-best-packages-by-name "guile" #f))))
  285. (let* ((inferior (open-inferior %top-builddir
  286. #:command "scripts/guix"))
  287. (guile (first (lookup-inferior-packages inferior "guile")))
  288. (manifest (packages->manifest (list guile))))
  289. (close-inferior inferior)
  290. (map manifest-entry->list (manifest-entries manifest))))
  291. (test-equal "#:error-port stderr"
  292. 42
  293. ;; There's a special case in open-bidirectional-pipe for
  294. ;; (current-error-port) being stderr, so this test just checks that
  295. ;; open-inferior doesn't raise an exception
  296. (let ((inferior (open-inferior %top-builddir
  297. #:command "scripts/guix"
  298. #:error-port (current-error-port))))
  299. (and (inferior? inferior)
  300. (inferior-eval '(display "test" (current-error-port)) inferior)
  301. (let ((result (inferior-eval '(apply * '(6 7)) inferior)))
  302. (close-inferior inferior)
  303. result))))
  304. (test-equal "#:error-port pipe"
  305. "42"
  306. (match (pipe)
  307. ((port-to-read-from . port-to-write-to)
  308. (setvbuf port-to-read-from 'line)
  309. (setvbuf port-to-write-to 'line)
  310. (let ((inferior (open-inferior %top-builddir
  311. #:command "scripts/guix"
  312. #:error-port port-to-write-to)))
  313. (and (inferior? inferior)
  314. (begin
  315. (inferior-eval '(display "42\n" (current-error-port)) inferior)
  316. (let loop ((line (read-line port-to-read-from)))
  317. (if (string=? line "42")
  318. (begin
  319. (close-inferior inferior)
  320. line)
  321. (loop (read-line port-to-read-from))))))))))
  322. (test-end "inferior")