1 ;;;; miscellaneous side-effectful tests of CLOS
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 ;;; clos.impure.lisp was getting too big and confusing
16 (load "assertoid.lisp")
18 (cl:defpackage
"CLOS-1"
19 (:use
"CL" "ASSERTOID" "TEST-UTIL"))
20 (cl:in-package
"CLOS-1")
22 ;;; tests that various optimization paths for slot-valuish things
23 ;;; respect class redefinitions.
27 (defvar *foo
* (make-instance 'foo
:a
1))
29 (defmethod a-of ((x foo
))
31 (defmethod b-of ((x foo
))
33 (defmethod c-of ((x foo
))
36 (let ((fun (checked-compile '(lambda (x) (slot-value x
'a
)))))
37 (dotimes (i 4) ; KLUDGE: get caches warm
38 (assert (= 1 (slot-value *foo
* 'a
)))
39 (assert (= 1 (a-of *foo
*)))
40 (assert (= 1 (funcall fun
*foo
*)))
41 (assert-error (b-of *foo
*))
42 (assert-error (c-of *foo
*))))
45 ((b :initarg
:b
:initform
3) (a :initarg
:a
)))
47 (let ((fun (checked-compile '(lambda (x) (slot-value x
'a
)))))
48 (dotimes (i 4) ; KLUDGE: get caches warm
49 (assert (= 1 (slot-value *foo
* 'a
)))
50 (assert (= 1 (a-of *foo
*)))
51 (assert (= 1 (funcall fun
*foo
*)))
52 (assert (= 3 (b-of *foo
*)))
53 (assert-error (c-of *foo
*))))
56 ((c :initarg
:c
:initform t
:allocation
:class
)
57 (b :initarg
:b
:initform
3)
60 (let ((fun (checked-compile '(lambda (x) (slot-value x
'a
)))))
61 (dotimes (i 4) ; KLUDGE: get caches warm
62 (assert (= 1 (slot-value *foo
* 'a
)))
63 (assert (= 1 (a-of *foo
*)))
64 (assert (= 1 (funcall fun
*foo
*)))
65 (assert (= 3 (b-of *foo
*)))
66 (assert (eq t
(c-of *foo
*)))))
70 (b :initarg
:b
:initform
3)
71 (c :initarg
:c
:initform t
)))
73 (let ((fun (checked-compile '(lambda (x) (slot-value x
'a
)))))
74 (dotimes (i 4) ; KLUDGE: get caches warm
75 (assert (= 1 (slot-value *foo
* 'a
)))
76 (assert (= 1 (a-of *foo
*)))
77 (assert (= 1 (funcall fun
*foo
*)))
78 (assert (= 3 (b-of *foo
*)))
79 (assert (eq t
(c-of *foo
*)))))
82 ((b :initarg
:b
:initform
3)))
84 (let ((fun (checked-compile '(lambda (x) (slot-value x
'a
)))))
85 (dotimes (i 4) ; KLUDGE: get caches warm
86 (assert-error (slot-value *foo
* 'a
))
87 (assert-error (a-of *foo
*))
88 (assert-error (funcall fun
*foo
*))
89 (assert (= 3 (b-of *foo
*)))
90 (assert-error (c-of *foo
*))))
92 ;;; test that :documentation argument to slot specifiers are used as
93 ;;; the docstrings of accessor methods.
95 ((a :reader a-of
:documentation
"docstring for A")
96 (b :writer set-b-of
:documentation
"docstring for B")
97 (c :accessor c
:documentation
"docstring for C")))
100 (documentation fun t
)))
101 (assert (string= (doc (find-method #'a-of nil
'(foo))) "docstring for A"))
102 (assert (string= (doc (find-method #'set-b-of nil
'(t foo
))) "docstring for B"))
103 (assert (string= (doc (find-method #'c nil
'(foo))) "docstring for C"))
104 (assert (string= (doc (find-method #'(setf c
) nil
'(t foo
))) "docstring for C")))
106 ;;; some nasty tests of NO-NEXT-METHOD.
107 (defvar *method-with-no-next-method
*)
108 (defvar *nnm-count
* 0)
109 (defun make-nnm-tester (x)
110 (setq *method-with-no-next-method
* (defmethod nnm-tester ((y (eql x
))) (call-next-method))))
112 (defmethod no-next-method ((gf (eql #'nnm-tester
)) method
&rest args
)
113 (declare (ignore args
))
114 (assert (eql method
*method-with-no-next-method
*))
116 (with-test (:name
(no-next-method :unknown-specializer
))
118 (assert (= *nnm-count
* 1)))
119 (let ((gf #'nnm-tester
))
120 (reinitialize-instance gf
:name
'new-nnm-tester
)
121 (setf (fdefinition 'new-nnm-tester
) gf
))
122 (with-test (:name
(no-next-method :gf-name-changed
))
124 (assert (= *nnm-count
* 2)))
126 ;;; Tests the compiler's incremental rejiggering of GF types.
128 (with-test (:name
:keywords-supplied-in-methods-ok-1
)
129 (defgeneric foo
(x &key
))
130 (defmethod foo ((x integer
) &key bar
) (list x bar
))
131 (checked-compile '(lambda () (foo (read) :bar
10))))
134 (with-test (:name
:keywords-supplied-in-methods-ok-2
)
135 (defgeneric foo
(x &key
))
136 (defmethod foo ((x integer
) &key bar
) (list x bar
))
137 ;; On second thought...
138 (remove-method #'foo
(find-method #'foo
() '(integer)))
139 (multiple-value-bind (fun failure-p warnings style-warnings
)
140 (checked-compile '(lambda () (foo (read) :bar
10))
141 :allow-style-warnings t
)
142 (declare (ignore fun failure-p warnings
))
143 (assert (= (length style-warnings
) 1))))
145 ;; If the GF has &REST with no &KEY, not all methods are required to
146 ;; parse the tail of the arglist as keywords, so we don't treat the
147 ;; function type as having &KEY in it.
149 (with-test (:name
:gf-rest-method-key
)
150 (defgeneric foo
(x &rest y
))
151 (defmethod foo ((i integer
) &key w
) (list i w
))
152 ;; 1.0.20.30 failed here.
153 (checked-compile '(lambda () (foo 5 :w
10 :foo
15)))
155 (not (sb-kernel::args-type-keyp
(sb-int:proclaimed-ftype
'foo
)))))
157 ;; If the GF has &KEY and &ALLOW-OTHER-KEYS, the methods' keys can be
158 ;; anything, and we don't warn about unrecognized keys.
160 (with-test (:name
:gf-allow-other-keys
)
161 (defgeneric foo
(x &key
&allow-other-keys
))
162 (defmethod foo ((i integer
) &key y z
) (list i y z
))
163 ;; Correctness of a GF's ftype was previously ensured by the compiler,
164 ;; and only if a lambda was compiled that referenced the GF, in a way
165 ;; that was just barely non-broken enough to make the compiler happy.
166 ;; Now the FTYPE is computed the instant anyone asks for it.
167 (assert (equal (mapcar 'sb-kernel
:key-info-name
168 (sb-kernel:fun-type-keywords
169 (sb-int:proclaimed-ftype
'foo
)))
171 (checked-compile '(lambda () (foo 5 :z
10 :y
15)))
172 (checked-compile '(lambda () (foo 5 :z
10 :foo
15)))
174 (sb-kernel::args-type-keyp
(sb-int:proclaimed-ftype
'foo
)))
176 (sb-kernel::args-type-allowp
(sb-int:proclaimed-ftype
'foo
))))
178 ;; If any method has &ALLOW-OTHER-KEYS, 7.6.4 point 5 seems to say the
179 ;; GF should be construed to have &ALLOW-OTHER-KEYS.
181 (with-test (:name
:method-allow-other-keys
)
182 (defgeneric foo
(x &key
))
183 (defmethod foo ((x integer
) &rest y
&key
&allow-other-keys
) (list x y
))
184 (checked-compile '(lambda () (foo 10 :foo
20)))
185 (assert (sb-kernel::args-type-keyp
(sb-int:proclaimed-ftype
'foo
)))
186 (assert (sb-kernel::args-type-allowp
(sb-int:proclaimed-ftype
'foo
))))
189 (with-test (:name
(defmethod symbol-macrolet))
190 (symbol-macrolet ((cnm (call-next-method)))
191 (defmethod foo ((x number
)) (1+ cnm
)))
192 (defmethod foo ((x t
)) 3)
193 (assert (= (foo t
) 3))
194 (assert (= (foo 3) 4)))
197 (define-symbol-macro magic-cnm
(call-next-method))
198 (with-test (:name
(defmethod define-symbol-macro))
199 (defmethod foo ((x number
)) (1- magic-cnm
))
200 (defmethod foo ((x t
)) 3)
201 (assert (= (foo t
) 3))
202 (assert (= (foo 3) 2)))