source: trunk/abcl/test/lisp/abcl/mop-tests.lisp @ 13884

Last change on this file since 13884 was 13884, checked in by Mark Evenson, 11 years ago

See #199: factored test for failing case.

  • Property svn:eol-style set to native
File size: 17.7 KB
Line 
1;;; mop-tests.lisp
2;;;
3;;; Copyright (C) 2010 Matthias Hölzl
4;;; Copyright (C) 2010 Erik Huelsmann
5;;;
6;;; This program is free software; you can redistribute it and/or
7;;; modify it under the terms of the GNU General Public License
8;;; as published by the Free Software Foundation; either version 2
9;;; of the License, or (at your option) any later version.
10;;;
11;;; This program is distributed in the hope that it will be useful,
12;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with this program; if not, write to the Free Software
18;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20(in-package #:abcl.test.lisp)
21
22(deftest compute-applicable-methods.foo.1
23    (equalp
24     (mop:compute-applicable-methods #'mop-test.foo '(111 222))
25     (mop:compute-applicable-methods-using-classes
26      #'mop-test.foo (find-classes 'fixnum 'fixnum)))
27  t)
28
29(deftest compute-applicable-methods.foo.2
30    (equalp
31     (mop:compute-applicable-methods #'mop-test.foo '(x y))
32     (mop:compute-applicable-methods-using-classes
33      #'mop-test.foo (find-classes 'symbol 'symbol)))
34  t)
35
36(deftest compute-applicable-methods.foo.3
37    (equalp
38     (mop:compute-applicable-methods #'mop-test.foo '(111 y))
39     (mop:compute-applicable-methods-using-classes
40      #'mop-test.foo (find-classes 'fixnum 'symbol)))
41  t)
42
43(deftest compute-applicable-methods.foo.4
44    (equalp
45     (mop:compute-applicable-methods #'mop-test.foo '(x 111))
46     (mop:compute-applicable-methods-using-classes
47      #'mop-test.foo (find-classes 'symbol  'fixnum)))
48  t)
49
50(deftest compute-applicable-methods.foo.5
51    (equalp
52     (mop:compute-applicable-methods #'mop-test.foo '(111 "asdf"))
53     (mop:compute-applicable-methods-using-classes
54      #'mop-test.foo (find-classes 'fixnum  'simple-base-string)))
55  t)
56
57(deftest compute-applicable-methods.foo.6
58    (equalp (mop:compute-applicable-methods #'mop-test.foo '(111 222))
59      (list (find-foo 'fixnum 'fixnum)
60      (find-foo 'fixnum t)
61      (find-foo t t)))
62  t)
63
64(deftest compute-applicable-methods.foo.7
65    (equalp (mop:compute-applicable-methods #'mop-test.foo '(111 x))
66      (list (find-foo 'fixnum t)
67      (find-foo t t)))
68  t)
69
70(deftest compute-applicable-methods.foo.8
71    (equalp (mop:compute-applicable-methods #'mop-test.foo '(x 222))
72      (list (find-foo t t)))
73  t)
74
75
76(deftest compute-applicable-methods.bar.1
77    (equalp
78     (mop:compute-applicable-methods #'mop-test.bar '(111 222))
79     (mop:compute-applicable-methods-using-classes
80      #'mop-test.bar (find-classes 'fixnum 'fixnum)))
81  ;;; Bar with two fixnums might select EQL specializer for second
82  ;;; argument.
83  nil)
84
85(deftest compute-applicable-methods.bar.1a
86    (equalp
87     (mop:compute-applicable-methods #'mop-test.bar '(111 222))
88     (list (find-bar 'fixnum 'fixnum)
89     (find-bar 'fixnum t)
90     (find-bar t t)))
91  t)
92
93(deftest compute-applicable-methods.bar.1b
94    (equalp
95     (mop:compute-applicable-methods #'mop-test.bar '(111 123))
96     (list (find-method #'mop-test.bar nil (list (find-class 'fixnum) '(eql 123)))
97     (find-bar 'fixnum 'fixnum)
98     (find-bar 'fixnum t)
99     (find-bar t t)))
100  t)
101
102(deftest compute-applicable-methods.bar.1c
103    (mop:compute-applicable-methods-using-classes
104     #'mop-test.bar (find-classes 'fixnum 'fixnum))
105  nil
106  nil)
107
108(deftest compute-applicable-methods.bar.2
109    (equalp
110     (mop:compute-applicable-methods #'mop-test.bar '(x y))
111     (mop:compute-applicable-methods-using-classes
112      #'mop-test.bar (find-classes 'symbol 'symbol)))
113  t)
114
115(deftest compute-applicable-methods.bar.2a
116    (equalp
117     (mop:compute-applicable-methods #'mop-test.bar '(x y))
118     (list (find-bar t t)))
119  t)
120
121(deftest compute-applicable-methods.bar.3
122    (equalp
123     (mop:compute-applicable-methods #'mop-test.bar '(111 y))
124     (mop:compute-applicable-methods-using-classes
125      #'mop-test.bar (find-classes 'fixnum 'symbol)))
126  t)
127
128(deftest compute-applicable-methods.bar.3a
129    (equalp
130     (mop:compute-applicable-methods #'mop-test.bar '(111 y))
131     (list (find-bar 'fixnum t)
132     (find-bar t t)))
133  t)
134
135(deftest compute-applicable-methods.bar.4
136    (equalp
137     (mop:compute-applicable-methods #'mop-test.bar '(x 111))
138     (mop:compute-applicable-methods-using-classes
139      #'mop-test.bar (find-classes 'symbol  'fixnum)))
140  t)
141
142(deftest compute-applicable-methods.bar.4a
143    (equalp
144     (mop:compute-applicable-methods #'mop-test.bar '(x 111))
145     (list (find-bar t t)))
146  t)
147
148(deftest compute-applicable-methods.bar.5
149    (equalp
150     (mop:compute-applicable-methods #'mop-test.bar '(111 "asdf"))
151     (mop:compute-applicable-methods-using-classes
152      #'mop-test.bar (find-classes 'fixnum  'simple-base-string)))
153  t)
154
155(deftest compute-applicable-methods.bar.5a
156    (equalp
157     (mop:compute-applicable-methods #'mop-test.bar '(111 "asdf"))
158     (list (find-bar 'fixnum 'string)
159     (find-bar 'fixnum t)
160     (find-bar t t)))
161  t)
162
163
164(deftest compute-applicable-methods.baz.1
165    (equalp
166     (mop:compute-applicable-methods #'mop-test.baz '(111 222))
167     (mop:compute-applicable-methods-using-classes
168      #'mop-test.baz (find-classes 'fixnum 'fixnum)))
169  ;; Two fixnum arguments might select EQL specializer for first
170  ;; argument.
171  nil)
172
173(deftest compute-applicable-methods.baz.1a
174    (equalp
175     (mop:compute-applicable-methods #'mop-test.baz '(111 222))
176     (list (find-baz 'fixnum 'fixnum)
177     (find-baz 'fixnum t)
178     (find-baz t t)))
179  t)
180
181(deftest compute-applicable-methods.baz.1b
182    (equalp
183     (mop:compute-applicable-methods #'mop-test.baz '(234 222))
184     (list (find-method #'mop-test.baz nil (list '(eql 234) (find-class 'fixnum)))
185     (find-baz 'fixnum 'fixnum)
186     (find-baz 'fixnum t)
187     (find-baz t t)))
188  t)
189
190(deftest compute-applicable-methods.baz.1c
191    (mop:compute-applicable-methods-using-classes
192     #'mop-test.baz (find-classes 'fixnum 'fixnum))
193  nil
194  nil)
195
196(deftest compute-applicable-methods.baz.2
197    (equalp
198     (mop:compute-applicable-methods #'mop-test.baz '(x y))
199     (mop:compute-applicable-methods-using-classes
200      #'mop-test.baz (find-classes 'symbol 'symbol)))
201  t)
202
203(deftest compute-applicable-methods.baz.3
204    (equalp
205     (mop:compute-applicable-methods #'mop-test.baz '(111 y))
206     (mop:compute-applicable-methods-using-classes
207      #'mop-test.baz (find-classes 'fixnum 'symbol)))
208  t)
209
210(deftest compute-applicable-methods.baz.4
211    (equalp
212     (mop:compute-applicable-methods #'mop-test.baz '(x 111))
213     (mop:compute-applicable-methods-using-classes
214      #'mop-test.baz (find-classes 'symbol  'fixnum)))
215  t)
216
217(deftest compute-applicable-methods.baz.5
218    (equalp
219     (mop:compute-applicable-methods #'mop-test.baz '(111 "asdf"))
220     (mop:compute-applicable-methods-using-classes
221      #'mop-test.baz (find-classes 'fixnum  'simple-base-string)))
222  t)
223
224
225(deftest compute-applicable-methods.quux.1
226    (equalp
227     (mop:compute-applicable-methods #'mop-test.quux '(111 222))
228     (mop:compute-applicable-methods-using-classes
229      #'mop-test.quux (find-classes 'fixnum 'fixnum)))
230  t)
231
232(deftest compute-applicable-methods.quux.1a
233    (equalp
234     (mop:compute-applicable-methods #'mop-test.quux '(111 222))
235     (list (find-quux 'fixnum 'fixnum)
236     (find-quux 'fixnum t)
237     (find-quux t t)))
238  t)
239
240(deftest compute-applicable-methods.quux.2
241    (equalp
242     (mop:compute-applicable-methods #'mop-test.quux '(x y))
243     (mop:compute-applicable-methods-using-classes
244      #'mop-test.quux (find-classes 'symbol 'symbol)))
245  t)
246
247(deftest compute-applicable-methods.quux.2a
248    (equalp
249     (mop:compute-applicable-methods #'mop-test.quux '(x y))
250     (list (find-quux t t)))
251  t)
252
253(deftest compute-applicable-methods.quux.3
254    (equalp
255     (mop:compute-applicable-methods #'mop-test.quux '(111 y))
256     (mop:compute-applicable-methods-using-classes
257      #'mop-test.quux (find-classes 'fixnum 'symbol)))
258  t)
259
260(deftest compute-applicable-methods.quux.3a
261    (equalp
262     (mop:compute-applicable-methods #'mop-test.quux '(111 y))
263     (list (find-quux 'fixnum t)
264     (find-quux t t)))
265  t)
266
267(deftest compute-applicable-methods.quux.4
268    (equalp
269     (mop:compute-applicable-methods #'mop-test.quux '(x 111))
270     (mop:compute-applicable-methods-using-classes
271      #'mop-test.quux (find-classes 'symbol  'fixnum)))
272  ;; Symbol/fixnum might trigger EQL spezializer
273  nil)
274
275(deftest compute-applicable-methods.quux.4a
276    (equalp
277     (mop:compute-applicable-methods #'mop-test.quux '(x 111))
278     (list (find-quux t t)))
279  t)
280
281(deftest compute-applicable-methods.quux.4b
282    (equalp
283     (mop:compute-applicable-methods #'mop-test.quux '(:foo 111))
284     (list (find-method #'mop-test.quux nil
285      (list '(eql :foo) (find-class 'fixnum)))
286
287     (find-quux t t)))
288  t)
289
290(deftest compute-applicable-methods.quux.4c
291    (mop:compute-applicable-methods-using-classes
292     #'mop-test.quux (find-classes 'symbol 'fixnum))
293  nil
294  nil)
295
296(deftest compute-applicable-methods.quux.5
297    (equalp
298     (mop:compute-applicable-methods #'mop-test.quux '(111 "asdf"))
299     (mop:compute-applicable-methods-using-classes
300      #'mop-test.quux (find-classes 'fixnum  'simple-base-string)))
301  t)
302
303
304
305;; tests for D-M-C, long form, taken from SBCL
306
307;; D-M-C should return the name of the new method combination, nothing else.
308
309(deftest dmc-return.1
310    (define-method-combination dmc-test-return-foo)
311  dmc-test-return-foo)
312
313(deftest dmc-return.2
314    (define-method-combination dmc-test-return-bar :operator and)
315  dmc-test-return-bar)
316
317(deftest dmc-return.3
318    (define-method-combination dmc-test-return
319        (&optional (order :most-specific-first))
320      ((around (:around))
321       (primary (dmc-test-return) :order order :required t))
322      (let ((form (if (rest primary)
323                      `(and ,@(mapcar #'(lambda (method)
324                                          `(call-method ,method))
325                                      primary))
326                      `(call-method ,(first primary)))))
327        (if around
328            `(call-method ,(first around)
329                          (,@(rest around)
330                             (make-method ,form)))
331            form)))
332  dmc-test-return)
333
334;; A method combination which originally failed;
335;;   for different reasons in SBCL than in ABCL (hence leaving out
336;;   the original comment)
337
338(define-method-combination dmc-test-mc.1
339    (&optional (order :most-specific-first))
340  ((around (:around))
341   (primary (dmc-test-mc) :order order :required t))
342  (let ((form (if (rest primary)
343                  `(and ,@(mapcar #'(lambda (method)
344                                      `(call-method ,method))
345                                  primary))
346                  `(call-method ,(first primary)))))
347    (if around
348        `(call-method ,(first around)
349                      (,@(rest around)
350                         (make-method ,form)))
351        form)))
352
353(defgeneric dmc-test-mc.1 (&key k) (:method-combination dmc-test-mc.1))
354
355(defmethod dmc-test-mc.1 dmc-test-mc (&key k)
356  k)
357
358(deftest dmc-test-mc.1
359    (dmc-test-mc.1 :k 1)
360  1)
361
362
363;; Completely DIY -- also taken from SBCL:
364(define-method-combination dmc-test-mc.2 ()
365  ((all-methods *))
366  (do ((methods all-methods (rest methods))
367       (primary nil)
368       (around nil))
369      ((null methods)
370       (let ((primary (nreverse primary))
371             (around (nreverse around)))
372         (if primary
373              (let ((form (if (rest primary)
374                             `(call-method ,(first primary) ,(rest primary))
375                             `(call-method ,(first primary)))))
376                (if around
377                    `(call-method ,(first around) (,@(rest around)
378                                                   (make-method ,form)))
379                    form))
380              `(make-method (error "No primary methods")))))
381    (let* ((method (first methods))
382           (qualifier (first (method-qualifiers method))))
383      (cond
384        ((equal :around qualifier)
385         (push method around))
386        ((null qualifier)
387         (push method primary))))))
388
389(defgeneric dmc-test-mc.2a (val)
390  (:method-combination dmc-test-mc.2))
391
392(defmethod dmc-test-mc.2a ((val number))
393  (+ val (if (next-method-p) (call-next-method) 0)))
394
395(deftest dmc-test-mc.2a
396    (= (dmc-test-mc.2a 13) 13)
397  T)
398
399(defgeneric dmc-test-mc.2b (val)
400  (:method-combination dmc-test-mc.2))
401
402(defmethod dmc-test-mc.2b ((val number))
403  (+ val (if (next-method-p) (call-next-method) 0)))
404
405(defmethod dmc-test-mc.2b :around ((val number))
406  (+ val (if (next-method-p) (call-next-method) 0)))
407
408(deftest dmc-test-mc.2b
409    (= 26 (dmc-test-mc.2b 13))
410  T)
411
412
413;;; Taken from SBCL: error when method sorting is ambiguous
414;;;  with multiple method groups
415
416(define-method-combination dmc-test-mc.3a ()
417  ((around (:around))
418   (primary * :required t))
419  (let ((form (if (rest primary)
420                  `(call-method ,(first primary) ,(rest primary))
421                  `(call-method ,(first primary)))))
422    (if around
423        `(call-method ,(first around) (,@(rest around)
424                                       (make-method ,form)))
425        form)))
426
427(defgeneric dmc-test-mc.3a (val)
428  (:method-combination dmc-test-mc.3a))
429
430(defmethod dmc-test-mc.3a ((val number))
431  (+ val (if (next-method-p) (call-next-method) 0)))
432
433(defmethod dmc-test-mc.3a :around ((val number))
434  (+ val (if (next-method-p) (call-next-method) 0)))
435
436(defmethod dmc-test-mc.3a :somethingelse ((val number))
437  (+ val (if (next-method-p) (call-next-method) 0)))
438
439(deftest dmc-test-mc.3a
440    (multiple-value-bind
441          (value error)
442        (ignore-errors (wam-test-mc.3a 13))
443      (declare (ignore value))
444      (typep error 'error))
445  T)
446
447;;; Taken from SBCL: error when method sorting is ambiguous
448;;;  with a single (non *) method group
449
450
451(define-method-combination dmc-test-mc.3b ()
452  ((methods listp :required t))
453  (if (rest methods)
454      `(call-method ,(first methods) ,(rest methods))
455      `(call-method ,(first methods))))
456
457(defgeneric dmc-test-mc.3b (val)
458  (:method-combination dmc-test-mc.3b))
459
460(defmethod dmc-test-mc.3b :foo ((val number))
461  (+ val (if (next-method-p) (call-next-method) 0)))
462
463(defmethod dmc-test-mc.3b :bar ((val number))
464  (+ val (if (next-method-p) (call-next-method) 0)))
465
466(deftest dmc-test-mc.3b
467    (multiple-value-bind
468          (value error)
469        (ignore-errors (dmc-test-mc.3b 13))
470      (declare (ignore value))
471      (typep error 'error))
472  T)
473
474
475;; Taken from SBCL: test that GF invocation arguments
476;;   are correctly bound using the (:arguments ...) form
477
478(defparameter *dmc-test-4* nil)
479
480(defun object-lock (obj)
481  (push "object-lock" *dmc-test-4*)
482  obj)
483(defun unlock (obj)
484  (push "unlock" *dmc-test-4*)
485  obj)
486(defun lock (obj)
487  (push "lock" *dmc-test-4*)
488  obj)
489
490
491(define-method-combination dmc-test-mc.4 ()
492  ((methods *))
493  (:arguments object)
494  `(unwind-protect
495        (progn (lock (object-lock ,object))
496               ,@(mapcar #'(lambda (method)
497                             `(call-method ,method))
498                         methods))
499     (unlock (object-lock ,object))))
500
501(defgeneric dmc-test.4 (x)
502  (:method-combination dmc-test-mc.4))
503(defmethod dmc-test.4 ((x symbol))
504  (push "primary" *dmc-test-4*))
505(defmethod dmc-test.4 ((x number))
506  (error "foo"))
507
508(deftest dmc-test.4a
509    (progn
510      (setq *dmc-test-4* nil)
511      (values (equal (dmc-test.4 t) '("primary" "lock" "object-lock"))
512              (equal *dmc-test-4* '("unlock" "object-lock"
513                                    "primary" "lock" "object-lock"))))
514  T T)
515
516(deftest dmc-test.4b
517    (progn
518      (setq *dmc-test-4* nil)
519      (ignore-errors (dmc-test.4 1))
520      (equal *dmc-test-4* '("unlock" "object-lock" "lock" "object-lock")))
521  T)
522
523
524;; From SBCL: method combination (long form) with arguments
525
526(define-method-combination dmc-test.5 ()
527  ((method-list *))
528  (:arguments arg1 arg2 &aux (extra :extra))
529  `(progn ,@(mapcar (lambda (method) `(call-method ,method)) method-list)))
530
531(defgeneric dmc-test-mc.5 (p1 p2 s)
532  (:method-combination dmc-test.5)
533  (:method ((p1 number) (p2 t) s)
534    (vector-push-extend (list 'number p1 p2) s))
535  (:method ((p1 string) (p2 t) s)
536    (vector-push-extend (list 'string p1 p2) s))
537  (:method ((p1 t) (p2 t) s) (vector-push-extend (list t p1 p2) s)))
538
539(deftest dmc-test.5a
540    (let ((v (make-array 0 :adjustable t :fill-pointer t)))
541      (values (dmc-test-mc.5 1 2 v)
542              (equal (aref v 0) '(number 1 2))
543              (equal (aref v 1) '(t 1 2))))
544  1 T T)
545
546
547
548(define-method-combination dmc-test.6 ()
549  ((normal ())
550   (ignored (:ignore :unused)))
551  `(list 'result
552    ,@(mapcar #'(lambda (method) `(call-method ,method)) normal)))
553
554(defgeneric dmc-test-mc.6 (x)
555  (:method-combination dmc-test.6)
556  (:method :ignore ((x number)) (/ 0)))
557
558(deftest dmc-test-mc.6a
559    (multiple-value-bind
560          (value error)
561        (ignore-errors (dmc-test-mc.6 7))
562      (values (null value)
563              (typep error 'error)))
564  T T)
565
566
567(define-method-combination dmc-test.7 ()
568  ((methods *))
569  (:arguments x &rest others)
570  `(progn
571     ,@(mapcar (lambda (method)
572                 `(call-method ,method))
573               methods)
574     (list ,x (length ',others))))
575
576(defgeneric dmc-test-mc.7 (x &rest others)
577  (:method-combination dmc-test.7))
578
579(defmethod dmc-test-mc.7 (x &rest others)
580  (declare (ignore others))
581  nil)
582
583(deftest dmc-test-mc.7a
584    (equal (apply #'dmc-test-mc.7 :foo (list 1 2 3 4 5 6 7 8))
585           '(:foo 8))
586  T)
587
588
589(defclass foo-class (standard-class))
590(defmethod mop:validate-superclass ((class foo-class) (superclass standard-object))
591  t)
592
593(deftest validate-superclass.1
594    (mop:validate-superclass
595     (make-instance 'foo-class)
596     (make-instance 'standard-object))
597  t)
598
599
600(defgeneric apply-rule (rule))
601(defmethod apply-rule ((rule t) &aux (context (format nil "~A" rule)))
602  (format nil "Applying rule '~A' in context '~A'" rule context))
603
604;;; See ticket # 199
605(deftest defmethod-&aux.1
606    (apply-rule "1")
607  "Applying rule '1' in context '1'")
608   
Note: See TracBrowser for help on using the repository browser.