test/tests.lisp @ 8f30975467d9 default tip
Fix doc build command
| author | Steve Losh <steve@stevelosh.com> |
|---|---|
| date | Thu, 13 Jun 2024 13:58:59 -0400 |
| parents | b9b3d5f9211c |
| children | (none) |
(in-package :adopt.test) ;;;; Utils -------------------------------------------------------------------- (defmacro define-test (name &body body) `(test ,(intern (concatenate 'string (symbol-name 'test-) (symbol-name name))) (let ((*package* ,*package*)) ,@body))) (defun run-tests () (1am:run)) (defun hash-table-equal (h1 h2) (and (= (hash-table-count h1) (hash-table-count h2)) (progn (maphash (lambda (k v) (unless (equal v (gethash k h2)) (return-from hash-table-equal nil))) h1) t))) (defun result (&rest key-value-pairs) (loop :with result = (make-hash-table) :for (k v) :on key-value-pairs :by #'cddr :do (setf (gethash k result) v) :finally (return result))) (defmacro check (interface input expected-args expected-result) (let ((args (gensym "ARGS")) (result (gensym "RESULT"))) `(multiple-value-bind (,args ,result) (adopt:parse-options ,interface (split-sequence:split-sequence #\space ,input :remove-empty-subseqs t)) (is (equal ,expected-args ,args)) (is (hash-table-equal ,expected-result ,result))))) (defun ct () (constantly t)) ;;;; Tests -------------------------------------------------------------------- (defparameter *noop* (adopt:make-interface :name "noop" :summary "no options" :help "this interface has no options" :usage "")) (defparameter *option-types* (adopt:make-interface :name "option-types" :summary "testing option types" :help "this interface tests both option types" :usage "[OPTIONS]" :contents (list (adopt:make-option 'long :help "long only" :long "long" :reduce (ct)) (adopt:make-option 'short :help "short only" :short #\s :reduce (ct)) (adopt:make-option 'both :help "both short and long" :short #\b :long "both" :reduce (ct))))) (defparameter *reducers* (adopt:make-interface :name "reducers" :summary "testing reducers" :help "this interface tests basic reducers" :usage "[OPTIONS]" :contents (list (adopt:make-option 'c1 :help "1" :short #\1 :reduce (constantly 1)) (adopt:make-option 'c2 :help "2" :short #\2 :reduce (constantly 2)) (adopt:make-option 'collect :help "collect" :short #\c :long "collect" :parameter "DATA" :reduce #'adopt:collect) (adopt:make-option 'last :help "last" :short #\l :long "last" :parameter "DATA" :reduce #'adopt:last) (adopt:make-option 'first :help "first" :short #\f :long "first" :parameter "DATA" :reduce #'adopt:first)))) (defparameter *same-key* (adopt:make-interface :name "same-key" :summary "testing same keys" :help "this interface tests options with the same result-key" :usage "[OPTIONS]" :contents (list (adopt:make-option '1 :result-key 'foo :help "1" :short #\1 :reduce (constantly 1)) (adopt:make-option '2 :result-key 'foo :help "2" :short #\2 :reduce (constantly 2))))) (defparameter *initial-value* (adopt:make-interface :name "initial-value" :summary "testing initial values" :help "this interface tests the initial-value argument" :usage "[OPTIONS]" :contents (list (adopt:make-option 'foo :help "foo" :short #\f :long "foo" :initial-value "hello" :reduce (constantly "goodbye"))))) (defparameter *finally* (adopt:make-interface :name "finally" :summary "testing finally" :help "this interface tests the finally argument" :usage "[OPTIONS]" :contents (list (adopt:make-option 'yell :help "yell" :short #\y :long "yell" :parameter "VAL" :initial-value "default" :reduce #'adopt:last :finally #'string-upcase) (adopt:make-option 'a :help "ensure a" :short #\a :initial-value "x" :parameter "A" :reduce #'adopt:last :finally (lambda (a) (assert (string= "a" a)) :ok))))) (defparameter *key* (adopt:make-interface :name "key" :summary "testing key" :help "this interface tests the key argument" :usage "[OPTIONS]" :contents (list (adopt:make-option 'int :help "int" :short #\i :long "int" :parameter "K" :reduce #'adopt:collect :key #'parse-integer) (adopt:make-option 'len :help "len" :short #\l :long "len" :parameter "K" :reduce #'adopt:collect :key #'length)))) (adopt:defparameters (*bool* *no-bool*) (adopt:make-boolean-options 'bool :long "bool" :short #\b :help "Bool yes." :help-no "Bool no.")) (defparameter *bools* (adopt:make-interface :name "bools" :summary "testing boolean options" :help "this interface tests booleans" :usage "[OPTIONS]" :contents (list *bool* *no-bool*))) (define-test noop (check *noop* "" '() (result)) (check *noop* "foo" '("foo") (result)) (check *noop* "a b c foo a" '("a" "b" "c" "foo" "a") (result))) (define-test option-types (check *option-types* "foo -s bar" '("foo" "bar") (result 'short t 'long nil 'both nil)) (check *option-types* "foo --long bar" '("foo" "bar") (result 'short nil 'long t 'both nil)) (check *option-types* "foo --both bar" '("foo" "bar") (result 'short nil 'long nil 'both t)) (check *option-types* "foo -b bar" '("foo" "bar") (result 'short nil 'long nil 'both t)) (check *option-types* "foo -bs --long bar" '("foo" "bar") (result 'short t 'long t 'both t)) ;; Make sure we require at least one of short/long. (is (adopt:make-option 'foo :reduce (ct) :help "this should work" :short #\x)) (signals error (adopt:make-option 'foo :reduce (ct) :help "this should not work"))) (define-test reducers (check *reducers* "" '() (result 'c1 nil 'c2 nil 'first nil 'last nil 'collect nil)) (check *reducers* "here we -2 -2 --collect a -c b go --collect c -1" '("here" "we" "go") (result 'c1 1 'c2 2 'first nil 'last nil 'collect '("a" "b" "c"))) (check *reducers* "foo -f 1 -f 2 --last 1 --first 3 --last 2 -l 3 bar" '("foo" "bar") (result 'c1 nil 'c2 nil 'first "1" 'last "3" 'collect nil))) (define-test same-key (check *same-key* "" '() (result 'x nil)) (check *same-key* "-1" '() (result 'foo 1)) (check *same-key* "-2" '() (result 'foo 2)) (check *same-key* "-1121" '() (result 'foo 1))) (define-test initial-value (check *initial-value* "" '() (result 'foo "hello")) (check *initial-value* "x" '("x") (result 'foo "hello")) (check *initial-value* "x --foo y" '("x" "y") (result 'foo "goodbye"))) (define-test key (check *key* "" '() (result 'len '() 'int '())) (check *key* "--int 123 --int 0 --len abc --len 123456" '() (result 'int '(123 0) 'len '(3 6)))) (define-test finally (check *finally* "-a a" '() (result 'yell "DEFAULT" 'a :ok)) (check *finally* "-y foo -y bar -a x -a a" '() (result 'yell "BAR" 'a :ok))) (define-test helpers (is (equal :old (adopt:first :old :new))) (is (equal :new (adopt:last :old :new))) (is (equal '(:a) (adopt:collect '() :a))) (is (equal '(:a :b) (adopt:collect '(:a) :b))) (is (equal '(2 . 1) (funcall (adopt:flip 'cons) 1 2)))) (define-test duplicate-options (is (adopt:make-interface :name "" :summary "" :help "" :usage "" :contents (list (adopt:make-option 'foo :reduce (ct) :help "" :short #\a :long "foo") (adopt:make-option 'bar :reduce (ct) :help "" :short #\b :long "bar")))) (signals error (adopt:make-interface :name "" :summary "" :help "" :usage "" :contents (list (adopt:make-option 'foo :reduce (ct) :help "" :short #\a :long "foo") (adopt:make-option 'bar :reduce (ct) :help "" :short #\a :long "bar")))) (signals error (adopt:make-interface :name "" :summary "" :help "" :usage "" :contents (list (adopt:make-option 'foo :reduce (ct) :help "" :short #\a :long "oops") (adopt:make-option 'bar :reduce (ct) :help "" :short #\b :long "oops"))))) (define-test boolean-options (check *bools* "" '() (result 'bool nil)) (check *bools* "--bool" '() (result 'bool t)) (check *bools* "--bool --no-bool" '() (result 'bool nil)) (check *bools* "-b" '() (result 'bool t)) (check *bools* "-b -B" '() (result 'bool nil)))