configuration.scm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2021, 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
  3. ;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
  4. ;;; Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
  5. ;;; Copyright © 2023 Bruno Victal <mirai@makinata.eu>
  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 (tests services configuration)
  22. #:use-module (gnu services configuration)
  23. #:use-module (guix diagnostics)
  24. #:use-module (guix gexp)
  25. #:autoload (guix i18n) (G_)
  26. #:use-module (srfi srfi-34)
  27. #:use-module (srfi srfi-64))
  28. ;;; Tests for the (gnu services configuration) module.
  29. (test-begin "services-configuration")
  30. (define (serialize-number field value)
  31. (format #f "~a=~a" field value))
  32. ;;;
  33. ;;; define-configuration macro.
  34. ;;;
  35. (define-configuration port-configuration
  36. (port (number 80) "The port number.")
  37. (no-serialization))
  38. (test-equal "default value, no serialization"
  39. 80
  40. (port-configuration-port (port-configuration)))
  41. (test-equal "wrong type for a field"
  42. '("configuration.scm" 59 11) ;error location
  43. (guard (c ((configuration-error? c)
  44. (let ((loc (error-location c)))
  45. (list (basename (location-file loc))
  46. (location-line loc)
  47. (location-column loc)))))
  48. (port-configuration
  49. ;; This is line 58; the test relies on line/column numbers!
  50. (port "This is not a number!"))))
  51. (define-configuration port-configuration-cs
  52. (port (number 80) "The port number." empty-serializer))
  53. (test-equal "default value, custom serializer"
  54. 80
  55. (port-configuration-cs-port (port-configuration-cs)))
  56. (define-configuration port-configuration-ndv
  57. (port (number) "The port number."))
  58. (test-equal "no default value, provided"
  59. 55
  60. (port-configuration-ndv-port (port-configuration-ndv
  61. (port 55))))
  62. (test-assert "no default value, not provided"
  63. (guard (c ((configuration-error? c)
  64. #t))
  65. (port-configuration-ndv-port (port-configuration-ndv))))
  66. (define (custom-number-serializer name value)
  67. (format #f "~a = ~a;" name value))
  68. (define-configuration serializable-configuration
  69. (port (number 80) "The port number." (serializer custom-number-serializer)))
  70. (define-configuration serializable-configuration-deprecated
  71. (port (number 80) "The port number." custom-number-serializer))
  72. (test-assert "serialize-configuration"
  73. (gexp?
  74. (let ((config (serializable-configuration)))
  75. (serialize-configuration config serializable-configuration-fields))))
  76. (test-assert "serialize-configuration [deprecated]"
  77. (gexp?
  78. (let ((config (serializable-configuration-deprecated)))
  79. (serialize-configuration
  80. config serializable-configuration-deprecated-fields))))
  81. (define-configuration serializable-configuration
  82. (port (number 80) "The port number." (serializer custom-number-serializer))
  83. (no-serialization))
  84. (test-assert "serialize-configuration with no-serialization"
  85. ;; When serialization is disabled, the serializer is set to #f, so
  86. ;; attempting to use it fails with a 'wrong-type-arg' error.
  87. (not (false-if-exception
  88. (let ((config (serializable-configuration)))
  89. (serialize-configuration config serializable-configuration-fields)))))
  90. (define (custom-prefix-serialize-integer field-name name) name)
  91. (define-configuration configuration-with-prefix
  92. (port (integer 10) "The port number.")
  93. (prefix custom-prefix-))
  94. (test-assert "serialize-configuration with prefix"
  95. (gexp?
  96. (let ((config (configuration-with-prefix)))
  97. (serialize-configuration config configuration-with-prefix-fields))))
  98. ;;;
  99. ;;; define-configuration macro, extra-args literals
  100. ;;;
  101. (define (eval-gexp x)
  102. "Get serialized config as string."
  103. (eval (gexp->approximate-sexp x)
  104. (current-module)))
  105. (define (port? value)
  106. (or (string? value) (number? value)))
  107. (define (sanitize-port value)
  108. (cond ((number? value) value)
  109. ((string? value) (string->number value))
  110. (else (raise (formatted-message (G_ "Bad value: ~a") value)))))
  111. (test-group "Basic sanitizer literal tests"
  112. (define serialize-port serialize-number)
  113. (define-configuration config-with-sanitizer
  114. (port
  115. (port 80)
  116. "Lorem Ipsum."
  117. (sanitizer sanitize-port)))
  118. (test-equal "default value, sanitizer"
  119. 80
  120. (config-with-sanitizer-port (config-with-sanitizer)))
  121. (test-equal "string value, sanitized to number"
  122. 56
  123. (config-with-sanitizer-port (config-with-sanitizer
  124. (port "56"))))
  125. (define (custom-serialize-port field-name value)
  126. (number->string value))
  127. (define-configuration config-serializer
  128. (port
  129. (port 80)
  130. "Lorem Ipsum."
  131. (serializer custom-serialize-port)))
  132. (test-equal "default value, serializer literal"
  133. "80"
  134. (eval-gexp
  135. (serialize-configuration (config-serializer)
  136. config-serializer-fields))))
  137. (test-group "empty-serializer as literal/procedure tests"
  138. (define-configuration config-with-literal
  139. (port
  140. (port 80)
  141. "Lorem Ipsum."
  142. empty-serializer))
  143. (define-configuration config-with-proc
  144. (port
  145. (port 80)
  146. "Lorem Ipsum."
  147. (serializer empty-serializer)))
  148. (test-equal "empty-serializer as literal"
  149. ""
  150. (eval-gexp
  151. (serialize-configuration (config-with-literal)
  152. config-with-literal-fields)))
  153. (test-equal "empty-serializer as procedure"
  154. ""
  155. (eval-gexp
  156. (serialize-configuration (config-with-proc)
  157. config-with-proc-fields))))
  158. (test-group "permutation tests"
  159. (define-configuration config-san+empty-ser
  160. (port
  161. (port 80)
  162. "Lorem Ipsum."
  163. (sanitizer sanitize-port)
  164. empty-serializer))
  165. (define-configuration config-san+ser
  166. (port
  167. (port 80)
  168. "Lorem Ipsum."
  169. (sanitizer sanitize-port)
  170. (serializer (lambda _ "foo"))))
  171. (test-equal "default value, sanitizer, permutation"
  172. 80
  173. (config-san+empty-ser-port (config-san+empty-ser)))
  174. (test-equal "default value, serializer, permutation"
  175. "foo"
  176. (eval-gexp
  177. (serialize-configuration (config-san+ser) config-san+ser-fields)))
  178. (test-equal "string value sanitized to number, permutation"
  179. 56
  180. (config-san+ser-port (config-san+ser
  181. (port "56"))))
  182. ;; Ordering tests.
  183. (define-configuration config-ser+san
  184. (port
  185. (port 80)
  186. "Lorem Ipsum."
  187. (sanitizer sanitize-port)
  188. (serializer (lambda _ "foo"))))
  189. (define-configuration config-empty-ser+san
  190. (port
  191. (port 80)
  192. "Lorem Ipsum."
  193. empty-serializer
  194. (sanitizer sanitize-port)))
  195. (test-equal "default value, sanitizer, permutation 2"
  196. 56
  197. (config-empty-ser+san-port (config-empty-ser+san
  198. (port "56"))))
  199. (test-equal "default value, serializer, permutation 2"
  200. "foo"
  201. (eval-gexp
  202. (serialize-configuration (config-ser+san) config-ser+san-fields))))
  203. (test-group "duplicated/conflicting entries"
  204. (test-error
  205. "duplicate sanitizer" #t
  206. (macroexpand '(define-configuration dupe-san
  207. (foo
  208. (list '())
  209. "Lorem Ipsum."
  210. (sanitizer (lambda () #t))
  211. (sanitizer (lambda () #t))))))
  212. (test-error
  213. "duplicate serializer" #t
  214. (macroexpand '(define-configuration dupe-ser
  215. (foo
  216. (list '())
  217. "Lorem Ipsum."
  218. (serializer (lambda _ ""))
  219. (serializer (lambda _ ""))))))
  220. (test-error
  221. "conflicting use of serializer + empty-serializer" #t
  222. (macroexpand '(define-configuration ser+empty-ser
  223. (foo
  224. (list '())
  225. "Lorem Ipsum."
  226. (serializer (lambda _ "lorem"))
  227. empty-serializer)))))
  228. (test-group "Mix of deprecated and new syntax"
  229. (test-error
  230. "Mix of bare serializer and new syntax" #t
  231. (macroexpand '(define-configuration mixed
  232. (foo
  233. (list '())
  234. "Lorem Ipsum."
  235. (sanitizer (lambda () #t))
  236. (lambda _ "lorem")))))
  237. (test-error
  238. "Mix of bare serializer and new syntax, permutation)" #t
  239. (macroexpand '(define-configuration mixed
  240. (foo
  241. (list '())
  242. "Lorem Ipsum."
  243. (lambda _ "lorem")
  244. (sanitizer (lambda () #t)))))))
  245. ;;;
  246. ;;; define-maybe macro.
  247. ;;;
  248. (define-maybe number)
  249. (define-configuration config-with-maybe-number
  250. (port (maybe-number 80) "")
  251. (count maybe-number ""))
  252. (test-equal "maybe value serialization"
  253. "port=80"
  254. (serialize-maybe-number "port" 80))
  255. (define (config-with-maybe-number->string x)
  256. (eval (gexp->approximate-sexp
  257. (serialize-configuration x config-with-maybe-number-fields))
  258. (current-module)))
  259. (test-equal "maybe value serialization of the instance"
  260. "port=42count=43"
  261. (config-with-maybe-number->string
  262. (config-with-maybe-number
  263. (port 42)
  264. (count 43))))
  265. (test-equal "maybe value serialization of the instance, unspecified"
  266. "port=42"
  267. (config-with-maybe-number->string
  268. (config-with-maybe-number
  269. (port 42))))
  270. (define (serialize-symbol name value)
  271. (format #f "~a=~a~%" name value))
  272. (define-maybe symbol)
  273. (define-configuration config-with-maybe-symbol
  274. (protocol maybe-symbol ""))
  275. ;;; Maybe symbol values are currently seen as serializable, because the
  276. ;;; unspecified value is '%unset-marker%, which is a symbol itself.
  277. ;;; TODO: Remove expected fail marker after resolution.
  278. (test-expect-fail 1)
  279. (test-equal "symbol maybe value serialization, unspecified"
  280. ""
  281. (gexp->approximate-sexp
  282. (serialize-configuration (config-with-maybe-symbol)
  283. config-with-maybe-symbol-fields)))
  284. (define-maybe/no-serialization string)
  285. (define-configuration config-with-maybe-string/no-serialization
  286. (name (maybe-string) "The name of the item.")
  287. (no-serialization))
  288. (test-assert "maybe value without serialization no procedure bound"
  289. (not (defined? 'serialize-maybe-string)))
  290. (test-assert "maybe type, no default"
  291. (eq? %unset-value
  292. (config-with-maybe-string/no-serialization-name
  293. (config-with-maybe-string/no-serialization))))
  294. (test-assert "maybe type, with default"
  295. (equal?
  296. "foo"
  297. (config-with-maybe-string/no-serialization-name
  298. (config-with-maybe-string/no-serialization
  299. (name "foo")))))