optargs.test 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. ;;;; optargs.test --- test suite for optional arg processing -*- scheme -*-
  2. ;;;; Matthias Koeppe <mkoeppe@mail.math.uni-magdeburg.de> --- June 2001
  3. ;;;;
  4. ;;;; Copyright (C) 2001, 2006, 2009, 2010 Free Software Foundation, Inc.
  5. ;;;;
  6. ;;;; This library is free software; you can redistribute it and/or
  7. ;;;; modify it under the terms of the GNU Lesser General Public
  8. ;;;; License as published by the Free Software Foundation; either
  9. ;;;; version 3 of the License, or (at your option) any later version.
  10. ;;;;
  11. ;;;; This library is distributed in the hope that it will be useful,
  12. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;;;; Lesser General Public License for more details.
  15. ;;;;
  16. ;;;; You should have received a copy of the GNU Lesser General Public
  17. ;;;; License along with this library; if not, write to the Free Software
  18. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. (define-module (test-suite test-optargs)
  20. #:use-module (test-suite lib)
  21. #:use-module (system base compile)
  22. #:use-module (ice-9 optargs))
  23. (define exception:unrecognized-keyword
  24. '(keyword-argument-error . "Unrecognized keyword"))
  25. (define exception:extraneous-arguments
  26. ;; Message depends on whether we use the interpreter or VM, and on the
  27. ;; evenness of the number of extra arguments (!).
  28. ;'(keyword-argument-error . ".*")
  29. '(#t . ".*"))
  30. (define-syntax c&e
  31. (syntax-rules (pass-if pass-if-exception)
  32. ((_ (pass-if test-name exp))
  33. (begin (pass-if (string-append test-name " (eval)")
  34. (primitive-eval 'exp))
  35. (pass-if (string-append test-name " (compile)")
  36. (compile 'exp #:to 'value #:env (current-module)))))
  37. ((_ (pass-if-exception test-name exc exp))
  38. (begin (pass-if-exception (string-append test-name " (eval)")
  39. exc (primitive-eval 'exp))
  40. (pass-if-exception (string-append test-name " (compile)")
  41. exc (compile 'exp #:to 'value
  42. #:env (current-module)))))))
  43. (define-syntax with-test-prefix/c&e
  44. (syntax-rules ()
  45. ((_ section-name exp ...)
  46. (with-test-prefix section-name (c&e exp) ...))))
  47. (with-test-prefix/c&e "optional argument processing"
  48. (pass-if "local defines work with optional arguments"
  49. (eval '(begin
  50. (define* (test-1 #:optional (x 0))
  51. (define d 1) ; local define
  52. #t)
  53. (false-if-exception (test-1)))
  54. (interaction-environment))))
  55. ;;;
  56. ;;; let-keywords
  57. ;;;
  58. (with-test-prefix/c&e "let-keywords"
  59. ;; in guile 1.6.4 and earlier, an empty binding list only used `begin',
  60. ;; which caused apparently internal defines to "leak" out into the
  61. ;; encompasing environment
  62. (pass-if-exception "empty bindings internal defines leaking out"
  63. exception:unbound-var
  64. (let ((rest '()))
  65. (let-keywords rest #f ()
  66. (define localvar #f)
  67. #f)
  68. localvar))
  69. (pass-if "one key"
  70. (let-keywords '(#:foo 123) #f (foo)
  71. (= foo 123))))
  72. ;;;
  73. ;;; let-keywords*
  74. ;;;
  75. (with-test-prefix/c&e "let-keywords*"
  76. ;; in guile 1.6.4 and earlier, an empty binding list only used `begin',
  77. ;; which caused apparently internal defines to "leak" out into the
  78. ;; encompasing environment
  79. (pass-if-exception "empty bindings internal defines leaking out"
  80. exception:unbound-var
  81. (let ((rest '()))
  82. (let-keywords* rest #f ()
  83. (define localvar #f)
  84. #f)
  85. localvar))
  86. (pass-if "one key"
  87. (let-keywords* '(#:foo 123) #f (foo)
  88. (= foo 123))))
  89. ;;;
  90. ;;; let-optional
  91. ;;;
  92. (with-test-prefix/c&e "let-optional"
  93. ;; in guile 1.6.4 and earlier, an empty binding list only used `begin',
  94. ;; which caused apparently internal defines to "leak" out into the
  95. ;; encompasing environment
  96. (pass-if-exception "empty bindings internal defines leaking out"
  97. exception:unbound-var
  98. (let ((rest '()))
  99. (let-optional rest ()
  100. (define localvar #f)
  101. #f)
  102. localvar))
  103. (pass-if "one var"
  104. (let ((rest '(123)))
  105. (let-optional rest ((foo 999))
  106. (= foo 123)))))
  107. ;;;
  108. ;;; let-optional*
  109. ;;;
  110. (with-test-prefix/c&e "let-optional*"
  111. ;; in guile 1.6.4 and earlier, an empty binding list only used `begin',
  112. ;; which caused apparently internal defines to "leak" out into the
  113. ;; encompasing environment
  114. (pass-if-exception "empty bindings internal defines leaking out"
  115. exception:unbound-var
  116. (let ((rest '()))
  117. (let-optional* rest ()
  118. (define localvar #f)
  119. #f)
  120. localvar))
  121. (pass-if "one var"
  122. (let ((rest '(123)))
  123. (let-optional* rest ((foo 999))
  124. (= foo 123)))))
  125. (define* (foo a b #:optional c (d 1) (e c) f #:key g (h a) (i r) #:rest r)
  126. (list a b c d e f g h i r))
  127. ;; So we could use lots more tests here, but the fact that lambda* is in
  128. ;; the compiler, and the compiler compiles itself, using the evaluator
  129. ;; (when bootstrapping) and compiled code (when doing a partial rebuild)
  130. ;; makes me a bit complacent.
  131. (with-test-prefix/c&e "define*"
  132. (pass-if "the whole enchilada"
  133. (equal? (foo 1 2)
  134. '(1 2 #f 1 #f #f #f 1 () ())))
  135. (pass-if-exception "extraneous arguments"
  136. exception:extraneous-arguments
  137. (let ((f (lambda* (#:key x) x)))
  138. (f 1 2 #:x 'x)))
  139. (pass-if-exception "unrecognized keyword"
  140. exception:unrecognized-keyword
  141. (let ((f (lambda* (#:key x) x)))
  142. (f #:y 'not-recognized)))
  143. (pass-if "rest given before keywords"
  144. ;; Passing the rest argument before the keyword arguments should not
  145. ;; prevent keyword argument binding.
  146. (let ((f (lambda* (#:key x y z #:rest r) (list x y z r))))
  147. (equal? (f 1 2 3 #:x 'x #:z 'z)
  148. '(x #f z (1 2 3 #:x x #:z z))))))
  149. (with-test-prefix/c&e "lambda* inits"
  150. (pass-if "can bind lexicals within inits"
  151. (begin
  152. (define qux
  153. (lambda* (#:optional a #:key (b (or a 13) #:a))
  154. b))
  155. #t))
  156. (pass-if "testing qux"
  157. (and (equal? (qux) 13)
  158. (equal? (qux 1) 1)
  159. (equal? (qux #:a 2) 2)))
  160. (pass-if "nested lambda* with optional"
  161. (begin
  162. (define (foo x)
  163. (define baz x)
  164. (define* (bar #:optional (y baz))
  165. (or (zero? y) (bar (1- y))))
  166. (bar))
  167. (foo 10)))
  168. (pass-if "nested lambda* with key"
  169. (begin
  170. (define (foo x)
  171. (define baz x)
  172. (define* (bar #:key (y baz))
  173. (or (zero? y) (bar #:y (1- y))))
  174. (bar))
  175. (foo 10))))
  176. (with-test-prefix/c&e "defmacro*"
  177. (pass-if "definition"
  178. (begin
  179. (defmacro* transmogrify (a #:optional (b 10))
  180. `(,a ,b))
  181. #t))
  182. (pass-if "explicit arg"
  183. (equal? (transmogrify quote 5)
  184. 5))
  185. (pass-if "default arg"
  186. (equal? (transmogrify quote)
  187. 10)))