getopt-long.test 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. ;;;; getopt-long.test --- long options processing -*- scheme -*-
  2. ;;;; Thien-Thi Nguyen <ttn@gnu.org> --- August 2001
  3. ;;;;
  4. ;;;; Copyright (C) 2001, 2006, 2011 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. (use-modules (test-suite lib)
  20. (ice-9 getopt-long)
  21. (ice-9 regex))
  22. (define-syntax pass-if-fatal-exception
  23. (syntax-rules ()
  24. ((_ name exn exp)
  25. (let ((port (open-output-string)))
  26. (with-error-to-port port
  27. (lambda ()
  28. (run-test
  29. name #t
  30. (lambda ()
  31. (catch (car exn)
  32. (lambda () exp #f)
  33. (lambda (k . args)
  34. (let ((output (get-output-string port)))
  35. (close-port port)
  36. (if (string-match (cdr exn) output)
  37. #t
  38. (error "Unexpected output" output)))))))))))))
  39. (defmacro deferr (name-frag re)
  40. (let ((name (symbol-append 'exception: name-frag)))
  41. `(define ,name (cons 'quit ,re))))
  42. (deferr no-such-option "no such option")
  43. (deferr option-predicate-failed "option predicate failed")
  44. (deferr option-does-not-support-arg "option does not support argument")
  45. (deferr option-must-be-specified "option must be specified")
  46. (deferr option-must-have-arg "option must be specified with argument")
  47. (with-test-prefix "exported procs"
  48. (pass-if "`option-ref' defined" (defined? 'option-ref))
  49. (pass-if "`getopt-long' defined" (defined? 'getopt-long)))
  50. (with-test-prefix "specifying predicate"
  51. (define (test1 . args)
  52. (getopt-long args
  53. `((test (value #t)
  54. (predicate ,(lambda (x)
  55. (string-match "^[0-9]+$" x)))))))
  56. (pass-if "valid arg"
  57. (equal? (test1 "foo" "bar" "--test=123")
  58. '((() "bar") (test . "123"))))
  59. (pass-if-fatal-exception "invalid arg"
  60. exception:option-predicate-failed
  61. (test1 "foo" "bar" "--test=foo"))
  62. (pass-if-fatal-exception "option has no arg"
  63. exception:option-must-have-arg
  64. (test1 "foo" "bar" "--test"))
  65. )
  66. (with-test-prefix "not specifying predicate"
  67. (define (test2 . args)
  68. (getopt-long args `((test (value #t)))))
  69. (pass-if "option has arg"
  70. (equal? (test2 "foo" "bar" "--test=foo")
  71. '((() "bar") (test . "foo"))))
  72. (pass-if "option has no arg"
  73. (equal? (test2 "foo" "bar")
  74. '((() "bar"))))
  75. )
  76. (with-test-prefix "value optional"
  77. (define (test3 . args)
  78. (getopt-long args '((foo (value optional) (single-char #\f))
  79. (bar))))
  80. (pass-if "long option `foo' w/ arg, long option `bar'"
  81. (equal? (test3 "prg" "--foo" "fooval" "--bar")
  82. '((()) (bar . #t) (foo . "fooval"))))
  83. (pass-if "short option `foo' w/ arg, long option `bar'"
  84. (equal? (test3 "prg" "-f" "fooval" "--bar")
  85. '((()) (bar . #t) (foo . "fooval"))))
  86. (pass-if "short option `foo', long option `bar', no args"
  87. (equal? (test3 "prg" "-f" "--bar")
  88. '((()) (bar . #t) (foo . #t))))
  89. (pass-if "long option `foo', long option `bar', no args"
  90. (equal? (test3 "prg" "--foo" "--bar")
  91. '((()) (bar . #t) (foo . #t))))
  92. (pass-if "long option `bar', short option `foo', no args"
  93. (equal? (test3 "prg" "--bar" "-f")
  94. '((()) (foo . #t) (bar . #t))))
  95. (pass-if "long option `bar', long option `foo', no args"
  96. (equal? (test3 "prg" "--bar" "--foo")
  97. '((()) (foo . #t) (bar . #t))))
  98. )
  99. (with-test-prefix "option-ref"
  100. (define (test4 option-arg . args)
  101. (equal? option-arg (option-ref (getopt-long
  102. (cons "prog" args)
  103. '((foo
  104. (value optional)
  105. (single-char #\f))
  106. (bar)))
  107. 'foo #f)))
  108. (pass-if "option-ref `--foo 4'"
  109. (test4 "4" "--foo" "4"))
  110. (pass-if "option-ref `-f 4'"
  111. (test4 "4" "-f" "4"))
  112. (pass-if "option-ref `-f4'"
  113. (test4 "4" "-f4"))
  114. (pass-if "option-ref `--foo=4'"
  115. (test4 "4" "--foo=4"))
  116. )
  117. (with-test-prefix "required"
  118. (define (test5 args specs)
  119. (getopt-long (cons "foo" args) specs))
  120. (pass-if "not mentioned, not given"
  121. (equal? (test5 '() '())
  122. '((()))))
  123. (pass-if-fatal-exception "not mentioned, given"
  124. exception:no-such-option
  125. (test5 '("--req") '((something))))
  126. (pass-if "not specified required, not given"
  127. (equal? (test5 '() '((req (required? #f))))
  128. '((()))))
  129. (pass-if "not specified required, given anyway"
  130. (equal? (test5 '("--req") '((req (required? #f))))
  131. '((()) (req . #t))))
  132. (pass-if "not specified required, but w/ value, given anyway w/ \"=\" val"
  133. (equal? (test5 '("--req=7") '((req (required? #f) (value #t))))
  134. '((()) (req . "7"))))
  135. (pass-if "not specified required, but w/ value, given anyway w/ non-\"=\" val"
  136. (equal? (test5 '("--req" "7") '((req (required? #f) (value #t))))
  137. '((()) (req . "7"))))
  138. (pass-if-fatal-exception "specified required, not given"
  139. exception:option-must-be-specified
  140. (test5 '() '((req (required? #t)))))
  141. )
  142. (with-test-prefix "specified no-value, given anyway"
  143. (define (test6 args specs)
  144. (getopt-long (cons "foo" args) specs))
  145. (pass-if-fatal-exception "using \"=\" syntax"
  146. exception:option-does-not-support-arg
  147. (test6 '("--maybe=yes") '((maybe))))
  148. )
  149. (with-test-prefix "specified arg required"
  150. (define (test7 args)
  151. (getopt-long (cons "foo" args) '((hmm (value #t) (single-char #\H))
  152. (ignore))))
  153. (pass-if "short opt, arg given"
  154. (equal? (test7 '("-H" "99"))
  155. '((()) (hmm . "99"))))
  156. (pass-if "long non-\"=\" opt, arg given"
  157. (equal? (test7 '("--hmm" "100"))
  158. '((()) (hmm . "100"))))
  159. (pass-if "long \"=\" opt, arg given"
  160. (equal? (test7 '("--hmm=101"))
  161. '((()) (hmm . "101"))))
  162. (pass-if-fatal-exception "short opt, arg not given"
  163. exception:option-must-have-arg
  164. (test7 '("-H")))
  165. (pass-if-fatal-exception "long non-\"=\" opt, arg not given (next arg an option)"
  166. exception:option-must-have-arg
  167. (test7 '("--hmm" "--ignore")))
  168. (pass-if-fatal-exception "long \"=\" opt, arg not given"
  169. exception:option-must-have-arg
  170. (test7 '("--hmm")))
  171. )
  172. (with-test-prefix "apples-blimps-catalexis example"
  173. (define (test8 . args)
  174. (equal? (sort (getopt-long (cons "foo" args)
  175. '((apples (single-char #\a))
  176. (blimps (single-char #\b) (value #t))
  177. (catalexis (single-char #\c) (value #t))))
  178. (lambda (a b)
  179. (cond ((null? (car a)) #t)
  180. ((null? (car b)) #f)
  181. (else (string<? (symbol->string (car a))
  182. (symbol->string (car b)))))))
  183. '((())
  184. (apples . #t)
  185. (blimps . "bang")
  186. (catalexis . "couth"))))
  187. (pass-if "normal 1" (test8 "-a" "-b" "bang" "-c" "couth"))
  188. (pass-if "normal 2" (test8 "-ab" "bang" "-c" "couth"))
  189. (pass-if "normal 3" (test8 "-ac" "couth" "-b" "bang"))
  190. (pass-if-fatal-exception "bad ordering causes missing option"
  191. exception:option-must-have-arg
  192. (test8 "-abc" "couth" "bang"))
  193. )
  194. (with-test-prefix "multiple occurrences"
  195. (define (test9 . args)
  196. (equal? (getopt-long (cons "foo" args)
  197. '((inc (single-char #\I) (value #t))
  198. (foo (single-char #\f))))
  199. '((()) (inc . "2") (foo . #t) (inc . "1"))))
  200. ;; terminology:
  201. ;; sf -- single-char free
  202. ;; sa -- single-char abutted
  203. ;; lf -- long free
  204. ;; la -- long abutted (using "=")
  205. (pass-if "sf/sf" (test9 "-I" "1" "-f" "-I" "2"))
  206. (pass-if "sa/sa" (test9 "-I1" "-f" "-I2"))
  207. (pass-if "sf/sa" (test9 "-I" "1" "-f" "-I2"))
  208. (pass-if "sa/sf" (test9 "-I1" "-f" "-I" "2"))
  209. (pass-if "lf/lf" (test9 "--inc" "1" "-f" "--inc" "2"))
  210. (pass-if "la/la" (test9 "--inc=1" "-f" "--inc=2"))
  211. (pass-if "lf/la" (test9 "--inc" "1" "-f" "--inc=2"))
  212. (pass-if "la/lf" (test9 "--inc=1" "-f" "--inc" "2"))
  213. (pass-if "sf/lf" (test9 "-I" "1" "-f" "--inc" "2"))
  214. (pass-if "lf/sf" (test9 "--inc" "1" "-f" "-I" "2"))
  215. (pass-if "sf/la" (test9 "-I" "1" "-f" "--inc=2"))
  216. (pass-if "la/sf" (test9 "--inc=1" "-f" "-I" "2"))
  217. (pass-if "sa/lf" (test9 "-I1" "-f" "--inc" "2"))
  218. (pass-if "lf/sa" (test9 "--inc" "1" "-f" "-I2"))
  219. (pass-if "sa/la" (test9 "-I1" "-f" "--inc=2"))
  220. (pass-if "la/sa" (test9 "--inc=1" "-f" "-I2"))
  221. )
  222. (with-test-prefix "stop-at-first-non-option"
  223. (pass-if "guile-tools compile example"
  224. (equal? (getopt-long '("guile-tools" "compile" "-Wformat" "eval.scm" "-o" "eval.go")
  225. '((help (single-char #\h))
  226. (version (single-char #\v)))
  227. #:stop-at-first-non-option #t)
  228. '((() "compile" "-Wformat" "eval.scm" "-o" "eval.go"))))
  229. )
  230. ;;; getopt-long.test ends here