style.scm 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2021-2023 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 (tests-style)
  19. #:use-module (guix packages)
  20. #:use-module (guix scripts style)
  21. #:use-module ((guix utils) #:select (call-with-temporary-directory))
  22. #:use-module ((guix build utils) #:select (substitute*))
  23. #:use-module (guix gexp) ;for the reader extension
  24. #:use-module (guix diagnostics)
  25. #:use-module (gnu packages acl)
  26. #:use-module (gnu packages multiprecision)
  27. #:use-module (srfi srfi-1)
  28. #:use-module (srfi srfi-64)
  29. #:use-module (ice-9 match)
  30. #:use-module (ice-9 rdelim)
  31. #:use-module (ice-9 pretty-print))
  32. (define (call-with-test-package inputs proc)
  33. (call-with-temporary-directory
  34. (lambda (directory)
  35. (call-with-output-file (string-append directory "/my-packages.scm")
  36. (lambda (port)
  37. (pretty-print
  38. `(begin
  39. (define-module (my-packages)
  40. #:use-module (guix)
  41. #:use-module (guix licenses)
  42. #:use-module (gnu packages acl)
  43. #:use-module (gnu packages base)
  44. #:use-module (gnu packages multiprecision)
  45. #:use-module (srfi srfi-1))
  46. (define base
  47. (package
  48. (inherit coreutils)
  49. (inputs '())
  50. (native-inputs '())
  51. (propagated-inputs '())))
  52. (define (sdl-union . lst)
  53. (package
  54. (inherit base)
  55. (name "sdl-union")))
  56. (define-public my-coreutils
  57. (package
  58. (inherit base)
  59. ,@inputs
  60. (name "my-coreutils"))))
  61. port)))
  62. (proc directory))))
  63. (define test-directory
  64. ;; Directory where the package definition lives.
  65. (make-parameter #f))
  66. (define-syntax-rule (with-test-package fields exp ...)
  67. (call-with-test-package fields
  68. (lambda (directory)
  69. (define file
  70. (string-append directory "/my-packages.scm"))
  71. ;; Run as a separate process to make sure FILE is reloaded.
  72. (system* "guix" "style" "-L" directory "-S" "inputs"
  73. "my-coreutils")
  74. (system* "cat" file)
  75. (load file)
  76. (parameterize ((test-directory directory))
  77. exp ...))))
  78. (define* (read-lines port line #:optional (count 1))
  79. "Read COUNT lines from PORT, starting from LINE."
  80. (let loop ((lines '())
  81. (count count))
  82. (cond ((< (port-line port) (- line 1))
  83. (read-char port)
  84. (loop lines count))
  85. ((zero? count)
  86. (string-concatenate-reverse lines))
  87. (else
  88. (match (read-line port 'concat)
  89. ((? eof-object?)
  90. (loop lines 0))
  91. (line
  92. (loop (cons line lines) (- count 1))))))))
  93. (define* (read-package-field package field #:optional (count 1))
  94. (let* ((location (package-field-location package field))
  95. (file (location-file location))
  96. (line (location-line location)))
  97. (call-with-input-file (if (string-prefix? "/" file)
  98. file
  99. (string-append (test-directory) "/"
  100. file))
  101. (lambda (port)
  102. (read-lines port line count)))))
  103. (test-begin "style")
  104. (test-equal "nothing to rewrite"
  105. '()
  106. (with-test-package '()
  107. (package-direct-inputs (@ (my-packages) my-coreutils))))
  108. (test-equal "input labels, mismatch"
  109. (list `(("foo" ,gmp) ("bar" ,acl))
  110. " (inputs `((\"foo\" ,gmp) (\"bar\" ,acl)))\n")
  111. (with-test-package '((inputs `(("foo" ,gmp) ("bar" ,acl))))
  112. (list (package-direct-inputs (@ (my-packages) my-coreutils))
  113. (read-package-field (@ (my-packages) my-coreutils) 'inputs))))
  114. (test-equal "input labels, simple"
  115. (list `(("gmp" ,gmp) ("acl" ,acl))
  116. " (inputs (list gmp acl))\n")
  117. (with-test-package '((inputs `(("gmp" ,gmp) ("acl" ,acl))))
  118. (list (package-direct-inputs (@ (my-packages) my-coreutils))
  119. (read-package-field (@ (my-packages) my-coreutils) 'inputs))))
  120. (test-equal "input labels, long list with one item per line"
  121. (list (concatenate (make-list 4 `(("gmp" ,gmp) ("acl" ,acl))))
  122. "\
  123. (list gmp
  124. acl
  125. gmp
  126. acl
  127. gmp
  128. acl
  129. gmp
  130. acl))\n")
  131. (with-test-package '((inputs `(("gmp" ,gmp) ("acl" ,acl)
  132. ("gmp" ,gmp) ("acl" ,acl)
  133. ("gmp" ,gmp) ("acl" ,acl)
  134. ("gmp" ,gmp) ("acl" ,acl))))
  135. (list (package-direct-inputs (@ (my-packages) my-coreutils))
  136. (read-package-field (@ (my-packages) my-coreutils) 'inputs 8))))
  137. (test-equal "input labels, sdl-union"
  138. "\
  139. (list gmp acl
  140. (sdl-union 1 2 3 4)))\n"
  141. (with-test-package '((inputs `(("gmp" ,gmp) ("acl" ,acl)
  142. ("sdl-union" ,(sdl-union 1 2 3 4)))))
  143. (read-package-field (@ (my-packages) my-coreutils) 'inputs 2)))
  144. (test-equal "input labels, output"
  145. (list `(("gmp" ,gmp "debug") ("acl" ,acl))
  146. " (inputs (list `(,gmp \"debug\") acl))\n")
  147. (with-test-package '((inputs `(("gmp" ,gmp "debug") ("acl" ,acl))))
  148. (list (package-direct-inputs (@ (my-packages) my-coreutils))
  149. (read-package-field (@ (my-packages) my-coreutils) 'inputs))))
  150. (test-equal "input labels, prepend"
  151. (list `(("gmp" ,gmp) ("acl" ,acl))
  152. "\
  153. (modify-inputs (package-propagated-inputs coreutils)
  154. (prepend gmp acl)))\n")
  155. (with-test-package '((inputs `(("gmp" ,gmp) ("acl" ,acl)
  156. ,@(package-propagated-inputs coreutils))))
  157. (list (package-inputs (@ (my-packages) my-coreutils))
  158. (read-package-field (@ (my-packages) my-coreutils) 'inputs 2))))
  159. (test-equal "input labels, prepend + delete"
  160. (list `(("gmp" ,gmp) ("acl" ,acl))
  161. "\
  162. (modify-inputs (package-propagated-inputs coreutils)
  163. (delete \"gmp\")
  164. (prepend gmp acl)))\n")
  165. (with-test-package '((inputs `(("gmp" ,gmp)
  166. ("acl" ,acl)
  167. ,@(alist-delete "gmp"
  168. (package-propagated-inputs coreutils)))))
  169. (list (package-inputs (@ (my-packages) my-coreutils))
  170. (read-package-field (@ (my-packages) my-coreutils) 'inputs 3))))
  171. (test-equal "input labels, prepend + delete multiple"
  172. (list `(("gmp" ,gmp) ("acl" ,acl))
  173. "\
  174. (modify-inputs (package-propagated-inputs coreutils)
  175. (delete \"foo\" \"bar\" \"baz\")
  176. (prepend gmp acl)))\n")
  177. (with-test-package '((inputs `(("gmp" ,gmp)
  178. ("acl" ,acl)
  179. ,@(fold alist-delete
  180. (package-propagated-inputs coreutils)
  181. '("foo" "bar" "baz")))))
  182. (list (package-inputs (@ (my-packages) my-coreutils))
  183. (read-package-field (@ (my-packages) my-coreutils) 'inputs 3))))
  184. (test-equal "input labels, replace"
  185. (list '() ;there's no "gmp" input to replace
  186. "\
  187. (modify-inputs (package-propagated-inputs coreutils)
  188. (replace \"gmp\" gmp)))\n")
  189. (with-test-package '((inputs `(("gmp" ,gmp)
  190. ,@(alist-delete "gmp"
  191. (package-propagated-inputs coreutils)))))
  192. (list (package-inputs (@ (my-packages) my-coreutils))
  193. (read-package-field (@ (my-packages) my-coreutils) 'inputs 2))))
  194. (test-equal "input labels, 'safe' policy"
  195. (list `(("gmp" ,gmp) ("acl" ,acl))
  196. "\
  197. (inputs (list gmp acl))\n")
  198. (call-with-test-package '((inputs `(("GMP" ,gmp) ("ACL" ,acl)))
  199. (arguments '())) ;no build system arguments
  200. (lambda (directory)
  201. (define file
  202. (string-append directory "/my-packages.scm"))
  203. (system* "guix" "style" "-L" directory "my-coreutils"
  204. "-S" "inputs"
  205. "--input-simplification=safe")
  206. (load file)
  207. (list (package-inputs (@ (my-packages) my-coreutils))
  208. (read-package-field (@ (my-packages) my-coreutils) 'inputs)))))
  209. (test-equal "input labels, 'safe' policy, trivial arguments"
  210. (list `(("gmp" ,gmp) ("mpfr" ,mpfr))
  211. "\
  212. (inputs (list gmp mpfr))\n")
  213. (call-with-test-package '((inputs `(("GMP" ,gmp) ("Mpfr" ,mpfr)))
  214. (arguments ;"trivial" arguments
  215. '(#:tests? #f
  216. #:test-target "whatever")))
  217. (lambda (directory)
  218. (define file
  219. (string-append directory "/my-packages.scm"))
  220. (system* "guix" "style" "-L" directory "my-coreutils"
  221. "-S" "inputs"
  222. "--input-simplification=safe")
  223. (load file)
  224. (list (package-inputs (@ (my-packages) my-coreutils))
  225. (read-package-field (@ (my-packages) my-coreutils) 'inputs)))))
  226. (test-equal "input labels, 'safe' policy, nothing changed"
  227. (list `(("GMP" ,gmp) ("ACL" ,acl))
  228. "\
  229. (inputs `((\"GMP\" ,gmp) (\"ACL\" ,acl)))\n")
  230. (call-with-test-package '((inputs `(("GMP" ,gmp) ("ACL" ,acl)))
  231. ;; Non-empty argument list, so potentially unsafe
  232. ;; input simplification.
  233. (arguments
  234. '(#:configure-flags
  235. (assoc-ref %build-inputs "GMP"))))
  236. (lambda (directory)
  237. (define file
  238. (string-append directory "/my-packages.scm"))
  239. (system* "guix" "style" "-L" directory "my-coreutils"
  240. "-S" "inputs"
  241. "--input-simplification=safe")
  242. (load file)
  243. (list (package-inputs (@ (my-packages) my-coreutils))
  244. (read-package-field (@ (my-packages) my-coreutils) 'inputs)))))
  245. (test-equal "input labels, margin comment"
  246. (list `(("gmp" ,gmp))
  247. `(("acl" ,acl))
  248. " (inputs (list gmp)) ;margin comment\n"
  249. " (native-inputs (list acl)) ;another one\n")
  250. (call-with-test-package '((inputs `(("gmp" ,gmp)))
  251. (native-inputs `(("acl" ,acl))))
  252. (lambda (directory)
  253. (define file
  254. (string-append directory "/my-packages.scm"))
  255. (substitute* file
  256. (("\"gmp\"(.*)$" _ rest)
  257. (string-append "\"gmp\"" (string-trim-right rest)
  258. " ;margin comment\n"))
  259. (("\"acl\"(.*)$" _ rest)
  260. (string-append "\"acl\"" (string-trim-right rest)
  261. " ;another one\n")))
  262. (system* "cat" file)
  263. (system* "guix" "style" "-L" directory "-S" "inputs"
  264. "my-coreutils")
  265. (load file)
  266. (list (package-inputs (@ (my-packages) my-coreutils))
  267. (package-native-inputs (@ (my-packages) my-coreutils))
  268. (read-package-field (@ (my-packages) my-coreutils) 'inputs)
  269. (read-package-field (@ (my-packages) my-coreutils) 'native-inputs)))))
  270. (test-equal "input labels, margin comment on long list"
  271. (list (concatenate (make-list 4 `(("gmp" ,gmp) ("acl" ,acl))))
  272. "\
  273. (list gmp ;margin comment
  274. acl
  275. gmp ;margin comment
  276. acl
  277. gmp ;margin comment
  278. acl
  279. gmp ;margin comment
  280. acl))\n")
  281. (call-with-test-package '((inputs `(("gmp" ,gmp) ("acl" ,acl)
  282. ("gmp" ,gmp) ("acl" ,acl)
  283. ("gmp" ,gmp) ("acl" ,acl)
  284. ("gmp" ,gmp) ("acl" ,acl))))
  285. (lambda (directory)
  286. (define file
  287. (string-append directory "/my-packages.scm"))
  288. (substitute* file
  289. (("\"gmp\"(.*)$" _ rest)
  290. (string-append "\"gmp\"" (string-trim-right rest)
  291. " ;margin comment\n")))
  292. (system* "cat" file)
  293. (system* "guix" "style" "-L" directory "-S" "inputs"
  294. "my-coreutils")
  295. (load file)
  296. (list (package-inputs (@ (my-packages) my-coreutils))
  297. (read-package-field (@ (my-packages) my-coreutils) 'inputs 8)))))
  298. (test-equal "input labels, line comment"
  299. (list `(("gmp" ,gmp) ("acl" ,acl))
  300. "\
  301. (inputs (list gmp
  302. ;; line comment!
  303. acl))\n")
  304. (call-with-test-package '((inputs `(("gmp" ,gmp) ("acl" ,acl))))
  305. (lambda (directory)
  306. (define file
  307. (string-append directory "/my-packages.scm"))
  308. (substitute* file
  309. ((",gmp\\)(.*)$" _ rest)
  310. (string-append ",gmp)\n ;; line comment!\n" rest)))
  311. (system* "guix" "style" "-L" directory "-S" "inputs"
  312. "my-coreutils")
  313. (load file)
  314. (list (package-inputs (@ (my-packages) my-coreutils))
  315. (read-package-field (@ (my-packages) my-coreutils) 'inputs 3)))))
  316. (test-equal "input labels, modify-inputs and margin comment"
  317. (list `(("gmp" ,gmp) ("acl" ,acl) ("mpfr" ,mpfr))
  318. "\
  319. (modify-inputs (package-propagated-inputs coreutils)
  320. (prepend gmp ;margin comment
  321. acl ;another one
  322. mpfr)))\n")
  323. (call-with-test-package '((inputs
  324. `(("gmp" ,gmp) ("acl" ,acl) ("mpfr" ,mpfr)
  325. ,@(package-propagated-inputs coreutils))))
  326. (lambda (directory)
  327. (define file
  328. (string-append directory "/my-packages.scm"))
  329. (substitute* file
  330. ((",gmp\\)(.*)$" _ rest)
  331. (string-append ",gmp) ;margin comment" rest))
  332. ((",acl\\)(.*)$" _ rest)
  333. (string-append ",acl) ;another one" rest)))
  334. (system* "guix" "style" "-L" directory "-S" "inputs"
  335. "my-coreutils")
  336. (load file)
  337. (list (package-inputs (@ (my-packages) my-coreutils))
  338. (read-package-field (@ (my-packages) my-coreutils) 'inputs 4)))))
  339. (test-assert "gexpify arguments, already gexpified"
  340. (call-with-test-package '((arguments
  341. (list #:configure-flags #~'("--help"))))
  342. (lambda (directory)
  343. (define file
  344. (string-append directory "/my-packages.scm"))
  345. (define (fingerprint file)
  346. (let ((stat (stat file)))
  347. (list (stat:mtime stat) (stat:size stat))))
  348. (define before
  349. (fingerprint file))
  350. (system* "guix" "style" "-L" directory "my-coreutils"
  351. "-S" "arguments")
  352. (equal? (fingerprint file) before))))
  353. (test-equal "gexpify arguments, non-gexp arguments, margin comment"
  354. (list (list #:tests? #f #:test-target "check")
  355. "\
  356. (arguments (list #:tests? #f ;no tests
  357. #:test-target \"check\"))\n")
  358. (call-with-test-package '((arguments
  359. '(#:tests? #f
  360. #:test-target "check")))
  361. (lambda (directory)
  362. (define file
  363. (string-append directory "/my-packages.scm"))
  364. (substitute* file
  365. (("#:tests\\? #f" all)
  366. (string-append all " ;no tests\n")))
  367. (system* "guix" "style" "-L" directory "my-coreutils"
  368. "-S" "arguments")
  369. (load file)
  370. (list (package-arguments (@ (my-packages) my-coreutils))
  371. (read-package-field (@ (my-packages) my-coreutils) 'arguments 2)))))
  372. (test-equal "gexpify arguments, phases and flags"
  373. "\
  374. (list #:tests? #f
  375. #:configure-flags #~'(\"--fast\")
  376. #:make-flags #~(list (string-append \"CC=\"
  377. #$(cc-for-target)))
  378. #:phases #~(modify-phases %standard-phases
  379. ;; Line comment.
  380. whatever)))\n"
  381. (call-with-test-package '((arguments
  382. `(#:tests? #f
  383. #:configure-flags '("--fast")
  384. #:make-flags
  385. (list (string-append "CC=" ,(cc-for-target)))
  386. #:phases (modify-phases %standard-phases
  387. whatever))))
  388. (lambda (directory)
  389. (define file
  390. (string-append directory "/my-packages.scm"))
  391. (substitute* file
  392. (("whatever")
  393. "\n;; Line comment.
  394. whatever"))
  395. (system* "guix" "style" "-L" directory "my-coreutils"
  396. "-S" "arguments")
  397. (load file)
  398. (read-package-field (@ (my-packages) my-coreutils) 'arguments 7))))
  399. (test-equal "gexpify arguments, append arguments"
  400. "\
  401. (append (list #:tests? #f
  402. #:configure-flags #~'(\"--fast\"))
  403. (package-arguments coreutils)))\n"
  404. (call-with-test-package '((arguments
  405. `(#:tests? #f
  406. #:configure-flags '("--fast")
  407. ,@(package-arguments coreutils))))
  408. (lambda (directory)
  409. (define file
  410. (string-append directory "/my-packages.scm"))
  411. (system* "guix" "style" "-L" directory "my-coreutils"
  412. "-S" "arguments")
  413. (load file)
  414. (read-package-field (@ (my-packages) my-coreutils) 'arguments 3))))
  415. (test-equal "gexpify arguments, substitute-keyword-arguments"
  416. "\
  417. (substitute-keyword-arguments (package-arguments coreutils)
  418. ((#:tests? _ #f)
  419. #t)
  420. ((#:make-flags flags
  421. #~'())
  422. #~(cons \"-DXYZ=yes\"
  423. #$flags))))\n"
  424. (call-with-test-package '((arguments
  425. (substitute-keyword-arguments
  426. (package-arguments coreutils)
  427. ((#:tests? _ #f) #t)
  428. ((#:make-flags flags ''())
  429. `(cons "-DXYZ=yes" ,flags)))))
  430. (lambda (directory)
  431. (define file
  432. (string-append directory "/my-packages.scm"))
  433. (system* "guix" "style" "-L" directory "my-coreutils"
  434. "-S" "arguments")
  435. (load file)
  436. (read-package-field (@ (my-packages) my-coreutils) 'arguments 7))))
  437. (test-equal "gexpify arguments, append substitute-keyword-arguments"
  438. "\
  439. (append (list #:tests? #f)
  440. (substitute-keyword-arguments (package-arguments coreutils)
  441. ((#:make-flags flags)
  442. #~(append `(\"-n\" ,%output)
  443. #$flags)))))\n"
  444. (call-with-test-package '((arguments
  445. `(#:tests? #f
  446. ,@(substitute-keyword-arguments
  447. (package-arguments coreutils)
  448. ((#:make-flags flags)
  449. `(append `("-n" ,%output) ,flags))))))
  450. (lambda (directory)
  451. (define file
  452. (string-append directory "/my-packages.scm"))
  453. (system* "guix" "style" "-L" directory "my-coreutils"
  454. "-S" "arguments")
  455. (load file)
  456. (read-package-field (@ (my-packages) my-coreutils) 'arguments 5))))
  457. (test-end)
  458. ;; Local Variables:
  459. ;; eval: (put 'with-test-package 'scheme-indent-function 1)
  460. ;; eval: (put 'call-with-test-package 'scheme-indent-function 1)
  461. ;; End: