1 #|----------------------------------------------------------------------------|
2 | Copyright
1990 by the Massachusetts Institute of Technology
, Cambridge MA. |
4 | Permission to use
, copy
, modify
, and distribute this software and its |
5 | documentation for any purpose and without fee is hereby granted
, provided |
6 | that this copyright and permission notice appear in all copies and |
7 | supporting documentation
, and that the name of M.I.T. not be used in |
8 | advertising or publicity pertaining to distribution of the software |
9 | without specific
, written prior permission. M.I.T. makes no |
10 | representations about the suitability of this software for any purpose. |
11 | It is provided
"as is" without express or implied warranty. |
13 | M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
, INCLUDING |
14 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
, IN NO EVENT SHALL |
15 | M.I.T. BE LIABLE FOR ANY SPECIAL
, INDIRECT OR CONSEQUENTIAL DAMAGES OR |
16 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE
, DATA OR PROFITS
, |
17 | WHETHER IN AN ACTION OF CONTRACT
, NEGLIGENCE OR OTHER TORTIOUS ACTION
, |
18 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
20 |----------------------------------------------------------------------------|
#
24 (:export
#:*do-tests-when-defined
* #:*test
* #:continue-testing
25 #:deftest
#:do-test
#:do-tests
#:get-test
#:pending-tests
26 #:rem-all-tests
#:rem-test
)
27 (:documentation
"The MIT regression tester"))
31 (defvar *test
* nil
"Current test name")
32 (defvar *do-tests-when-defined
* nil
)
33 (defvar *entries
* '(nil) "Test database")
34 (defvar *in-test
* nil
"Used by TEST")
35 (defvar *debug
* nil
"For debugging")
36 (defvar *catch-errors
* t
37 "When true, causes errors in a test to be caught.")
38 (defvar *print-circle-on-failure
* nil
39 "Failure reports are printed with *PRINT-CIRCLE* bound to this value.")
40 (defvar *compile-tests
* nil
41 "When true, compile the tests before running them.")
42 (defvar *optimization-settings
* '((safety 3)))
43 (defvar *expected-failures
* nil
44 "A list of test names that are expected to fail.")
46 (defstruct (entry (:conc-name nil
)
50 (defmacro vals
(entry) `(cdddr ,entry
))
52 (defmacro defn
(entry) `(cdr ,entry
))
54 (defun pending-tests ()
55 (do ((l (cdr *entries
*) (cdr l
))
57 ((null l
) (nreverse r
))
59 (push (name (car l
)) r
))))
61 (defun rem-all-tests ()
62 (setq *entries
* (list nil
))
65 (defun rem-test (&optional
(name *test
*))
66 (do ((l *entries
* (cdr l
)))
68 (when (equal (name (cadr l
)) name
)
69 (setf (cdr l
) (cddr l
))
72 (defun get-test (&optional
(name *test
*))
73 (defn (get-entry name
)))
75 (defun get-entry (name)
76 (let ((entry (find name
(cdr *entries
*)
81 "~%No test with name ~:@(~S~)."
85 (defmacro deftest
(name form
&rest values
)
86 `(add-entry '(t ,name
,form .
,values
)))
88 (defun add-entry (entry)
89 (setq entry
(copy-list entry
))
90 (do ((l *entries
* (cdr l
))) (nil)
92 (setf (cdr l
) (list entry
))
94 (when (equal (name (cadr l
))
98 "Redefining test ~:@(~S~)"
101 (when *do-tests-when-defined
*
103 (setq *test
* (name entry
)))
105 (defun report-error (error?
&rest args
)
107 (apply #'format t args
)
108 (if error?
(throw '*debug
* nil
)))
109 (error?
(apply #'error args
))
110 (t (apply #'warn args
))))
112 (defun do-test (&optional
(name *test
*))
113 (do-entry (get-entry name
)))
115 (defun equalp-with-case (x y
)
116 "Like EQUALP, but doesn't do case conversion of characters.
117 Also does not descend into structures, which EQUALP does."
122 (equalp-with-case (car x
) (car y
))
123 (equalp-with-case (cdr x
) (cdr y
))))
124 ((and (typep x
'array
)
125 (= (array-rank x
) 0))
126 (equalp-with-case (aref x
) (aref y
)))
128 (and (typep y
'vector
)
129 (let ((x-len (length x
))
131 (and (eql x-len y-len
)
135 always
(equalp-with-case e1 e2
))))))
136 ((and (typep x
'array
)
138 (not (equal (array-dimensions x
)
139 (array-dimensions y
))))
142 (and (typep y
'array
)
143 (let ((size (array-total-size x
)))
144 (loop for i from
0 below size
145 always
(equalp-with-case (row-major-aref x i
)
146 (row-major-aref y i
))))))
149 (defun do-entry (entry &optional
150 (s *standard-output
*))
152 (setq *test
* (name entry
))
153 (setf (pend entry
) t
)
155 ;; (*break-on-warnings* t)
158 ;; (declare (special *break-on-warnings*))
170 (optimize ,@*optimization-settings
*))
173 (eval (form entry
))))))
176 ((style-warning #'muffle-warning
)
180 (return-from aborted nil
))))
186 (not (equalp-with-case r
(vals entry
)))))
189 (let ((*print-circle
* *print-circle-on-failure
*))
190 (format s
"~&Test ~:@(~S~) failed~
192 ~%Expected value~P: ~
195 (length (vals entry
))
197 (format s
"Actual value~P: ~
200 (when (not (pend entry
)) *test
*))
202 (defun continue-testing ()
204 (throw '*in-test
* nil
)
205 (do-entries *standard-output
*)))
207 (defun do-tests (&optional
208 (out *standard-output
*))
209 (dolist (entry (cdr *entries
*))
210 (setf (pend entry
) t
))
214 (stream out
:direction
:output
)
215 (do-entries stream
))))
217 (defun do-entries (s)
218 (format s
"~&Doing ~A pending test~:P ~
219 of ~A tests total.~%"
220 (count t
(cdr *entries
*)
222 (length (cdr *entries
*)))
223 (dolist (entry (cdr *entries
*))
225 (format s
"~@[~<~%~:; ~:@(~S~)~>~]"
226 (do-entry entry s
))))
227 (let ((pending (pending-tests))
228 (expected-table (make-hash-table :test
#'equal
)))
229 (dolist (ex *expected-failures
*)
230 (setf (gethash ex expected-table
) t
))
232 (loop for pend in pending
233 unless
(gethash pend expected-table
)
236 (format s
"~&No tests failed.")
238 (format s
"~&~A out of ~A ~
239 total tests failed: ~
243 (length (cdr *entries
*))
245 (if (null new-failures
)
246 (format s
"~&No unexpected failures.")
247 (when *expected-failures
*
248 (format s
"~&~A unexpected failures: ~
251 (length new-failures
)
254 (values (null new-failures
) (null pending
) pending
))))