2047 lines
		
	
	
	
		
			53 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
			
		
		
	
	
			2047 lines
		
	
	
	
		
			53 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
| (in-package :cl-user)
 | |
| 
 | |
| (defpackage :alexandria-tests
 | |
|   (:use :cl :alexandria #+sbcl :sb-rt #-sbcl :rtest)
 | |
|   (:import-from #+sbcl :sb-rt #-sbcl :rtest
 | |
|                 #:*compile-tests* #:*expected-failures*))
 | |
| 
 | |
| (in-package :alexandria-tests)
 | |
| 
 | |
| (defun run-tests (&key ((:compiled *compile-tests*)))
 | |
|   (do-tests))
 | |
| 
 | |
| (defun hash-table-test-name (name)
 | |
|   ;; Workaround for Clisp calling EQL in a hash-table FASTHASH-EQL.
 | |
|   (hash-table-test (make-hash-table :test name)))
 | |
| 
 | |
| ;;;; Arrays
 | |
| 
 | |
| (deftest copy-array.1
 | |
|     (let* ((orig (vector 1 2 3))
 | |
|            (copy (copy-array orig)))
 | |
|       (values (eq orig copy) (equalp orig copy)))
 | |
|   nil t)
 | |
| 
 | |
| (deftest copy-array.2
 | |
|     (let ((orig (make-array 1024 :fill-pointer 0)))
 | |
|       (vector-push-extend 1 orig)
 | |
|       (vector-push-extend 2 orig)
 | |
|       (vector-push-extend 3 orig)
 | |
|       (let ((copy (copy-array orig)))
 | |
|         (values (eq orig copy) (equalp orig copy)
 | |
|                 (array-has-fill-pointer-p copy)
 | |
|                 (eql (fill-pointer orig) (fill-pointer copy)))))
 | |
|   nil t t t)
 | |
| 
 | |
| (deftest copy-array.3
 | |
|     (let* ((orig (vector 1 2 3))
 | |
|            (copy (copy-array orig)))
 | |
|       (typep copy 'simple-array))
 | |
|   t)
 | |
| 
 | |
| (deftest copy-array.4
 | |
|    (let ((orig (make-array 21
 | |
|                            :adjustable t
 | |
|                            :fill-pointer 0)))
 | |
|      (dotimes (n 42)
 | |
|        (vector-push-extend n orig))
 | |
|      (let ((copy (copy-array orig
 | |
|                              :adjustable nil
 | |
|                              :fill-pointer nil)))
 | |
|        (typep copy 'simple-array)))
 | |
|  t)
 | |
| 
 | |
| (deftest array-index.1
 | |
|     (typep 0 'array-index)
 | |
|   t)
 | |
| 
 | |
| ;;;; Conditions
 | |
| 
 | |
| (deftest unwind-protect-case.1
 | |
|     (let (result)
 | |
|       (unwind-protect-case ()
 | |
|           (random 10)
 | |
|         (:normal (push :normal result))
 | |
|         (:abort  (push :abort result))
 | |
|         (:always (push :always result)))
 | |
|       result)
 | |
|   (:always :normal))
 | |
| 
 | |
| (deftest unwind-protect-case.2
 | |
|     (let (result)
 | |
|       (unwind-protect-case ()
 | |
|           (random 10)
 | |
|         (:always (push :always result))
 | |
|         (:normal (push :normal result))
 | |
|         (:abort  (push :abort result)))
 | |
|       result)
 | |
|   (:normal :always))
 | |
| 
 | |
| (deftest unwind-protect-case.3
 | |
|     (let (result1 result2 result3)
 | |
|       (ignore-errors
 | |
|         (unwind-protect-case ()
 | |
|             (error "FOOF!")
 | |
|           (:normal (push :normal result1))
 | |
|           (:abort  (push :abort result1))
 | |
|           (:always (push :always result1))))
 | |
|       (catch 'foof
 | |
|         (unwind-protect-case ()
 | |
|             (throw 'foof 42)
 | |
|           (:normal (push :normal result2))
 | |
|           (:abort  (push :abort result2))
 | |
|           (:always (push :always result2))))
 | |
|       (block foof
 | |
|         (unwind-protect-case ()
 | |
|             (return-from foof 42)
 | |
|           (:normal (push :normal result3))
 | |
|           (:abort  (push :abort result3))
 | |
|           (:always (push :always result3))))
 | |
|       (values result1 result2 result3))
 | |
|   (:always :abort)
 | |
|   (:always :abort)
 | |
|   (:always :abort))
 | |
| 
 | |
| (deftest unwind-protect-case.4
 | |
|     (let (result)
 | |
|       (unwind-protect-case (aborted-p)
 | |
|           (random 42)
 | |
|         (:always (setq result aborted-p)))
 | |
|       result)
 | |
|   nil)
 | |
| 
 | |
| (deftest unwind-protect-case.5
 | |
|     (let (result)
 | |
|       (block foof
 | |
|         (unwind-protect-case (aborted-p)
 | |
|             (return-from foof)
 | |
|           (:always (setq result aborted-p))))
 | |
|       result)
 | |
|   t)
 | |
| 
 | |
| ;;;; Control flow
 | |
| 
 | |
| (deftest switch.1
 | |
|     (switch (13 :test =)
 | |
|       (12 :oops)
 | |
|       (13.0 :yay))
 | |
|   :yay)
 | |
| 
 | |
| (deftest switch.2
 | |
|     (switch (13)
 | |
|       ((+ 12 2) :oops)
 | |
|       ((- 13 1) :oops2)
 | |
|       (t :yay))
 | |
|   :yay)
 | |
| 
 | |
| (deftest eswitch.1
 | |
|     (let ((x 13))
 | |
|       (eswitch (x :test =)
 | |
|         (12 :oops)
 | |
|         (13.0 :yay)))
 | |
|   :yay)
 | |
| 
 | |
| (deftest eswitch.2
 | |
|     (let ((x 13))
 | |
|       (eswitch (x :key 1+)
 | |
|         (11 :oops)
 | |
|         (14 :yay)))
 | |
|   :yay)
 | |
| 
 | |
| (deftest cswitch.1
 | |
|     (cswitch (13 :test =)
 | |
|       (12 :oops)
 | |
|       (13.0 :yay))
 | |
|   :yay)
 | |
| 
 | |
| (deftest cswitch.2
 | |
|     (cswitch (13 :key 1-)
 | |
|       (12 :yay)
 | |
|       (13.0 :oops))
 | |
|   :yay)
 | |
| 
 | |
| (deftest multiple-value-prog2.1
 | |
|     (multiple-value-prog2
 | |
|         (values 1 1 1)
 | |
|         (values 2 20 200)
 | |
|       (values 3 3 3))
 | |
|   2 20 200)
 | |
| 
 | |
| (deftest nth-value-or.1
 | |
|     (multiple-value-bind (a b c)
 | |
|         (nth-value-or 1
 | |
|                       (values 1 nil 1)
 | |
|                       (values 2 2 2))
 | |
|       (= a b c 2))
 | |
|   t)
 | |
| 
 | |
| (deftest whichever.1
 | |
|     (let ((x (whichever 1 2 3)))
 | |
|       (and (member x '(1 2 3)) t))
 | |
|   t)
 | |
| 
 | |
| (deftest whichever.2
 | |
|     (let* ((a 1)
 | |
|            (b 2)
 | |
|            (c 3)
 | |
|            (x (whichever a b c)))
 | |
|       (and (member x '(1 2 3)) t))
 | |
|   t)
 | |
| 
 | |
| (deftest xor.1
 | |
|     (xor nil nil 1 nil)
 | |
|   1
 | |
|   t)
 | |
| 
 | |
| (deftest xor.2
 | |
|     (xor nil nil 1 2)
 | |
|   nil
 | |
|   nil)
 | |
| 
 | |
| (deftest xor.3
 | |
|     (xor nil nil nil)
 | |
|   nil
 | |
|   t)
 | |
| 
 | |
| ;;;; Definitions
 | |
| 
 | |
| (deftest define-constant.1
 | |
|     (let ((name (gensym)))
 | |
|       (eval `(define-constant ,name "FOO" :test 'equal))
 | |
|       (eval `(define-constant ,name "FOO" :test 'equal))
 | |
|       (values (equal "FOO" (symbol-value name))
 | |
|               (constantp name)))
 | |
|   t
 | |
|   t)
 | |
| 
 | |
| (deftest define-constant.2
 | |
|     (let ((name (gensym)))
 | |
|       (eval `(define-constant ,name 13))
 | |
|       (eval `(define-constant ,name 13))
 | |
|       (values (eql 13 (symbol-value name))
 | |
|               (constantp name)))
 | |
|   t
 | |
|   t)
 | |
| 
 | |
| ;;;; Errors
 | |
| 
 | |
| ;;; TYPEP is specified to return a generalized boolean and, for
 | |
| ;;; example, ECL exploits this by returning the superclasses of ERROR
 | |
| ;;; in this case.
 | |
| (defun errorp (x)
 | |
|   (not (null (typep x 'error))))
 | |
| 
 | |
| (deftest required-argument.1
 | |
|     (multiple-value-bind (res err)
 | |
|         (ignore-errors (required-argument))
 | |
|       (errorp err))
 | |
|   t)
 | |
| 
 | |
| ;;;; Hash tables
 | |
| 
 | |
| (deftest ensure-gethash.1
 | |
|     (let ((table (make-hash-table))
 | |
|           (x (list 1)))
 | |
|       (multiple-value-bind (value already-there)
 | |
|           (ensure-gethash x table 42)
 | |
|         (and (= value 42)
 | |
|              (not already-there)
 | |
|              (= 42 (gethash x table))
 | |
|              (multiple-value-bind (value2 already-there2)
 | |
|                  (ensure-gethash x table 13)
 | |
|                (and (= value2 42)
 | |
|                     already-there2
 | |
|                     (= 42 (gethash x table)))))))
 | |
|   t)
 | |
| 
 | |
| (deftest ensure-gethash.2
 | |
|     (let ((table (make-hash-table))
 | |
|           (count 0))
 | |
|       (multiple-value-call #'values
 | |
|         (ensure-gethash (progn (incf count) :foo)
 | |
|                         (progn (incf count) table)
 | |
|                         (progn (incf count) :bar))
 | |
|         (gethash :foo table)
 | |
|         count))
 | |
|   :bar nil :bar t 3)
 | |
| 
 | |
| (deftest copy-hash-table.1
 | |
|     (let ((orig (make-hash-table :test 'eq :size 123))
 | |
|           (foo "foo"))
 | |
|       (setf (gethash orig orig) t
 | |
|             (gethash foo orig) t)
 | |
|       (let ((eq-copy (copy-hash-table orig))
 | |
|             (eql-copy (copy-hash-table orig :test 'eql))
 | |
|             (equal-copy (copy-hash-table orig :test 'equal))
 | |
|             (equalp-copy (copy-hash-table orig :test 'equalp)))
 | |
|         (list (eql (hash-table-size eq-copy) (hash-table-size orig))
 | |
|               (eql (hash-table-rehash-size eq-copy)
 | |
|                    (hash-table-rehash-size orig))
 | |
|               (hash-table-count eql-copy)
 | |
|               (gethash orig eq-copy)
 | |
|               (gethash (copy-seq foo) eql-copy)
 | |
|               (gethash foo eql-copy)
 | |
|               (gethash (copy-seq foo) equal-copy)
 | |
|               (gethash "FOO" equal-copy)
 | |
|               (gethash "FOO" equalp-copy))))
 | |
|   (t t 2 t nil t t nil t))
 | |
| 
 | |
| (deftest copy-hash-table.2
 | |
|     (let ((ht (make-hash-table))
 | |
|           (list (list :list (vector :A :B :C))))
 | |
|       (setf (gethash 'list ht) list)
 | |
|       (let* ((shallow-copy (copy-hash-table ht))
 | |
|              (deep1-copy (copy-hash-table ht :key 'copy-list))
 | |
|              (list         (gethash 'list ht))
 | |
|              (shallow-list (gethash 'list shallow-copy))
 | |
|              (deep1-list   (gethash 'list deep1-copy)))
 | |
|         (list (eq ht shallow-copy)
 | |
|               (eq ht deep1-copy)
 | |
|               (eq list shallow-list)
 | |
|               (eq list deep1-list)                   ; outer list was copied.
 | |
|               (eq (second list) (second shallow-list))
 | |
|               (eq (second list) (second deep1-list)) ; inner vector wasn't copied.
 | |
|               )))
 | |
|   (nil nil t nil t t))
 | |
| 
 | |
| (deftest maphash-keys.1
 | |
|     (let ((keys nil)
 | |
|           (table (make-hash-table)))
 | |
|       (declare (notinline maphash-keys))
 | |
|       (dotimes (i 10)
 | |
|         (setf (gethash i table) t))
 | |
|       (maphash-keys (lambda (k) (push k keys)) table)
 | |
|       (set-equal keys '(0 1 2 3 4 5 6 7 8 9)))
 | |
|   t)
 | |
| 
 | |
| (deftest maphash-values.1
 | |
|     (let ((vals nil)
 | |
|           (table (make-hash-table)))
 | |
|       (declare (notinline maphash-values))
 | |
|       (dotimes (i 10)
 | |
|         (setf (gethash i table) (- i)))
 | |
|       (maphash-values (lambda (v) (push v vals)) table)
 | |
|       (set-equal vals '(0 -1 -2 -3 -4 -5 -6 -7 -8 -9)))
 | |
|   t)
 | |
| 
 | |
| (deftest hash-table-keys.1
 | |
|     (let ((table (make-hash-table)))
 | |
|       (dotimes (i 10)
 | |
|         (setf (gethash i table) t))
 | |
|       (set-equal (hash-table-keys table) '(0 1 2 3 4 5 6 7 8 9)))
 | |
|   t)
 | |
| 
 | |
| (deftest hash-table-values.1
 | |
|     (let ((table (make-hash-table)))
 | |
|       (dotimes (i 10)
 | |
|         (setf (gethash (gensym) table) i))
 | |
|       (set-equal (hash-table-values table) '(0 1 2 3 4 5 6 7 8 9)))
 | |
|   t)
 | |
| 
 | |
| (deftest hash-table-alist.1
 | |
|     (let ((table (make-hash-table)))
 | |
|       (dotimes (i 10)
 | |
|         (setf (gethash i table) (- i)))
 | |
|       (let ((alist (hash-table-alist table)))
 | |
|         (list (length alist)
 | |
|               (assoc 0 alist)
 | |
|               (assoc 3 alist)
 | |
|               (assoc 9 alist)
 | |
|               (assoc nil alist))))
 | |
|   (10 (0 . 0) (3 . -3) (9 . -9) nil))
 | |
| 
 | |
| (deftest hash-table-plist.1
 | |
|     (let ((table (make-hash-table)))
 | |
|       (dotimes (i 10)
 | |
|         (setf (gethash i table) (- i)))
 | |
|       (let ((plist (hash-table-plist table)))
 | |
|         (list (length plist)
 | |
|               (getf plist 0)
 | |
|               (getf plist 2)
 | |
|               (getf plist 7)
 | |
|               (getf plist nil))))
 | |
|   (20 0 -2 -7 nil))
 | |
| 
 | |
| (deftest alist-hash-table.1
 | |
|     (let* ((alist '((0 a) (1 b) (2 c)))
 | |
|            (table (alist-hash-table alist)))
 | |
|       (list (hash-table-count table)
 | |
|             (gethash 0 table)
 | |
|             (gethash 1 table)
 | |
|             (gethash 2 table)
 | |
|             (eq (hash-table-test-name 'eql)
 | |
|                 (hash-table-test table))))
 | |
|   (3 (a) (b) (c) t))
 | |
| 
 | |
| (deftest alist-hash-table.duplicate-keys
 | |
|     (let* ((alist '((0 a) (1 b) (0 c) (1 d) (2 e)))
 | |
|            (table (alist-hash-table alist)))
 | |
|       (list (hash-table-count table)
 | |
|             (gethash 0 table)
 | |
|             (gethash 1 table)
 | |
|             (gethash 2 table)))
 | |
|   (3 (a) (b) (e)))
 | |
| 
 | |
| (deftest plist-hash-table.1
 | |
|     (let* ((plist '(:a 1 :b 2 :c 3))
 | |
|            (table (plist-hash-table plist :test 'eq)))
 | |
|       (list (hash-table-count table)
 | |
|             (gethash :a table)
 | |
|             (gethash :b table)
 | |
|             (gethash :c table)
 | |
|             (gethash 2 table)
 | |
|             (gethash nil table)
 | |
|             (eq (hash-table-test-name 'eq)
 | |
|                 (hash-table-test table))))
 | |
|   (3 1 2 3 nil nil t))
 | |
| 
 | |
| (deftest plist-hash-table.duplicate-keys
 | |
|     (let* ((plist '(:a 1 :b 2 :a 3 :b 4 :c 5))
 | |
|            (table (plist-hash-table plist)))
 | |
|       (list (hash-table-count table)
 | |
|             (gethash :a table)
 | |
|             (gethash :b table)
 | |
|             (gethash :c table)))
 | |
|   (3 1 2 5))
 | |
| 
 | |
| ;;;; Functions
 | |
| 
 | |
| (deftest disjoin.1
 | |
|     (let ((disjunction (disjoin (lambda (x)
 | |
|                                   (and (consp x) :cons))
 | |
|                                 (lambda (x)
 | |
|                                   (and (stringp x) :string)))))
 | |
|       (list (funcall disjunction 'zot)
 | |
|             (funcall disjunction '(foo bar))
 | |
|             (funcall disjunction "test")))
 | |
|   (nil :cons :string))
 | |
| 
 | |
| (deftest disjoin.2
 | |
|     (let ((disjunction (disjoin #'zerop)))
 | |
|       (list (funcall disjunction 0)
 | |
|             (funcall disjunction 1)))
 | |
|   (t nil))
 | |
| 
 | |
| (deftest conjoin.1
 | |
|     (let ((conjunction (conjoin #'consp
 | |
|                                 (lambda (x)
 | |
|                                   (stringp (car x)))
 | |
|                                 (lambda (x)
 | |
|                                   (char (car x) 0)))))
 | |
|       (list (funcall conjunction 'zot)
 | |
|             (funcall conjunction '(foo))
 | |
|             (funcall conjunction '("foo"))))
 | |
|   (nil nil #\f))
 | |
| 
 | |
| (deftest conjoin.2
 | |
|     (let ((conjunction (conjoin #'zerop)))
 | |
|       (list (funcall conjunction 0)
 | |
|             (funcall conjunction 1)))
 | |
|   (t nil))
 | |
| 
 | |
| (deftest compose.1
 | |
|     (let ((composite (compose '1+
 | |
|                               (lambda (x)
 | |
|                                 (* x 2))
 | |
|                               #'read-from-string)))
 | |
|       (funcall composite "1"))
 | |
|   3)
 | |
| 
 | |
| (deftest compose.2
 | |
|     (let ((composite
 | |
|            (locally (declare (notinline compose))
 | |
|              (compose '1+
 | |
|                       (lambda (x)
 | |
|                         (* x 2))
 | |
|                       #'read-from-string))))
 | |
|       (funcall composite "2"))
 | |
|   5)
 | |
| 
 | |
| (deftest compose.3
 | |
|     (let ((compose-form (funcall (compiler-macro-function 'compose)
 | |
|                                  '(compose '1+
 | |
|                                    (lambda (x)
 | |
|                                      (* x 2))
 | |
|                                    #'read-from-string)
 | |
|                                  nil)))
 | |
|       (let ((fun (funcall (compile nil `(lambda () ,compose-form)))))
 | |
|         (funcall fun "3")))
 | |
|   7)
 | |
| 
 | |
| (deftest compose.4
 | |
|     (let ((composite (compose #'zerop)))
 | |
|       (list (funcall composite 0)
 | |
|             (funcall composite 1)))
 | |
|   (t nil))
 | |
| 
 | |
| (deftest multiple-value-compose.1
 | |
|     (let ((composite (multiple-value-compose
 | |
|                       #'truncate
 | |
|                       (lambda (x y)
 | |
|                         (values y x))
 | |
|                       (lambda (x)
 | |
|                         (with-input-from-string (s x)
 | |
|                           (values (read s) (read s)))))))
 | |
|       (multiple-value-list (funcall composite "2 7")))
 | |
|   (3 1))
 | |
| 
 | |
| (deftest multiple-value-compose.2
 | |
|     (let ((composite (locally (declare (notinline multiple-value-compose))
 | |
|                        (multiple-value-compose
 | |
|                         #'truncate
 | |
|                         (lambda (x y)
 | |
|                           (values y x))
 | |
|                        (lambda (x)
 | |
|                          (with-input-from-string (s x)
 | |
|                            (values (read s) (read s))))))))
 | |
|       (multiple-value-list (funcall composite "2 11")))
 | |
|   (5 1))
 | |
| 
 | |
| (deftest multiple-value-compose.3
 | |
|     (let ((compose-form (funcall (compiler-macro-function 'multiple-value-compose)
 | |
|                                  '(multiple-value-compose
 | |
|                                    #'truncate
 | |
|                                    (lambda (x y)
 | |
|                                      (values y x))
 | |
|                                    (lambda (x)
 | |
|                                      (with-input-from-string (s x)
 | |
|                                        (values (read s) (read s)))))
 | |
|                                  nil)))
 | |
|       (let ((fun (funcall (compile nil `(lambda () ,compose-form)))))
 | |
|         (multiple-value-list (funcall fun "2 9"))))
 | |
|   (4 1))
 | |
| 
 | |
| (deftest multiple-value-compose.4
 | |
|     (let ((composite (multiple-value-compose #'truncate)))
 | |
|       (multiple-value-list (funcall composite 9 2)))
 | |
|   (4 1))
 | |
| 
 | |
| (deftest curry.1
 | |
|     (let ((curried (curry '+ 3)))
 | |
|       (funcall curried 1 5))
 | |
|   9)
 | |
| 
 | |
| (deftest curry.2
 | |
|     (let ((curried (locally (declare (notinline curry))
 | |
|                      (curry '* 2 3))))
 | |
|       (funcall curried 7))
 | |
|   42)
 | |
| 
 | |
| (deftest curry.3
 | |
|     (let ((curried-form (funcall (compiler-macro-function 'curry)
 | |
|                                  '(curry '/ 8)
 | |
|                                  nil)))
 | |
|       (let ((fun (funcall (compile nil `(lambda () ,curried-form)))))
 | |
|         (funcall fun 2)))
 | |
|   4)
 | |
| 
 | |
| (deftest curry.4
 | |
|     (let* ((x 1)
 | |
|            (curried (curry (progn
 | |
|                              (incf x)
 | |
|                              (lambda (y z) (* x y z)))
 | |
|                            3)))
 | |
|       (list (funcall curried 7)
 | |
|             (funcall curried 7)
 | |
|             x))
 | |
|   (42 42 2))
 | |
| 
 | |
| (deftest rcurry.1
 | |
|     (let ((r (rcurry '/ 2)))
 | |
|       (funcall r 8))
 | |
|   4)
 | |
| 
 | |
| (deftest rcurry.2
 | |
|     (let* ((x 1)
 | |
|            (curried (rcurry (progn
 | |
|                               (incf x)
 | |
|                               (lambda (y z) (* x y z)))
 | |
|                             3)))
 | |
|       (list (funcall curried 7)
 | |
|             (funcall curried 7)
 | |
|             x))
 | |
|   (42 42 2))
 | |
| 
 | |
| (deftest named-lambda.1
 | |
|     (let ((fac (named-lambda fac (x)
 | |
|                  (if (> x 1)
 | |
|                      (* x (fac (- x 1)))
 | |
|                      x))))
 | |
|       (funcall fac 5))
 | |
|   120)
 | |
| 
 | |
| (deftest named-lambda.2
 | |
|     (let ((fac (named-lambda fac (&key x)
 | |
|                  (if (> x 1)
 | |
|                      (* x (fac :x (- x 1)))
 | |
|                      x))))
 | |
|       (funcall fac :x 5))
 | |
|   120)
 | |
| 
 | |
| ;;;; Lists
 | |
| 
 | |
| (deftest alist-plist.1
 | |
|     (alist-plist '((a . 1) (b . 2) (c . 3)))
 | |
|   (a 1 b 2 c 3))
 | |
| 
 | |
| (deftest plist-alist.1
 | |
|     (plist-alist '(a 1 b 2 c 3))
 | |
|   ((a . 1) (b . 2) (c . 3)))
 | |
| 
 | |
| (deftest unionf.1
 | |
|     (let* ((list (list 1 2 3))
 | |
|            (orig list))
 | |
|       (unionf list (list 1 2 4))
 | |
|       (values (equal orig (list 1 2 3))
 | |
|               (eql (length list) 4)
 | |
|               (set-difference list (list 1 2 3 4))
 | |
|               (set-difference (list 1 2 3 4) list)))
 | |
|   t
 | |
|   t
 | |
|   nil
 | |
|   nil)
 | |
| 
 | |
| (deftest nunionf.1
 | |
|     (let ((list (list 1 2 3)))
 | |
|       (nunionf list (list 1 2 4))
 | |
|       (values (eql (length list) 4)
 | |
|               (set-difference (list 1 2 3 4) list)
 | |
|               (set-difference list (list 1 2 3 4))))
 | |
|   t
 | |
|   nil
 | |
|   nil)
 | |
| 
 | |
| (deftest appendf.1
 | |
|     (let* ((list (list 1 2 3))
 | |
|            (orig list))
 | |
|       (appendf list '(4 5 6) '(7 8))
 | |
|       (list list (eq list orig)))
 | |
|   ((1 2 3 4 5 6 7 8) nil))
 | |
| 
 | |
| (deftest nconcf.1
 | |
|     (let ((list1 (list 1 2 3))
 | |
|           (list2 (list 4 5 6)))
 | |
|       (nconcf list1 list2 (list 7 8 9))
 | |
|       list1)
 | |
|   (1 2 3 4 5 6 7 8 9))
 | |
| 
 | |
| (deftest circular-list.1
 | |
|     (let ((circle (circular-list 1 2 3)))
 | |
|       (list (first circle)
 | |
|             (second circle)
 | |
|             (third circle)
 | |
|             (fourth circle)
 | |
|             (eq circle (nthcdr 3 circle))))
 | |
|   (1 2 3 1 t))
 | |
| 
 | |
| (deftest circular-list-p.1
 | |
|     (let* ((circle (circular-list 1 2 3 4))
 | |
|            (tree (list circle circle))
 | |
|            (dotted (cons circle t))
 | |
|            (proper (list 1 2 3 circle))
 | |
|            (tailcirc (list* 1 2 3 circle)))
 | |
|       (list (circular-list-p circle)
 | |
|             (circular-list-p tree)
 | |
|             (circular-list-p dotted)
 | |
|             (circular-list-p proper)
 | |
|             (circular-list-p tailcirc)))
 | |
|   (t nil nil nil t))
 | |
| 
 | |
| (deftest circular-list-p.2
 | |
|     (circular-list-p 'foo)
 | |
|   nil)
 | |
| 
 | |
| (deftest circular-tree-p.1
 | |
|     (let* ((circle (circular-list 1 2 3 4))
 | |
|            (tree1 (list circle circle))
 | |
|            (tree2 (let* ((level2 (list 1 nil 2))
 | |
|                          (level1 (list level2)))
 | |
|                     (setf (second level2) level1)
 | |
|                     level1))
 | |
|            (dotted (cons circle t))
 | |
|            (proper (list 1 2 3 circle))
 | |
|            (tailcirc (list* 1 2 3 circle))
 | |
|            (quite-proper (list 1 2 3))
 | |
|            (quite-dotted (list 1 (cons 2 3))))
 | |
|       (list (circular-tree-p circle)
 | |
|             (circular-tree-p tree1)
 | |
|             (circular-tree-p tree2)
 | |
|             (circular-tree-p dotted)
 | |
|             (circular-tree-p proper)
 | |
|             (circular-tree-p tailcirc)
 | |
|             (circular-tree-p quite-proper)
 | |
|             (circular-tree-p quite-dotted)))
 | |
|   (t t t t t t nil nil))
 | |
| 
 | |
| (deftest circular-tree-p.2
 | |
|     (alexandria:circular-tree-p '#1=(#1#))
 | |
|   t)
 | |
| 
 | |
| (deftest proper-list-p.1
 | |
|     (let ((l1 (list 1))
 | |
|           (l2 (list 1 2))
 | |
|           (l3 (cons 1 2))
 | |
|           (l4 (list (cons 1 2) 3))
 | |
|           (l5 (circular-list 1 2)))
 | |
|       (list (proper-list-p l1)
 | |
|             (proper-list-p l2)
 | |
|             (proper-list-p l3)
 | |
|             (proper-list-p l4)
 | |
|             (proper-list-p l5)))
 | |
|   (t t nil t nil))
 | |
| 
 | |
| (deftest proper-list-p.2
 | |
|     (proper-list-p '(1 2 . 3))
 | |
|   nil)
 | |
| 
 | |
| (deftest proper-list.type.1
 | |
|     (let ((l1 (list 1))
 | |
|           (l2 (list 1 2))
 | |
|           (l3 (cons 1 2))
 | |
|           (l4 (list (cons 1 2) 3))
 | |
|           (l5 (circular-list 1 2)))
 | |
|       (list (typep l1 'proper-list)
 | |
|             (typep l2 'proper-list)
 | |
|             (typep l3 'proper-list)
 | |
|             (typep l4 'proper-list)
 | |
|             (typep l5 'proper-list)))
 | |
|   (t t nil t nil))
 | |
| 
 | |
| (deftest proper-list-length.1
 | |
|     (values
 | |
|      (proper-list-length nil)
 | |
|      (proper-list-length (list 1))
 | |
|      (proper-list-length (list 2 2))
 | |
|      (proper-list-length (list 3 3 3))
 | |
|      (proper-list-length (list 4 4 4 4))
 | |
|      (proper-list-length (list 5 5 5 5 5))
 | |
|      (proper-list-length (list 6 6 6 6 6 6))
 | |
|      (proper-list-length (list 7 7 7 7 7 7 7))
 | |
|      (proper-list-length (list 8 8 8 8 8 8 8 8))
 | |
|      (proper-list-length (list 9 9 9 9 9 9 9 9 9)))
 | |
|   0 1 2 3 4 5 6 7 8 9)
 | |
| 
 | |
| (deftest proper-list-length.2
 | |
|     (flet ((plength (x)
 | |
|              (handler-case
 | |
|                  (proper-list-length x)
 | |
|                (type-error ()
 | |
|                  :ok))))
 | |
|       (values
 | |
|        (plength (list* 1))
 | |
|        (plength (list* 2 2))
 | |
|        (plength (list* 3 3 3))
 | |
|        (plength (list* 4 4 4 4))
 | |
|        (plength (list* 5 5 5 5 5))
 | |
|        (plength (list* 6 6 6 6 6 6))
 | |
|        (plength (list* 7 7 7 7 7 7 7))
 | |
|        (plength (list* 8 8 8 8 8 8 8 8))
 | |
|        (plength (list* 9 9 9 9 9 9 9 9 9))))
 | |
|   :ok :ok :ok
 | |
|   :ok :ok :ok
 | |
|   :ok :ok :ok)
 | |
| 
 | |
| (deftest lastcar.1
 | |
|     (let ((l1 (list 1))
 | |
|           (l2 (list 1 2)))
 | |
|       (list (lastcar l1)
 | |
|             (lastcar l2)))
 | |
|   (1 2))
 | |
| 
 | |
| (deftest lastcar.error.2
 | |
|     (handler-case
 | |
|         (progn
 | |
|           (lastcar (circular-list 1 2 3))
 | |
|           nil)
 | |
|       (error ()
 | |
|         t))
 | |
|   t)
 | |
| 
 | |
| (deftest setf-lastcar.1
 | |
|     (let ((l (list 1 2 3 4)))
 | |
|       (values (lastcar l)
 | |
|               (progn
 | |
|                 (setf (lastcar l) 42)
 | |
|                 (lastcar l))))
 | |
|   4
 | |
|   42)
 | |
| 
 | |
| (deftest setf-lastcar.2
 | |
|     (let ((l (circular-list 1 2 3)))
 | |
|       (multiple-value-bind (res err)
 | |
|           (ignore-errors (setf (lastcar l) 4))
 | |
|         (typep err 'type-error)))
 | |
|   t)
 | |
| 
 | |
| (deftest make-circular-list.1
 | |
|     (let ((l (make-circular-list 3 :initial-element :x)))
 | |
|       (setf (car l) :y)
 | |
|       (list (eq l (nthcdr 3 l))
 | |
|             (first l)
 | |
|             (second l)
 | |
|             (third l)
 | |
|             (fourth l)))
 | |
|   (t :y :x :x :y))
 | |
| 
 | |
| (deftest circular-list.type.1
 | |
|     (let* ((l1 (list 1 2 3))
 | |
|            (l2 (circular-list 1 2 3))
 | |
|            (l3 (list* 1 2 3 l2)))
 | |
|       (list (typep l1 'circular-list)
 | |
|             (typep l2 'circular-list)
 | |
|             (typep l3 'circular-list)))
 | |
|   (nil t t))
 | |
| 
 | |
| (deftest ensure-list.1
 | |
|     (let ((x (list 1))
 | |
|           (y 2))
 | |
|       (list (ensure-list x)
 | |
|             (ensure-list y)))
 | |
|   ((1) (2)))
 | |
| 
 | |
| (deftest ensure-cons.1
 | |
|     (let ((x (cons 1 2))
 | |
|           (y nil)
 | |
|           (z "foo"))
 | |
|       (values (ensure-cons x)
 | |
|               (ensure-cons y)
 | |
|               (ensure-cons z)))
 | |
|   (1 . 2)
 | |
|   (nil)
 | |
|   ("foo"))
 | |
| 
 | |
| (deftest setp.1
 | |
|     (setp '(1))
 | |
|   t)
 | |
| 
 | |
| (deftest setp.2
 | |
|     (setp nil)
 | |
|   t)
 | |
| 
 | |
| (deftest setp.3
 | |
|     (setp "foo")
 | |
|   nil)
 | |
| 
 | |
| (deftest setp.4
 | |
|     (setp '(1 2 3 1))
 | |
|   nil)
 | |
| 
 | |
| (deftest setp.5
 | |
|     (setp '(1 2 3))
 | |
|   t)
 | |
| 
 | |
| (deftest setp.6
 | |
|     (setp '(a :a))
 | |
|   t)
 | |
| 
 | |
| (deftest setp.7
 | |
|     (setp '(a :a) :key 'character)
 | |
|   nil)
 | |
| 
 | |
| (deftest setp.8
 | |
|     (setp '(a :a) :key 'character :test (constantly nil))
 | |
|   t)
 | |
| 
 | |
| (deftest set-equal.1
 | |
|     (set-equal '(1 2 3) '(3 1 2))
 | |
|   t)
 | |
| 
 | |
| (deftest set-equal.2
 | |
|     (set-equal '("Xa") '("Xb")
 | |
|                :test (lambda (a b) (eql (char a 0) (char b 0))))
 | |
|   t)
 | |
| 
 | |
| (deftest set-equal.3
 | |
|     (set-equal '(1 2) '(4 2))
 | |
|   nil)
 | |
| 
 | |
| (deftest set-equal.4
 | |
|     (set-equal '(a b c) '(:a :b :c) :key 'string :test 'equal)
 | |
|   t)
 | |
| 
 | |
| (deftest set-equal.5
 | |
|     (set-equal '(a d c) '(:a :b :c) :key 'string :test 'equal)
 | |
|   nil)
 | |
| 
 | |
| (deftest set-equal.6
 | |
|     (set-equal '(a b c) '(a b c d))
 | |
|   nil)
 | |
| 
 | |
| (deftest map-product.1
 | |
|     (map-product 'cons '(2 3) '(1 4))
 | |
|   ((2 . 1) (2 . 4) (3 . 1) (3 . 4)))
 | |
| 
 | |
| (deftest map-product.2
 | |
|     (map-product #'cons '(2 3) '(1 4))
 | |
|   ((2 . 1) (2 . 4) (3 . 1) (3 . 4)))
 | |
| 
 | |
| (deftest flatten.1
 | |
|     (flatten '((1) 2 (((3 4))) ((((5)) 6)) 7))
 | |
|   (1 2 3 4 5 6 7))
 | |
| 
 | |
| (deftest remove-from-plist.1
 | |
|     (let ((orig '(a 1 b 2 c 3 d 4)))
 | |
|       (list (remove-from-plist orig 'a 'c)
 | |
|             (remove-from-plist orig 'b 'd)
 | |
|             (remove-from-plist orig 'b)
 | |
|             (remove-from-plist orig 'a)
 | |
|             (remove-from-plist orig 'd 42 "zot")
 | |
|             (remove-from-plist orig 'a 'b 'c 'd)
 | |
|             (remove-from-plist orig 'a 'b 'c 'd 'x)
 | |
|             (equal orig '(a 1 b 2 c 3 d 4))))
 | |
|   ((b 2 d 4)
 | |
|    (a 1 c 3)
 | |
|    (a 1 c 3 d 4)
 | |
|    (b 2 c 3 d 4)
 | |
|    (a 1 b 2 c 3)
 | |
|    nil
 | |
|    nil
 | |
|    t))
 | |
| 
 | |
| (deftest delete-from-plist.1
 | |
|     (let ((orig '(a 1 b 2 c 3 d 4 d 5)))
 | |
|       (list (delete-from-plist (copy-list orig) 'a 'c)
 | |
|             (delete-from-plist (copy-list orig) 'b 'd)
 | |
|             (delete-from-plist (copy-list orig) 'b)
 | |
|             (delete-from-plist (copy-list orig) 'a)
 | |
|             (delete-from-plist (copy-list orig) 'd 42 "zot")
 | |
|             (delete-from-plist (copy-list orig) 'a 'b 'c 'd)
 | |
|             (delete-from-plist (copy-list orig) 'a 'b 'c 'd 'x)
 | |
|             (equal orig (delete-from-plist orig))
 | |
|             (eq orig (delete-from-plist orig))))
 | |
|   ((b 2 d 4 d 5)
 | |
|    (a 1 c 3)
 | |
|    (a 1 c 3 d 4 d 5)
 | |
|    (b 2 c 3 d 4 d 5)
 | |
|    (a 1 b 2 c 3)
 | |
|    nil
 | |
|    nil
 | |
|    t
 | |
|    t))
 | |
| 
 | |
| (deftest mappend.1
 | |
|     (mappend (compose 'list '*) '(1 2 3) '(1 2 3))
 | |
|   (1 4 9))
 | |
| 
 | |
| (deftest assoc-value.1
 | |
|     (let ((key1 '(complex key))
 | |
|           (key2 'simple-key)
 | |
|           (alist '())
 | |
|           (result '()))
 | |
|       (push 1 (assoc-value alist key1 :test #'equal))
 | |
|       (push 2 (assoc-value alist key1 :test 'equal))
 | |
|       (push 42 (assoc-value alist key2))
 | |
|       (push 43 (assoc-value alist key2 :test 'eq))
 | |
|       (push (assoc-value alist key1 :test #'equal) result)
 | |
|       (push (assoc-value alist key2) result)
 | |
| 
 | |
|       (push 'very (rassoc-value alist (list 2 1) :test #'equal))
 | |
|       (push (cdr (assoc '(very complex key) alist :test #'equal)) result)
 | |
|       result)
 | |
|   ((2 1) (43 42) (2 1)))
 | |
| 
 | |
| ;;;; Numbers
 | |
| 
 | |
| (deftest clamp.1
 | |
|     (list (clamp 1.5 1 2)
 | |
|           (clamp 2.0 1 2)
 | |
|           (clamp 1.0 1 2)
 | |
|           (clamp 3 1 2)
 | |
|           (clamp 0 1 2))
 | |
|   (1.5 2.0 1.0 2 1))
 | |
| 
 | |
| (deftest gaussian-random.1
 | |
|     (let ((min -0.2)
 | |
|           (max +0.2))
 | |
|       (multiple-value-bind (g1 g2)
 | |
|           (gaussian-random min max)
 | |
|         (values (<= min g1 max)
 | |
|                 (<= min g2 max)
 | |
|                 (/= g1 g2) ;uh
 | |
|                 )))
 | |
|   t
 | |
|   t
 | |
|   t)
 | |
| 
 | |
| #+sbcl
 | |
| (deftest gaussian-random.2
 | |
|     (handler-case
 | |
|         (sb-ext:with-timeout 2
 | |
|           (progn
 | |
|             (loop
 | |
|               :repeat 10000
 | |
|               :do (gaussian-random 0 nil))
 | |
|             'done))
 | |
|       (sb-ext:timeout ()
 | |
|         'timed-out))
 | |
|   done)
 | |
| 
 | |
| (deftest iota.1
 | |
|     (iota 3)
 | |
|   (0 1 2))
 | |
| 
 | |
| (deftest iota.2
 | |
|     (iota 3 :start 0.0d0)
 | |
|   (0.0d0 1.0d0 2.0d0))
 | |
| 
 | |
| (deftest iota.3
 | |
|     (iota 3 :start 2 :step 3.0)
 | |
|   (2.0 5.0 8.0))
 | |
| 
 | |
| (deftest map-iota.1
 | |
|     (let (all)
 | |
|       (declare (notinline map-iota))
 | |
|       (values (map-iota (lambda (x) (push x all))
 | |
|                         3
 | |
|                         :start 2
 | |
|                         :step 1.1d0)
 | |
|               all))
 | |
|   3
 | |
|   (4.2d0 3.1d0 2.0d0))
 | |
| 
 | |
| (deftest lerp.1
 | |
|     (lerp 0.5 1 2)
 | |
|   1.5)
 | |
| 
 | |
| (deftest lerp.2
 | |
|     (lerp 0.1 1 2)
 | |
|   1.1)
 | |
| 
 | |
| (deftest lerp.3
 | |
|     (lerp 0.1 4 25)
 | |
|   6.1)
 | |
| 
 | |
| (deftest mean.1
 | |
|     (mean '(1 2 3))
 | |
|   2)
 | |
| 
 | |
| (deftest mean.2
 | |
|     (mean '(1 2 3 4))
 | |
|   5/2)
 | |
| 
 | |
| (deftest mean.3
 | |
|     (mean '(1 2 10))
 | |
|   13/3)
 | |
| 
 | |
| (deftest median.1
 | |
|     (median '(100 0 99 1 98 2 97))
 | |
|   97)
 | |
| 
 | |
| (deftest median.2
 | |
|     (median '(100 0 99 1 98 2 97 96))
 | |
|   193/2)
 | |
| 
 | |
| (deftest variance.1
 | |
|     (variance (list 1 2 3))
 | |
|   2/3)
 | |
| 
 | |
| (deftest standard-deviation.1
 | |
|     (< 0 (standard-deviation (list 1 2 3)) 1)
 | |
|   t)
 | |
| 
 | |
| (deftest maxf.1
 | |
|     (let ((x 1))
 | |
|       (maxf x 2)
 | |
|       x)
 | |
|   2)
 | |
| 
 | |
| (deftest maxf.2
 | |
|     (let ((x 1))
 | |
|       (maxf x 0)
 | |
|       x)
 | |
|   1)
 | |
| 
 | |
| (deftest maxf.3
 | |
|     (let ((x 1)
 | |
|           (c 0))
 | |
|       (maxf x (incf c))
 | |
|       (list x c))
 | |
|   (1 1))
 | |
| 
 | |
| (deftest maxf.4
 | |
|     (let ((xv (vector 0 0 0))
 | |
|           (p 0))
 | |
|       (maxf (svref xv (incf p)) (incf p))
 | |
|       (list p xv))
 | |
|   (2 #(0 2 0)))
 | |
| 
 | |
| (deftest minf.1
 | |
|     (let ((y 1))
 | |
|       (minf y 0)
 | |
|       y)
 | |
|   0)
 | |
| 
 | |
| (deftest minf.2
 | |
|     (let ((xv (vector 10 10 10))
 | |
|           (p 0))
 | |
|       (minf (svref xv (incf p)) (incf p))
 | |
|       (list p xv))
 | |
|   (2 #(10 2 10)))
 | |
| 
 | |
| (deftest subfactorial.1
 | |
|     (mapcar #'subfactorial (iota 22))
 | |
|   (1
 | |
|    0
 | |
|    1
 | |
|    2
 | |
|    9
 | |
|    44
 | |
|    265
 | |
|    1854
 | |
|    14833
 | |
|    133496
 | |
|    1334961
 | |
|    14684570
 | |
|    176214841
 | |
|    2290792932
 | |
|    32071101049
 | |
|    481066515734
 | |
|    7697064251745
 | |
|    130850092279664
 | |
|    2355301661033953
 | |
|    44750731559645106
 | |
|    895014631192902121
 | |
|    18795307255050944540))
 | |
| 
 | |
| ;;;; Arrays
 | |
| 
 | |
| #+nil
 | |
| (deftest array-index.type)
 | |
| 
 | |
| #+nil
 | |
| (deftest copy-array)
 | |
| 
 | |
| ;;;; Sequences
 | |
| 
 | |
| (deftest rotate.1
 | |
|     (list (rotate (list 1 2 3) 0)
 | |
|           (rotate (list 1 2 3) 1)
 | |
|           (rotate (list 1 2 3) 2)
 | |
|           (rotate (list 1 2 3) 3)
 | |
|           (rotate (list 1 2 3) 4))
 | |
|   ((1 2 3)
 | |
|    (3 1 2)
 | |
|    (2 3 1)
 | |
|    (1 2 3)
 | |
|    (3 1 2)))
 | |
| 
 | |
| (deftest rotate.2
 | |
|     (list (rotate (vector 1 2 3 4) 0)
 | |
|           (rotate (vector 1 2 3 4))
 | |
|           (rotate (vector 1 2 3 4) 2)
 | |
|           (rotate (vector 1 2 3 4) 3)
 | |
|           (rotate (vector 1 2 3 4) 4)
 | |
|           (rotate (vector 1 2 3 4) 5))
 | |
|   (#(1 2 3 4)
 | |
|     #(4 1 2 3)
 | |
|     #(3 4 1 2)
 | |
|     #(2 3 4 1)
 | |
|     #(1 2 3 4)
 | |
|     #(4 1 2 3)))
 | |
| 
 | |
| (deftest rotate.3
 | |
|     (list (rotate (list 1 2 3) 0)
 | |
|           (rotate (list 1 2 3) -1)
 | |
|           (rotate (list 1 2 3) -2)
 | |
|           (rotate (list 1 2 3) -3)
 | |
|           (rotate (list 1 2 3) -4))
 | |
|   ((1 2 3)
 | |
|    (2 3 1)
 | |
|    (3 1 2)
 | |
|    (1 2 3)
 | |
|    (2 3 1)))
 | |
| 
 | |
| (deftest rotate.4
 | |
|     (list (rotate (vector 1 2 3 4) 0)
 | |
|           (rotate (vector 1 2 3 4) -1)
 | |
|           (rotate (vector 1 2 3 4) -2)
 | |
|           (rotate (vector 1 2 3 4) -3)
 | |
|           (rotate (vector 1 2 3 4) -4)
 | |
|           (rotate (vector 1 2 3 4) -5))
 | |
|   (#(1 2 3 4)
 | |
|    #(2 3 4 1)
 | |
|    #(3 4 1 2)
 | |
|    #(4 1 2 3)
 | |
|    #(1 2 3 4)
 | |
|    #(2 3 4 1)))
 | |
| 
 | |
| (deftest rotate.5
 | |
|     (values (rotate (list 1) 17)
 | |
|             (rotate (list 1) -5))
 | |
|   (1)
 | |
|   (1))
 | |
| 
 | |
| (deftest shuffle.1
 | |
|     (let ((s (shuffle (iota 100))))
 | |
|       (list (equal s (iota 100))
 | |
|             (every (lambda (x)
 | |
|                      (member x s))
 | |
|                    (iota 100))
 | |
|             (every (lambda (x)
 | |
|                      (typep x '(integer 0 99)))
 | |
|                    s)))
 | |
|   (nil t t))
 | |
| 
 | |
| (deftest shuffle.2
 | |
|     (let ((s (shuffle (coerce (iota 100) 'vector))))
 | |
|       (list (equal s (coerce (iota 100) 'vector))
 | |
|             (every (lambda (x)
 | |
|                      (find x s))
 | |
|                    (iota 100))
 | |
|             (every (lambda (x)
 | |
|                      (typep x '(integer 0 99)))
 | |
|                    s)))
 | |
|   (nil t t))
 | |
| 
 | |
| (deftest shuffle.3
 | |
|     (let* ((orig (coerce (iota 21) 'vector))
 | |
|            (copy (copy-seq orig)))
 | |
|       (shuffle copy :start 10 :end 15)
 | |
|       (list (every #'eql (subseq copy 0 10) (subseq orig 0 10))
 | |
|             (every #'eql (subseq copy 15) (subseq orig 15))))
 | |
|   (t t))
 | |
| 
 | |
| (deftest random-elt.1
 | |
|     (let ((s1 #(1 2 3 4))
 | |
|           (s2 '(1 2 3 4)))
 | |
|       (list (dotimes (i 1000 nil)
 | |
|               (unless (member (random-elt s1) s2)
 | |
|                 (return nil))
 | |
|               (when (/= (random-elt s1) (random-elt s1))
 | |
|                 (return t)))
 | |
|             (dotimes (i 1000 nil)
 | |
|               (unless (member (random-elt s2) s2)
 | |
|                 (return nil))
 | |
|               (when (/= (random-elt s2) (random-elt s2))
 | |
|                 (return t)))))
 | |
|   (t t))
 | |
| 
 | |
| (deftest removef.1
 | |
|     (let* ((x '(1 2 3))
 | |
|            (x* x)
 | |
|            (y #(1 2 3))
 | |
|            (y* y))
 | |
|       (removef x 1)
 | |
|       (removef y 3)
 | |
|       (list x x* y y*))
 | |
|   ((2 3)
 | |
|    (1 2 3)
 | |
|    #(1 2)
 | |
|    #(1 2 3)))
 | |
| 
 | |
| (deftest deletef.1
 | |
|     (let* ((x (list 1 2 3))
 | |
|            (x* x)
 | |
|            (y (vector 1 2 3)))
 | |
|       (deletef x 2)
 | |
|       (deletef y 1)
 | |
|       (list x x* y))
 | |
|   ((1 3)
 | |
|    (1 3)
 | |
|    #(2 3)))
 | |
| 
 | |
| (deftest map-permutations.1
 | |
|     (let ((seq (list 1 2 3))
 | |
|           (seen nil)
 | |
|           (ok t))
 | |
|       (map-permutations (lambda (s)
 | |
|                           (unless (set-equal s seq)
 | |
|                             (setf ok nil))
 | |
|                           (when (member s seen :test 'equal)
 | |
|                             (setf ok nil))
 | |
|                           (push s seen))
 | |
|                         seq
 | |
|                         :copy t)
 | |
|       (values ok (length seen)))
 | |
|   t
 | |
|   6)
 | |
| 
 | |
| (deftest proper-sequence.type.1
 | |
|     (mapcar (lambda (x)
 | |
|               (typep x 'proper-sequence))
 | |
|             (list (list 1 2 3)
 | |
|                   (vector 1 2 3)
 | |
|                   #2a((1 2) (3 4))
 | |
|                   (circular-list 1 2 3 4)))
 | |
|   (t t nil nil))
 | |
| 
 | |
| (deftest emptyp.1
 | |
|     (mapcar #'emptyp
 | |
|             (list (list 1)
 | |
|                   (circular-list 1)
 | |
|                   nil
 | |
|                   (vector)
 | |
|                   (vector 1)))
 | |
|   (nil nil t t nil))
 | |
| 
 | |
| (deftest sequence-of-length-p.1
 | |
|     (mapcar #'sequence-of-length-p
 | |
|             (list nil
 | |
|                   #()
 | |
|                   (list 1)
 | |
|                   (vector 1)
 | |
|                   (list 1 2)
 | |
|                   (vector 1 2)
 | |
|                   (list 1 2)
 | |
|                   (vector 1 2)
 | |
|                   (list 1 2)
 | |
|                   (vector 1 2))
 | |
|             (list 0
 | |
|                   0
 | |
|                   1
 | |
|                   1
 | |
|                   2
 | |
|                   2
 | |
|                   1
 | |
|                   1
 | |
|                   4
 | |
|                   4))
 | |
|   (t t t t t t nil nil nil nil))
 | |
| 
 | |
| (deftest length=.1
 | |
|     (mapcar #'length=
 | |
|             (list nil
 | |
|                   #()
 | |
|                   (list 1)
 | |
|                   (vector 1)
 | |
|                   (list 1 2)
 | |
|                   (vector 1 2)
 | |
|                   (list 1 2)
 | |
|                   (vector 1 2)
 | |
|                   (list 1 2)
 | |
|                   (vector 1 2))
 | |
|             (list 0
 | |
|                   0
 | |
|                   1
 | |
|                   1
 | |
|                   2
 | |
|                   2
 | |
|                   1
 | |
|                   1
 | |
|                   4
 | |
|                   4))
 | |
|   (t t t t t t nil nil nil nil))
 | |
| 
 | |
| (deftest length=.2
 | |
|     ;; test the compiler macro
 | |
|     (macrolet ((x (&rest args)
 | |
|                  (funcall
 | |
|                   (compile nil
 | |
|                            `(lambda ()
 | |
|                               (length= ,@args))))))
 | |
|       (list (x 2 '(1 2))
 | |
|             (x '(1 2) '(3 4))
 | |
|             (x '(1 2) 2)
 | |
|             (x '(1 2) 2 '(3 4))
 | |
|             (x 1 2 3)))
 | |
|   (t t t t nil))
 | |
| 
 | |
| (deftest copy-sequence.1
 | |
|     (let ((l (list 1 2 3))
 | |
|           (v (vector #\a #\b #\c)))
 | |
|       (declare (notinline copy-sequence))
 | |
|       (let ((l.list (copy-sequence 'list l))
 | |
|             (l.vector (copy-sequence 'vector l))
 | |
|             (l.spec-v (copy-sequence '(vector fixnum) l))
 | |
|             (v.vector (copy-sequence 'vector v))
 | |
|             (v.list (copy-sequence 'list v))
 | |
|             (v.string (copy-sequence 'string v)))
 | |
|         (list (member l (list l.list l.vector l.spec-v))
 | |
|               (member v (list v.vector v.list v.string))
 | |
|               (equal l.list l)
 | |
|               (equalp l.vector #(1 2 3))
 | |
|               (type= (upgraded-array-element-type 'fixnum)
 | |
|                      (array-element-type l.spec-v))
 | |
|               (equalp v.vector v)
 | |
|               (equal v.list '(#\a #\b #\c))
 | |
|               (equal "abc" v.string))))
 | |
|   (nil nil t t t t t t))
 | |
| 
 | |
| (deftest first-elt.1
 | |
|     (mapcar #'first-elt
 | |
|             (list (list 1 2 3)
 | |
|                   "abc"
 | |
|                   (vector :a :b :c)))
 | |
|   (1 #\a :a))
 | |
| 
 | |
| (deftest first-elt.error.1
 | |
|     (mapcar (lambda (x)
 | |
|               (handler-case
 | |
|                   (first-elt x)
 | |
|                 (type-error ()
 | |
|                   :type-error)))
 | |
|             (list nil
 | |
|                   #()
 | |
|                   12
 | |
|                   :zot))
 | |
|   (:type-error
 | |
|    :type-error
 | |
|    :type-error
 | |
|    :type-error))
 | |
| 
 | |
| (deftest setf-first-elt.1
 | |
|     (let ((l (list 1 2 3))
 | |
|           (s (copy-seq "foobar"))
 | |
|           (v (vector :a :b :c)))
 | |
|       (setf (first-elt l) -1
 | |
|             (first-elt s) #\x
 | |
|             (first-elt v) 'zot)
 | |
|       (values l s v))
 | |
|   (-1 2 3)
 | |
|   "xoobar"
 | |
|   #(zot :b :c))
 | |
| 
 | |
| (deftest setf-first-elt.error.1
 | |
|     (let ((l 'foo))
 | |
|       (multiple-value-bind (res err)
 | |
|           (ignore-errors (setf (first-elt l) 4))
 | |
|         (typep err 'type-error)))
 | |
|   t)
 | |
| 
 | |
| (deftest last-elt.1
 | |
|     (mapcar #'last-elt
 | |
|             (list (list 1 2 3)
 | |
|                   (vector :a :b :c)
 | |
|                   "FOOBAR"
 | |
|                   #*001
 | |
|                   #*010))
 | |
|   (3 :c #\R 1 0))
 | |
| 
 | |
| (deftest last-elt.error.1
 | |
|     (mapcar (lambda (x)
 | |
|               (handler-case
 | |
|                   (last-elt x)
 | |
|                 (type-error ()
 | |
|                   :type-error)))
 | |
|             (list nil
 | |
|                   #()
 | |
|                   12
 | |
|                   :zot
 | |
|                   (circular-list 1 2 3)
 | |
|                   (list* 1 2 3 (circular-list 4 5))))
 | |
|   (:type-error
 | |
|    :type-error
 | |
|    :type-error
 | |
|    :type-error
 | |
|    :type-error
 | |
|    :type-error))
 | |
| 
 | |
| (deftest setf-last-elt.1
 | |
|     (let ((l (list 1 2 3))
 | |
|           (s (copy-seq "foobar"))
 | |
|           (b (copy-seq #*010101001)))
 | |
|       (setf (last-elt l) '???
 | |
|             (last-elt s) #\?
 | |
|             (last-elt b) 0)
 | |
|       (values l s b))
 | |
|   (1 2 ???)
 | |
|   "fooba?"
 | |
|   #*010101000)
 | |
| 
 | |
| (deftest setf-last-elt.error.1
 | |
|     (handler-case
 | |
|         (setf (last-elt 'foo) 13)
 | |
|       (type-error ()
 | |
|         :type-error))
 | |
|   :type-error)
 | |
| 
 | |
| (deftest starts-with.1
 | |
|     (list (starts-with 1 '(1 2 3))
 | |
|           (starts-with 1 #(1 2 3))
 | |
|           (starts-with #\x "xyz")
 | |
|           (starts-with 2 '(1 2 3))
 | |
|           (starts-with 3 #(1 2 3))
 | |
|           (starts-with 1 1)
 | |
|           (starts-with nil nil))
 | |
|   (t t t nil nil nil nil))
 | |
| 
 | |
| (deftest starts-with.2
 | |
|     (values (starts-with 1 '(-1 2 3) :key '-)
 | |
|             (starts-with "foo" '("foo" "bar") :test 'equal)
 | |
|             (starts-with "f" '(#\f) :key 'string :test 'equal)
 | |
|             (starts-with -1 '(0 1 2) :key #'1+)
 | |
|             (starts-with "zot" '("ZOT") :test 'equal))
 | |
|   t
 | |
|   t
 | |
|   t
 | |
|   nil
 | |
|   nil)
 | |
| 
 | |
| (deftest ends-with.1
 | |
|     (list (ends-with 3 '(1 2 3))
 | |
|           (ends-with 3 #(1 2 3))
 | |
|           (ends-with #\z "xyz")
 | |
|           (ends-with 2 '(1 2 3))
 | |
|           (ends-with 1 #(1 2 3))
 | |
|           (ends-with 1 1)
 | |
|           (ends-with nil nil))
 | |
|   (t t t nil nil nil nil))
 | |
| 
 | |
| (deftest ends-with.2
 | |
|     (values (ends-with 2 '(0 13 1) :key '1+)
 | |
|             (ends-with "foo" (vector "bar" "foo") :test 'equal)
 | |
|             (ends-with "X" (vector 1 2 #\X) :key 'string :test 'equal)
 | |
|             (ends-with "foo" "foo" :test 'equal))
 | |
|   t
 | |
|   t
 | |
|   t
 | |
|   nil)
 | |
| 
 | |
| (deftest ends-with.error.1
 | |
|     (handler-case
 | |
|         (ends-with 3 (circular-list 3 3 3 1 3 3))
 | |
|       (type-error ()
 | |
|         :type-error))
 | |
|   :type-error)
 | |
| 
 | |
| (deftest sequences.passing-improper-lists
 | |
|     (macrolet ((signals-error-p (form)
 | |
|                  `(handler-case
 | |
|                       (progn ,form nil)
 | |
|                     (type-error (e)
 | |
|                       t)))
 | |
|                (cut (fn &rest args)
 | |
|                  (with-gensyms (arg)
 | |
|                    (print`(lambda (,arg)
 | |
|                        (apply ,fn (list ,@(substitute arg '_ args))))))))
 | |
|       (let ((circular-list (make-circular-list 5 :initial-element :foo))
 | |
|             (dotted-list (list* 'a 'b 'c 'd)))
 | |
|         (loop for nth from 0
 | |
|               for fn in (list
 | |
|                          (cut #'lastcar _)
 | |
|                          (cut #'rotate _ 3)
 | |
|                          (cut #'rotate _ -3)
 | |
|                          (cut #'shuffle _)
 | |
|                          (cut #'random-elt _)
 | |
|                          (cut #'last-elt _)
 | |
|                          (cut #'ends-with :foo _))
 | |
|               nconcing
 | |
|                  (let ((on-circular-p (signals-error-p (funcall fn circular-list)))
 | |
|                        (on-dotted-p (signals-error-p (funcall fn dotted-list))))
 | |
|                    (when (or (not on-circular-p) (not on-dotted-p))
 | |
|                      (append
 | |
|                       (unless on-circular-p
 | |
|                         (let ((*print-circle* t))
 | |
|                           (list
 | |
|                            (format nil
 | |
|                                    "No appropriate error signalled when passing ~S to ~Ath entry."
 | |
|                                    circular-list nth))))
 | |
|                       (unless on-dotted-p
 | |
|                         (list
 | |
|                          (format nil
 | |
|                                  "No appropriate error signalled when passing ~S to ~Ath entry."
 | |
|                                  dotted-list nth)))))))))
 | |
|   nil)
 | |
| 
 | |
| ;;;; IO
 | |
| 
 | |
| (deftest read-stream-content-into-string.1
 | |
|     (values (with-input-from-string (stream "foo bar")
 | |
|               (read-stream-content-into-string stream))
 | |
|             (with-input-from-string (stream "foo bar")
 | |
|               (read-stream-content-into-string stream :buffer-size 1))
 | |
|             (with-input-from-string (stream "foo bar")
 | |
|               (read-stream-content-into-string stream :buffer-size 6))
 | |
|             (with-input-from-string (stream "foo bar")
 | |
|               (read-stream-content-into-string stream :buffer-size 7)))
 | |
|   "foo bar"
 | |
|   "foo bar"
 | |
|   "foo bar"
 | |
|   "foo bar")
 | |
| 
 | |
| (deftest read-stream-content-into-string.2
 | |
|     (handler-case
 | |
|         (let ((stream (make-broadcast-stream)))
 | |
|           (read-stream-content-into-string stream :buffer-size 0))
 | |
|       (type-error ()
 | |
|         :type-error))
 | |
|   :type-error)
 | |
| 
 | |
| #+(or)
 | |
| (defvar *octets*
 | |
|   (map '(simple-array (unsigned-byte 8) (7)) #'char-code "foo bar"))
 | |
| 
 | |
| #+(or)
 | |
| (deftest read-stream-content-into-byte-vector.1
 | |
|     (values (with-input-from-byte-vector (stream *octets*)
 | |
|               (read-stream-content-into-byte-vector stream))
 | |
|             (with-input-from-byte-vector (stream *octets*)
 | |
|               (read-stream-content-into-byte-vector stream :initial-size 1))
 | |
|             (with-input-from-byte-vector (stream *octets*)
 | |
|               (read-stream-content-into-byte-vector stream 'alexandria::%length 6))
 | |
|             (with-input-from-byte-vector (stream *octets*)
 | |
|               (read-stream-content-into-byte-vector stream 'alexandria::%length 3)))
 | |
|   *octets*
 | |
|   *octets*
 | |
|   *octets*
 | |
|   (subseq *octets* 0 3))
 | |
| 
 | |
| (deftest read-stream-content-into-byte-vector.2
 | |
|     (handler-case
 | |
|         (let ((stream (make-broadcast-stream)))
 | |
|           (read-stream-content-into-byte-vector stream :initial-size 0))
 | |
|       (type-error ()
 | |
|         :type-error))
 | |
|   :type-error)
 | |
| 
 | |
| ;;;; Macros
 | |
| 
 | |
| (deftest with-unique-names.1
 | |
|     (let ((*gensym-counter* 0))
 | |
|       (let ((syms (with-unique-names (foo bar quux)
 | |
|                     (list foo bar quux))))
 | |
|         (list (find-if #'symbol-package syms)
 | |
|               (equal '("FOO0" "BAR1" "QUUX2")
 | |
|                      (mapcar #'symbol-name syms)))))
 | |
|   (nil t))
 | |
| 
 | |
| (deftest with-unique-names.2
 | |
|     (let ((*gensym-counter* 0))
 | |
|       (let ((syms (with-unique-names ((foo "_foo_") (bar -bar-) (quux #\q))
 | |
|                     (list foo bar quux))))
 | |
|         (list (find-if #'symbol-package syms)
 | |
|               (equal '("_foo_0" "-BAR-1" "q2")
 | |
|                      (mapcar #'symbol-name syms)))))
 | |
|   (nil t))
 | |
| 
 | |
| (deftest with-unique-names.3
 | |
|     (let ((*gensym-counter* 0))
 | |
|       (multiple-value-bind (res err)
 | |
|           (ignore-errors
 | |
|             (eval
 | |
|              '(let ((syms
 | |
|                      (with-unique-names ((foo "_foo_") (bar -bar-) (quux 42))
 | |
|                        (list foo bar quux))))
 | |
|                (list (find-if #'symbol-package syms)
 | |
|                 (equal '("_foo_0" "-BAR-1" "q2")
 | |
|                  (mapcar #'symbol-name syms))))))
 | |
|         (errorp err)))
 | |
|   t)
 | |
| 
 | |
| (deftest once-only.1
 | |
|     (macrolet ((cons1.good (x)
 | |
|                  (once-only (x)
 | |
|                    `(cons ,x ,x)))
 | |
|                (cons1.bad (x)
 | |
|                  `(cons ,x ,x)))
 | |
|       (let ((y 0))
 | |
|         (list (cons1.good (incf y))
 | |
|               y
 | |
|               (cons1.bad (incf y))
 | |
|               y)))
 | |
|   ((1 . 1) 1 (2 . 3) 3))
 | |
| 
 | |
| (deftest once-only.2
 | |
|     (macrolet ((cons1 (x)
 | |
|                  (once-only ((y x))
 | |
|                    `(cons ,y ,y))))
 | |
|       (let ((z 0))
 | |
|         (list (cons1 (incf z))
 | |
|               z
 | |
|               (cons1 (incf z)))))
 | |
|   ((1 . 1) 1 (2 . 2)))
 | |
| 
 | |
| (deftest parse-body.1
 | |
|     (parse-body '("doc" "body") :documentation t)
 | |
|   ("body")
 | |
|   nil
 | |
|   "doc")
 | |
| 
 | |
| (deftest parse-body.2
 | |
|     (parse-body '("body") :documentation t)
 | |
|   ("body")
 | |
|   nil
 | |
|   nil)
 | |
| 
 | |
| (deftest parse-body.3
 | |
|     (parse-body '("doc" "body"))
 | |
|   ("doc" "body")
 | |
|   nil
 | |
|   nil)
 | |
| 
 | |
| (deftest parse-body.4
 | |
|     (parse-body '((declare (foo)) "doc" (declare (bar)) body) :documentation t)
 | |
|   (body)
 | |
|   ((declare (foo)) (declare (bar)))
 | |
|   "doc")
 | |
| 
 | |
| (deftest parse-body.5
 | |
|     (parse-body '((declare (foo)) "doc" (declare (bar)) body))
 | |
|   ("doc" (declare (bar)) body)
 | |
|   ((declare (foo)))
 | |
|   nil)
 | |
| 
 | |
| (deftest parse-body.6
 | |
|     (multiple-value-bind (res err)
 | |
|         (ignore-errors
 | |
|           (parse-body '("foo" "bar" "quux")
 | |
|                       :documentation t))
 | |
|       (errorp err))
 | |
|   t)
 | |
| 
 | |
| ;;;; Symbols
 | |
| 
 | |
| (deftest ensure-symbol.1
 | |
|     (ensure-symbol :cons :cl)
 | |
|   cons
 | |
|   :external)
 | |
| 
 | |
| (deftest ensure-symbol.2
 | |
|     (ensure-symbol "CONS" :alexandria)
 | |
|   cons
 | |
|   :inherited)
 | |
| 
 | |
| (deftest ensure-symbol.3
 | |
|     (ensure-symbol 'foo :keyword)
 | |
|   :foo
 | |
|   :external)
 | |
| 
 | |
| (deftest ensure-symbol.4
 | |
|     (ensure-symbol #\* :alexandria)
 | |
|   *
 | |
|   :inherited)
 | |
| 
 | |
| (deftest format-symbol.1
 | |
|     (let ((s (format-symbol nil '#:x-~d 13)))
 | |
|       (list (symbol-package s)
 | |
|             (string= (string '#:x-13) (symbol-name s))))
 | |
|   (nil t))
 | |
| 
 | |
| (deftest format-symbol.2
 | |
|     (format-symbol :keyword '#:sym-~a (string :bolic))
 | |
|   :sym-bolic)
 | |
| 
 | |
| (deftest format-symbol.3
 | |
|     (let ((*package* (find-package :cl)))
 | |
|       (format-symbol t '#:find-~a (string 'package)))
 | |
|   find-package)
 | |
| 
 | |
| (deftest make-keyword.1
 | |
|     (list (make-keyword 'zot)
 | |
|           (make-keyword "FOO")
 | |
|           (make-keyword #\Q))
 | |
|   (:zot :foo :q))
 | |
| 
 | |
| (deftest make-gensym-list.1
 | |
|     (let ((*gensym-counter* 0))
 | |
|       (let ((syms (make-gensym-list 3 "FOO")))
 | |
|         (list (find-if 'symbol-package syms)
 | |
|               (equal '("FOO0" "FOO1" "FOO2")
 | |
|                      (mapcar 'symbol-name syms)))))
 | |
|   (nil t))
 | |
| 
 | |
| (deftest make-gensym-list.2
 | |
|     (let ((*gensym-counter* 0))
 | |
|       (let ((syms (make-gensym-list 3)))
 | |
|         (list (find-if 'symbol-package syms)
 | |
|               (equal '("G0" "G1" "G2")
 | |
|                      (mapcar 'symbol-name syms)))))
 | |
|   (nil t))
 | |
| 
 | |
| ;;;; Type-system
 | |
| 
 | |
| (deftest of-type.1
 | |
|     (locally
 | |
|         (declare (notinline of-type))
 | |
|     (let ((f (of-type 'string)))
 | |
|       (list (funcall f "foo")
 | |
|             (funcall f 'bar))))
 | |
|   (t nil))
 | |
| 
 | |
| (deftest type=.1
 | |
|     (type= 'string 'string)
 | |
|   t
 | |
|   t)
 | |
| 
 | |
| (deftest type=.2
 | |
|     (type= 'list '(or null cons))
 | |
|   t
 | |
|   t)
 | |
| 
 | |
| (deftest type=.3
 | |
|     (type= 'null '(and symbol list))
 | |
|   t
 | |
|   t)
 | |
| 
 | |
| (deftest type=.4
 | |
|     (type= 'string '(satisfies emptyp))
 | |
|   nil
 | |
|   nil)
 | |
| 
 | |
| (deftest type=.5
 | |
|     (type= 'string 'list)
 | |
|   nil
 | |
|   t)
 | |
| 
 | |
| (macrolet
 | |
|     ((test (type numbers)
 | |
|        `(deftest ,(format-symbol t '#:cdr5.~a (string type))
 | |
|             (let ((numbers ,numbers))
 | |
|               (values (mapcar (of-type ',(format-symbol t '#:negative-~a (string type))) numbers)
 | |
|                       (mapcar (of-type ',(format-symbol t '#:non-positive-~a (string type))) numbers)
 | |
|                       (mapcar (of-type ',(format-symbol t '#:non-negative-~a (string type))) numbers)
 | |
|                       (mapcar (of-type ',(format-symbol t '#:positive-~a (string type))) numbers)))
 | |
|           (t t t nil nil nil nil)
 | |
|           (t t t t nil nil nil)
 | |
|           (nil nil nil t t t t)
 | |
|           (nil nil nil nil t t t))))
 | |
|   (test fixnum       (list most-negative-fixnum       -42      -1     0     1     42      most-positive-fixnum))
 | |
|   (test integer      (list (1- most-negative-fixnum)  -42      -1     0     1     42      (1+ most-positive-fixnum)))
 | |
|   (test rational     (list (1- most-negative-fixnum)  -42/13   -1     0     1     42/13   (1+ most-positive-fixnum)))
 | |
|   (test real         (list most-negative-long-float   -42/13   -1     0     1     42/13   most-positive-long-float))
 | |
|   (test float        (list most-negative-short-float  -42.02   -1.0   0.0   1.0   42.02   most-positive-short-float))
 | |
|   (test short-float  (list most-negative-short-float  -42.02s0 -1.0s0 0.0s0 1.0s0 42.02s0 most-positive-short-float))
 | |
|   (test single-float (list most-negative-single-float -42.02f0 -1.0f0 0.0f0 1.0f0 42.02f0 most-positive-single-float))
 | |
|   (test double-float (list most-negative-double-float -42.02d0 -1.0d0 0.0d0 1.0d0 42.02d0 most-positive-double-float))
 | |
|   (test long-float   (list most-negative-long-float   -42.02l0 -1.0l0 0.0l0 1.0l0 42.02l0 most-positive-long-float)))
 | |
| 
 | |
| ;;;; Bindings
 | |
| 
 | |
| (declaim (notinline opaque))
 | |
| (defun opaque (x)
 | |
|   x)
 | |
| 
 | |
| (deftest if-let.1
 | |
|     (if-let (x (opaque :ok))
 | |
|             x
 | |
|             :bad)
 | |
|   :ok)
 | |
| 
 | |
| (deftest if-let.2
 | |
|     (if-let (x (opaque nil))
 | |
|             :bad
 | |
|             (and (not x) :ok))
 | |
|   :ok)
 | |
| 
 | |
| (deftest if-let.3
 | |
|     (let ((x 1))
 | |
|       (if-let ((x 2)
 | |
|                (y x))
 | |
|               (+ x y)
 | |
|               :oops))
 | |
|   3)
 | |
| 
 | |
| (deftest if-let.4
 | |
|     (if-let ((x 1)
 | |
|              (y nil))
 | |
|             :oops
 | |
|             (and (not y) x))
 | |
|   1)
 | |
| 
 | |
| (deftest if-let.5
 | |
|     (if-let (x)
 | |
|             :oops
 | |
|             (not x))
 | |
|   t)
 | |
| 
 | |
| (deftest if-let.error.1
 | |
|     (handler-case
 | |
|         (eval '(if-let x
 | |
|                 :oops
 | |
|                 :oops))
 | |
|       (type-error ()
 | |
|         :type-error))
 | |
|   :type-error)
 | |
| 
 | |
| (deftest when-let.1
 | |
|     (when-let (x (opaque :ok))
 | |
|       (setf x (cons x x))
 | |
|       x)
 | |
|   (:ok . :ok))
 | |
| 
 | |
| (deftest when-let.2
 | |
|     (when-let ((x 1)
 | |
|                (y nil)
 | |
|                (z 3))
 | |
|       :oops)
 | |
|   nil)
 | |
| 
 | |
| (deftest when-let.3
 | |
|     (let ((x 1))
 | |
|       (when-let ((x 2)
 | |
|                  (y x))
 | |
|         (+ x y)))
 | |
|   3)
 | |
| 
 | |
| (deftest when-let.error.1
 | |
|     (handler-case
 | |
|         (eval '(when-let x :oops))
 | |
|       (type-error ()
 | |
|         :type-error))
 | |
|   :type-error)
 | |
| 
 | |
| (deftest when-let*.1
 | |
|     (let ((x 1))
 | |
|       (when-let* ((x 2)
 | |
|                   (y x))
 | |
|         (+ x y)))
 | |
|   4)
 | |
| 
 | |
| (deftest when-let*.2
 | |
|     (let ((y 1))
 | |
|       (when-let* (x y)
 | |
|         (1+ x)))
 | |
|   2)
 | |
| 
 | |
| (deftest when-let*.3
 | |
|     (when-let* ((x t)
 | |
|                 (y (consp x))
 | |
|                 (z (error "OOPS")))
 | |
|       t)
 | |
|   nil)
 | |
| 
 | |
| (deftest when-let*.error.1
 | |
|     (handler-case
 | |
|         (eval '(when-let* x :oops))
 | |
|       (type-error ()
 | |
|         :type-error))
 | |
|   :type-error)
 | |
| 
 | |
| (deftest doplist.1
 | |
|     (let (keys values)
 | |
|       (doplist (k v '(a 1 b 2 c 3) (values t (reverse keys) (reverse values) k v))
 | |
|         (push k keys)
 | |
|         (push v values)))
 | |
|   t
 | |
|   (a b c)
 | |
|   (1 2 3)
 | |
|   nil
 | |
|   nil)
 | |
| 
 | |
| (deftest count-permutations.1
 | |
|     (values (count-permutations 31 7)
 | |
|             (count-permutations 1 1)
 | |
|             (count-permutations 2 1)
 | |
|             (count-permutations 2 2)
 | |
|             (count-permutations 3 2)
 | |
|             (count-permutations 3 1))
 | |
|   13253058000
 | |
|   1
 | |
|   2
 | |
|   2
 | |
|   6
 | |
|   3)
 | |
| 
 | |
| (deftest binomial-coefficient.1
 | |
|     (alexandria:binomial-coefficient 1239 139)
 | |
|   28794902202288970200771694600561826718847179309929858835480006683522184441358211423695124921058123706380656375919763349913245306834194782172712255592710204598527867804110129489943080460154)
 | |
| 
 | |
| ;; Exercise bignum case (at least on x86).
 | |
| (deftest binomial-coefficient.2
 | |
|     (alexandria:binomial-coefficient 2000000000000 20)
 | |
|   430998041177272843950422879590338454856322722740402365741730748431530623813012487773080486408378680853987520854296499536311275320016878730999689934464711239072435565454954447356845336730100919970769793030177499999999900000000000)
 | |
| 
 | |
| (deftest copy-stream.1
 | |
|     (let ((data "sdkfjhsakfh weior763495ewofhsdfk sdfadlkfjhsadf woif sdlkjfhslkdfh sdklfjh"))
 | |
|       (values (equal data
 | |
|                      (with-input-from-string (in data)
 | |
|                        (with-output-to-string (out)
 | |
|                          (alexandria:copy-stream in out))))
 | |
|               (equal (subseq data 10 20)
 | |
|                      (with-input-from-string (in data)
 | |
|                        (with-output-to-string (out)
 | |
|                          (alexandria:copy-stream in out :start 10 :end 20))))
 | |
|               (equal (subseq data 10)
 | |
|                      (with-input-from-string (in data)
 | |
|                        (with-output-to-string (out)
 | |
|                          (alexandria:copy-stream in out :start 10))))
 | |
|               (equal (subseq data 0 20)
 | |
|                      (with-input-from-string (in data)
 | |
|                        (with-output-to-string (out)
 | |
|                          (alexandria:copy-stream in out :end 20))))))
 | |
|   t
 | |
|   t
 | |
|   t
 | |
|   t)
 | |
| 
 | |
| (deftest extremum.1
 | |
|     (let ((n 0))
 | |
|       (dotimes (i 10)
 | |
|        (let ((data (shuffle (coerce (iota 10000 :start i) 'vector)))
 | |
|              (ok t))
 | |
|          (unless (eql i (extremum data #'<))
 | |
|            (setf ok nil))
 | |
|          (unless (eql i (extremum (coerce data 'list) #'<))
 | |
|            (setf ok nil))
 | |
|          (unless (eql (+ 9999 i) (extremum data #'>))
 | |
|            (setf ok nil))
 | |
|          (unless (eql (+ 9999 i) (extremum (coerce  data 'list) #'>))
 | |
|            (setf ok nil))
 | |
|          (when ok
 | |
|            (incf n))))
 | |
|       (when (eql 10 (extremum #(100 1 10 1000) #'> :start 1 :end 3))
 | |
|         (incf n))
 | |
|       (when (eql -1000 (extremum #(100 1 10 -1000) #'> :key 'abs))
 | |
|         (incf n))
 | |
|       (when (eq nil (extremum "" (lambda (a b) (error "wtf? ~S, ~S" a b))))
 | |
|         (incf n))
 | |
|       n)
 | |
|   13)
 | |
| 
 | |
| (deftest starts-with-subseq.string
 | |
|     (starts-with-subseq "f" "foo" :return-suffix t)
 | |
|   t
 | |
|   "oo")
 | |
| 
 | |
| (deftest starts-with-subseq.vector
 | |
|     (starts-with-subseq #(1) #(1 2 3) :return-suffix t)
 | |
|   t
 | |
|   #(2 3))
 | |
| 
 | |
| (deftest starts-with-subseq.list
 | |
|     (starts-with-subseq '(1) '(1 2 3) :return-suffix t)
 | |
|   t
 | |
|   (2 3))
 | |
| 
 | |
| (deftest starts-with-subseq.start1
 | |
|     (starts-with-subseq "foo" "oop" :start1 1)
 | |
|   t
 | |
|   nil)
 | |
| 
 | |
| (deftest starts-with-subseq.start2
 | |
|     (starts-with-subseq "foo" "xfoop" :start2 1)
 | |
|   t
 | |
|   nil)
 | |
| 
 | |
| (deftest format-symbol.print-case-bound
 | |
|     (let ((upper (intern "FOO-BAR"))
 | |
|           (lower (intern "foo-bar"))
 | |
|           (*print-escape* nil))
 | |
|       (values
 | |
|        (let ((*print-case* :downcase))
 | |
|          (and (eq upper (format-symbol t "~A" upper))
 | |
|                (eq lower (format-symbol t "~A" lower))))
 | |
|        (let ((*print-case* :upcase))
 | |
|          (and (eq upper (format-symbol t "~A" upper))
 | |
|                (eq lower (format-symbol t "~A" lower))))
 | |
|        (let ((*print-case* :capitalize))
 | |
|          (and (eq upper (format-symbol t "~A" upper))
 | |
|               (eq lower (format-symbol t "~A" lower))))))
 | |
|   t
 | |
|   t
 | |
|   t)
 | |
| 
 | |
| (deftest iota.fp-start-and-complex-integer-step
 | |
|     (equal '(#C(0.0 0.0) #C(0.0 2.0) #C(0.0 4.0))
 | |
|            (iota 3 :start 0.0 :step #C(0 2)))
 | |
|   t)
 | |
| 
 | |
| (deftest parse-ordinary-lambda-list.1
 | |
|     (multiple-value-bind (req opt rest keys allowp aux keyp)
 | |
|         (parse-ordinary-lambda-list '(a b c
 | |
|                                       &optional o1 (o2 42) (o3 42 o3-supplied?)
 | |
|                                       &key (k1) ((:key k2)) (k3 42 k3-supplied?))
 | |
|                                     :normalize t)
 | |
|       (and (equal '(a b c) req)
 | |
|            (equal '((o1 nil nil)
 | |
|                     (o2 42 nil)
 | |
|                     (o3 42 o3-supplied?))
 | |
|                   opt)
 | |
|            (equal '(((:k1 k1) nil nil)
 | |
|                     ((:key k2) nil nil)
 | |
|                     ((:k3 k3) 42 k3-supplied?))
 | |
|                   keys)
 | |
|            (not allowp)
 | |
|            (not aux)
 | |
|            (eq t keyp)))
 | |
|   t)
 |