utils.scm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
  3. ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
  4. ;;; Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
  5. ;;; Copyright © 2021 Simon Tournier <zimon.toutoune@gmail.com>
  6. ;;;
  7. ;;; This file is part of GNU Guix.
  8. ;;;
  9. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  10. ;;; under the terms of the GNU General Public License as published by
  11. ;;; the Free Software Foundation; either version 3 of the License, or (at
  12. ;;; your option) any later version.
  13. ;;;
  14. ;;; GNU Guix is distributed in the hope that it will be useful, but
  15. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ;;; GNU General Public License for more details.
  18. ;;;
  19. ;;; You should have received a copy of the GNU General Public License
  20. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  21. (define-module (test-utils)
  22. #:use-module ((guix config) #:select (%gzip))
  23. #:use-module (guix utils)
  24. #:use-module ((guix store) #:select (%store-prefix store-path-package-name))
  25. #:use-module ((guix search-paths) #:select (string-tokenize*))
  26. #:use-module (srfi srfi-1)
  27. #:use-module (srfi srfi-11)
  28. #:use-module (srfi srfi-64)
  29. #:use-module (rnrs bytevectors)
  30. #:use-module (rnrs io ports)
  31. #:use-module (ice-9 match)
  32. #:use-module (ice-9 vlist))
  33. (define temp-file
  34. (string-append "t-utils-" (number->string (getpid))))
  35. (test-begin "utils")
  36. (test-assert "gnu-triplet->nix-system"
  37. (let ((samples '(("i586-gnu0.3" "i686-gnu")
  38. ("x86_64-unknown-linux-gnu" "x86_64-linux")
  39. ("i386-pc-linux-gnu" "i686-linux")
  40. ("x86_64-unknown-freebsd8.2" "x86_64-freebsd")
  41. ("x86_64-apple-darwin10.8.0" "x86_64-darwin")
  42. ("i686-pc-cygwin" "i686-cygwin"))))
  43. (let-values (((gnu nix) (unzip2 samples)))
  44. (every (lambda (gnu nix)
  45. (equal? nix (gnu-triplet->nix-system gnu)))
  46. gnu nix))))
  47. (test-assert "package-name->name+version"
  48. (every (match-lambda
  49. ((name version)
  50. (let*-values (((full-name)
  51. (if version
  52. (string-append name "@" version)
  53. name))
  54. ((name* version*)
  55. (package-name->name+version full-name)))
  56. (and (equal? name* name)
  57. (equal? version* version)))))
  58. '(("foo" "0.9.1b")
  59. ("foo-14-bar" "320")
  60. ("foo-bar2" #f)
  61. ("guile" "2.0.6.65-134c9") ; as produced by `git-version-gen'
  62. ("nixpkgs" "1.0pre22125_a28fe19")
  63. ("gtk2" "2.38.0"))))
  64. (test-assert "guile-version>? 1.8"
  65. (guile-version>? "1.8"))
  66. (test-assert "guile-version>? 10.5"
  67. (not (guile-version>? "10.5")))
  68. (test-assert "version-prefix?"
  69. (and (version-prefix? "4.1" "4.1.2")
  70. (version-prefix? "4.1" "4.1")
  71. (not (version-prefix? "4.1" "4.16.2"))
  72. (not (version-prefix? "4.1" "4"))))
  73. (test-equal "version-unique-prefix"
  74. '("2" "2.2" "")
  75. (list (version-unique-prefix "2.0" '("3.0" "2.0"))
  76. (version-unique-prefix "2.2" '("3.0.5" "2.0.9" "2.2.7"))
  77. (version-unique-prefix "27.1" '("27.1"))))
  78. (test-equal "string-tokenize*"
  79. '(("foo")
  80. ("foo" "bar" "baz")
  81. ("foo" "bar" "")
  82. ("foo" "bar" "baz"))
  83. (list (string-tokenize* "foo" ":")
  84. (string-tokenize* "foo;bar;baz" ";")
  85. (string-tokenize* "foo!bar!" "!")
  86. (string-tokenize* "foo+-+bar+-+baz" "+-+")))
  87. (test-equal "string-replace-substring"
  88. '("foo BAR! baz"
  89. "/gnu/store/chbouib"
  90. "")
  91. (list (string-replace-substring "foo bar baz" "bar" "BAR!")
  92. (string-replace-substring "/nix/store/chbouib" "/nix/" "/gnu/")
  93. (string-replace-substring "" "foo" "bar")))
  94. (test-equal "strip-keyword-arguments"
  95. '(a #:b b #:c c)
  96. (strip-keyword-arguments '(#:foo #:bar #:baz)
  97. '(a #:foo 42 #:b b #:baz 3
  98. #:c c #:bar 4)))
  99. (test-equal "ensure-keyword-arguments"
  100. '((#:foo 2)
  101. (#:foo 2 #:bar 3)
  102. (#:foo 42 #:bar 3))
  103. (list (ensure-keyword-arguments '(#:foo 2) '(#:foo 2))
  104. (ensure-keyword-arguments '(#:foo 2) '(#:bar 3))
  105. (ensure-keyword-arguments '(#:foo 2) '(#:bar 3 #:foo 42))))
  106. (test-equal "default-keyword-arguments"
  107. '((#:foo 2)
  108. (#:foo 2)
  109. (#:foo 2 #:bar 3)
  110. (#:foo 2 #:bar 3)
  111. (#:foo 2 #:bar 3))
  112. (list (default-keyword-arguments '() '(#:foo 2))
  113. (default-keyword-arguments '(#:foo 2) '(#:foo 4))
  114. (default-keyword-arguments '() '(#:bar 3 #:foo 2))
  115. (default-keyword-arguments '(#:bar 3) '(#:foo 2))
  116. (default-keyword-arguments '(#:foo 2 #:bar 3) '(#:bar 6))))
  117. (test-equal "substitute-keyword-arguments"
  118. '((#:foo 3)
  119. (#:foo 3)
  120. (#:foo 3 #:bar (1 2))
  121. (#:bar (1 2) #:foo 3)
  122. (#:foo 3))
  123. (list (substitute-keyword-arguments '(#:foo 2)
  124. ((#:foo f) (1+ f)))
  125. (substitute-keyword-arguments '()
  126. ((#:foo f 2) (1+ f)))
  127. (substitute-keyword-arguments '(#:foo 2 #:bar (2))
  128. ((#:foo f) (1+ f))
  129. ((#:bar b) (cons 1 b)))
  130. (substitute-keyword-arguments '(#:foo 2)
  131. ((#:foo _) 3)
  132. ((#:bar b '(2)) (cons 1 b)))
  133. (substitute-keyword-arguments '(#:foo 2)
  134. ((#:foo f 1) (1+ f))
  135. ((#:bar b) (cons 42 b)))))
  136. (test-assert "filtered-port, file"
  137. (let* ((file (search-path %load-path "guix.scm"))
  138. (input (open-file file "r0b")))
  139. (let*-values (((compressed pids1)
  140. (filtered-port `(,%gzip "-c" "--fast") input))
  141. ((decompressed pids2)
  142. (filtered-port `(,%gzip "-d") compressed)))
  143. (and (every (compose zero? cdr waitpid)
  144. (append pids1 pids2))
  145. (equal? (get-bytevector-all decompressed)
  146. (call-with-input-file file get-bytevector-all))))))
  147. (test-assert "filtered-port, non-file"
  148. (let ((data (call-with-input-file (search-path %load-path "guix.scm")
  149. get-bytevector-all)))
  150. (let*-values (((compressed pids1)
  151. (filtered-port `(,%gzip "-c" "--fast")
  152. (open-bytevector-input-port data)))
  153. ((decompressed pids2)
  154. (filtered-port `(,%gzip "-d") compressed)))
  155. (and (pk (every (compose zero? cdr waitpid)
  156. (append pids1 pids2)))
  157. (equal? (get-bytevector-all decompressed) data)))))
  158. (test-assert "filtered-port, does not exist"
  159. (let* ((file (search-path %load-path "guix.scm"))
  160. (input (open-file file "r0b")))
  161. (let-values (((port pids)
  162. (filtered-port '("/does/not/exist") input)))
  163. (any (compose (negate zero?) cdr waitpid)
  164. pids))))
  165. (define (test-compression/decompression method run?)
  166. "Test METHOD, a symbol such as 'gzip. Call RUN? to determine whether to
  167. skip these tests."
  168. (unless (run?) (test-skip 1))
  169. (test-assert (format #f "compressed-port, decompressed-port, non-file [~a]"
  170. method)
  171. (let ((data (call-with-input-file (search-path %load-path "guix.scm")
  172. get-bytevector-all)))
  173. (call-with-temporary-output-file
  174. (lambda (output port)
  175. (close-port port)
  176. (let*-values (((compressed pids)
  177. ;; Note: 'compressed-output-port' only supports file
  178. ;; ports.
  179. (compressed-output-port method
  180. (open-file output "w0"))))
  181. (put-bytevector compressed data)
  182. (close-port compressed)
  183. (and (every (compose zero? cdr waitpid)
  184. (pk 'pids method pids))
  185. (let*-values (((decompressed pids)
  186. (decompressed-port method
  187. (open-bytevector-input-port
  188. (call-with-input-file output
  189. get-bytevector-all))))
  190. ((result)
  191. (get-bytevector-all decompressed)))
  192. (close-port decompressed)
  193. (pk 'len method
  194. (if (bytevector? result)
  195. (bytevector-length result)
  196. result)
  197. (bytevector-length data))
  198. (and (every (compose zero? cdr waitpid)
  199. (pk 'pids method pids))
  200. (equal? result data)))))))))
  201. (false-if-exception (delete-file temp-file))
  202. (unless (run?) (test-skip 1))
  203. (test-assert (format #f "compressed-output-port + decompressed-port [~a]"
  204. method)
  205. (let* ((file (search-path %load-path "guix/derivations.scm"))
  206. (data (call-with-input-file file get-bytevector-all))
  207. (port (open-file temp-file "w0b")))
  208. (call-with-compressed-output-port method port
  209. (lambda (compressed)
  210. (put-bytevector compressed data)))
  211. (close-port port)
  212. (bytevector=? data
  213. (call-with-decompressed-port method (open-file temp-file "r0b")
  214. get-bytevector-all)))))
  215. (for-each test-compression/decompression
  216. `(gzip xz lzip zstd)
  217. (list (const #t) (const #t) (const #t)
  218. (lambda ()
  219. (resolve-module '(zstd) #t #f #:ensure #f))))
  220. ;; This is actually in (guix store).
  221. (test-equal "store-path-package-name"
  222. "bash-4.2-p24"
  223. (store-path-package-name
  224. (string-append (%store-prefix)
  225. "/qvs2rj2ia5vci3wsdb7qvydrmacig4pg-bash-4.2-p24")))
  226. (test-equal "canonical-newline-port"
  227. "This is a journey\nInto the sound\nA journey ...\n"
  228. (let ((port (open-string-input-port
  229. "This is a journey\r\nInto the sound\r\nA journey ...\n")))
  230. (get-string-all (canonical-newline-port port))))
  231. (test-equal "canonical-newline-port-1024"
  232. (string-concatenate (make-list 100 "0123456789abcde\n"))
  233. (let ((port (open-string-input-port
  234. (string-concatenate
  235. (make-list 100 "0123456789abcde\r\n")))))
  236. (get-string-all (canonical-newline-port port))))
  237. (test-equal "edit-expression"
  238. "(display \"GNU Guix\")\n(newline)\n"
  239. (begin
  240. (call-with-output-file temp-file
  241. (lambda (port)
  242. (display "(display \"xiuG UNG\")\n(newline)\n" port)))
  243. (edit-expression `((filename . ,temp-file)
  244. (line . 0)
  245. (column . 9))
  246. string-reverse)
  247. (call-with-input-file temp-file get-string-all)))
  248. (test-equal "string-distance"
  249. '(0 1 1 5 5)
  250. (list
  251. (string-distance "hello" "hello")
  252. (string-distance "hello" "helo")
  253. (string-distance "helo" "hello")
  254. (string-distance "" "hello")
  255. (string-distance "hello" "")))
  256. (test-equal "string-closest"
  257. '("hello" "hello" "helo" #f)
  258. (list
  259. (string-closest "hello" '("hello"))
  260. (string-closest "hello" '("helo" "hello" "halo"))
  261. (string-closest "hello" '("kikoo" "helo" "hihihi" "halo"))
  262. (string-closest "hello" '("aaaaa" "12345" "hellohello" "h"))))
  263. (test-end)
  264. (false-if-exception (delete-file temp-file))