(define-library (chibi app-test)
  (import (scheme base) (chibi app) (chibi config) (chibi test))
  (export run-tests)
  (begin
    (define (feed cfg spec . args)
      (let ((animals (conf-get-list cfg 'animals '())))
        (cons (if (conf-get cfg 'lions) (cons 'lions animals) animals) args)))
    (define (wash cfg spec . args)
      (let ((animals (conf-get-list cfg 'animals '())))
        (cons (cons 'soap (conf-get cfg '(command wash soap))) animals)))
    (define zoo-app-spec
      `(zoo
        "Zookeeper Application"
        (@
         (animals (list symbol) "list of animals to act on (default all)")
         (lions boolean (#\l) "also apply the action to lions"))
        (or
         (feed "feed the animals" (,feed animals ...))
         (wash "wash the animals" (@ (soap boolean)) (,wash animals ...))
         (help "print help" (,app-help-command)))
        ))
    (define (run-tests)
      (test-begin "app")
      (test '((camel elephant) "today")
          (run-application
           zoo-app-spec
           '("zoo" "--animals" "camel,elephant" "feed" "today")))
      (test '((lions camel elephant) "tomorrow")
          (run-application
           zoo-app-spec
           '("zoo" "--animals" "camel,elephant" "--lions" "feed" "tomorrow")))
      (test '((soap . #f) rhino)
          (run-application zoo-app-spec '("zoo" "--animals" "rhino" "wash")))
      (test '((soap . #t) rhino)
          (run-application zoo-app-spec
                           '("zoo" "--animals" "rhino" "wash" "--soap")))
      (test '((soap . #t) rhino)
          (run-application zoo-app-spec
                           '("zoo" "wash" "--soap" "--animals" "rhino")))
      (test 'error
          (guard (exn (else 'error))
            (run-application zoo-app-spec
                             '("zoo" "--soap" "wash" "--animals" "rhino"))))
      (let ((out (open-output-string)))
        (parameterize ((current-output-port out))
          (run-application zoo-app-spec '("zoo" "help"))
          (test "Usage: zoo [options] <command>\nCommands:\n  feed animals ... - feed the animals\n  wash animals ... - wash the animals\n  help - print help\nOptions:\n      --animals - list of animals to act on (default all)\n  -l, --lions - also apply the action to lions\n"
              (get-output-string out))))
      (test-end))))