1 ;;;; side-effect-free tests of the condition system
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; While most of SBCL is derived from the CMU CL system, the test
7 ;;;; files (like this one) were written from scratch after the fork
10 ;;;; This software is in the public domain and is provided with
11 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
12 ;;;; more information.
14 (cl:in-package :cl-user)
16 (load "test-util.lisp")
18 ;;; Until 0.7.7.21, (MAKE-CONDITION 'FILE-ERROR :PATHNAME "FOO")
19 ;;; wasn't printable, because the REPORT function for FILE-ERROR
20 ;;; referred to unbound slots. This was reported and fixed by Antonio
21 ;;; Martinez (sbcl-devel 2002-09-10).
23 "~&printable now: ~A~%"
24 (make-condition 'file-error :pathname "foo"))
28 (macrolet ((opaque-error (arg) `(error ,arg)))
31 (let ((restarts (remove 'res (compute-restarts c)
34 (assert (= (length restarts) 2))
35 (invoke-restart (second restarts))))))
36 (let ((foo1 (make-condition 'error))
37 (foo2 (make-condition 'error)))
39 (with-condition-restarts foo1 (list (find-restart 'res))
49 (macrolet ((opaque-error (arg) `(error ,arg)))
50 (let ((foo1 (make-condition 'error))
51 (foo2 (make-condition 'error)))
55 (let ((restarts (remove 'res (compute-restarts foo1)
58 (assert (= (length restarts) 1))
59 (invoke-restart (first restarts))))))
61 (with-condition-restarts foo1 (list (find-restart 'res))
73 (c1 (make-condition 'error))
74 (c2 (make-condition 'error)))
79 (flet ((check-restarts (length)
81 (length (remove 'foo (compute-restarts c1)
87 (invoke-restart (find-restart 'foo c1))))))
92 (foo () :test (lambda (c) (declare (ignore c)) visible)
96 ;;; First argument of CERROR is a format control
100 ((type-error (lambda (c)
103 (simple-error (lambda (c)
105 (return (if (find-restart 'continue)
108 (cerror (formatter "Continue from ~A") "bug ~A" :bug)))
111 ;;; clauses in HANDLER-CASE are allowed to have declarations (and
112 ;;; indeed, only declarations)
114 (null (handler-case (error "foo") (error () (declare (optimize speed))))))
117 (handler-bind ((warning #'muffle-warning))
119 ;; if it's a control error, it had better be printable
120 (control-error (c) (format nil "~A" c))
121 ;; there had better be an error
122 (:no-error (&rest args) (error "No error: ~S" args)))
125 (funcall (lambda (x) (check-type x fixnum) x) t)
127 (assert (and (subtypep (type-error-expected-type c) 'fixnum)
128 (subtypep 'fixnum (type-error-expected-type c))))
129 (assert (eq (type-error-datum c) t)))
130 (:no-error (&rest rest) (error "no error: ~S" rest)))
132 ;;; ANSI specifies TYPE-ERROR if datum and arguments of ERROR are not
133 ;;; designators for a condition. Reported by Bruno Haible on cmucl-imp
135 (flet ((test (&rest args)
136 (multiple-value-bind (res err)
137 (ignore-errors (apply #'error args))
139 (assert (typep err 'type-error))
140 (assert (not (nth-value 1 (ignore-errors
141 (type-error-datum err)))))
142 (assert (not (nth-value 1 (ignore-errors
143 (type-error-expected-type err))))))))
144 (test '#:no-such-condition)
148 (test (make-instance 'standard-object)))
150 ;;; If CERROR is given a condition, any remaining arguments are only
151 ;;; used for the continue format control.
152 (with-test (:name (cerror :condition-object-and-format-arguments))
155 ((simple-error (lambda (c) (incf x) (continue c))))
156 (cerror "Continue from ~A at ~A"
157 (make-condition 'simple-error :format-control "foo"
158 :format-arguments nil)
159 'cerror (get-universal-time))
162 ;; Test some of the variations permitted by the RESTART-CASE syntax.
163 (with-test (:name (restart-case :smoke))
165 ((test (clause &optional (expected ''(:ok)) (args '(:ok)))
166 `(assert (equal ,expected
171 (invoke-restart ',(first clause) ,@args))))
175 (test (foo (quux) quux))
176 (test (foo (&optional quux) quux))
177 ;; Multiple values should work.
178 (test (foo (a b) (values a b)) '(1 2) (1 2))
179 ;; Although somewhat unlikely, these should be legal and return
180 ;; the respective keyword when the restart is invoked.
181 (test (foo () :report) '(:report) ())
182 (test (foo () :interactive) '(:interactive) ())
183 (test (foo () :test) '(:test) ())
184 ;; Declarations should work normally as part of the restart body.
185 (test (foo (quux) :declare ()) '(nil))
186 (test (foo () :declare () :report "quux") '("quux") ())))
188 (with-test (:name (restart-case :malformed-clauses))
190 ((test (clause &optional (expected clause))
194 `(restart-case (error "foo") ,',clause))
196 (assert (equal '(restart-case ,expected)
197 (simple-condition-format-arguments e)))
200 (test :report) ; not even a list
202 (test (foo)) ; no lambda-list
203 (test (foo :report)) ; no lambda-list
204 (test (foo :report "quux")) ; no lambda-list
205 (test (foo :report "quux" (quux))) ; confused report and lambda list
208 (with-test (:name :simple-condition-without-args)
209 (let ((sc (make-condition 'simple-condition)))
210 (assert (not (simple-condition-format-control sc)))
211 (assert (not (simple-condition-format-arguments sc)))
212 (assert (stringp (prin1-to-string sc)))
218 (when (and (equal "No format-control for ~S"
219 (simple-condition-format-control c))
221 (simple-condition-format-arguments c))))
224 (with-test (:name :malformed-simple-condition-printing-type-error)
225 (assert (eq :type-error
228 (make-condition 'simple-error :format-control "" :format-arguments 8))
230 (when (and (eq 'list (type-error-expected-type e))
231 (eql 8 (type-error-datum e)))
234 (with-test (:name (:printing-unintitialized-condition :bug-1184586))
235 (prin1-to-string (make-condition 'simple-type-error)))
237 (with-test (:name (:print-undefined-function-condition))
238 (handler-case (funcall '#:foo)
239 (undefined-function (c) (princ c))))