Initial Commit
[packages] / xemacs-packages / eieio / eieio-tests.el
1 ;;; eieio-tests.el -- eieio tests routines
2
3 ;;;
4 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2006 Eric M. Ludlam
5 ;;
6 ;; Author: <zappo@gnu.org>
7 ;; RCS: $Id: eieio-tests.el,v 1.4 2007-11-26 15:01:05 michaels Exp $
8 ;; Keywords: oop, lisp, tools
9 ;;
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14 ;;
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
19 ;;
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24 ;;
25 ;; Please send bug reports, etc. to zappo@gnu.org
26 ;;
27
28 ;;; Commentary:
29 ;;  
30 ;; Test the various features of EIEIO.  To run the tests, evaluate the
31 ;; entire buffer.
32
33 (require 'eieio-base)
34
35 ;;; Code:
36
37 ;;; Multiple Inheritance, and method signal testing
38 ;;
39 (defclass class-a ()
40   ((water :initarg :water
41           :initform h20
42           :type symbol
43           :documentation "Detail about water.")
44    (classslot :initform penguin
45               :type symbol
46               :documentation "A class allocated slot."
47               :allocation :class)
48    (test-tag :initform nil
49              :documentation "Used to make sure methods are called.")
50    (self :initform nil
51          :type (or null class-a)
52          :documentation "Test self referencing types.")
53    )
54   "Class A")
55
56 (condition-case msg
57
58     (progn
59       (defclass class-alloc-initarg ()
60         ((throwwarning :initarg :throwwarning
61                        :allocation :class))
62         "Throw a warning mixing allocation class and an initarg.")
63
64       (if (not (string-match "Class allocated slots do not need :initarg"
65                              (current-message)))
66           (error ":initarg and :allocation warning not thrown!"))
67       )
68   (error (error msg)))
69   
70
71 (defclass class-b ()
72   ((land :initform "Sc"
73          :type string
74          :documentation "Detail about land."))
75   "Class b")
76
77 (defclass class-ab (class-a class-b)
78   ((amphibian :initform "frog"
79               :documentation "Detail about amphibian on land and water."))
80   "Class A and B combined.")
81
82 \f
83 ;;; Defining a class with a slot tag error
84 ;;
85 (let ((eieio-error-unsupported-class-tags t))
86   (condition-case nil
87       (progn
88         (defclass class-error ()
89           ((error-slot :initarg :error-slot
90                        :badslottag 1))
91           "A class with a bad slot tag.")
92         (error "No error was thrown for badslottag"))
93     (invalid-slot-type nil)))
94
95 (let ((eieio-error-unsupported-class-tags nil))
96   (condition-case nil
97       (progn
98         (defclass class-error ()
99           ((error-slot :initarg :error-slot
100                        :badslottag 1))
101           "A class with a bad slot tag."))
102     (invalid-slot-type
103      (error "invalid-slot-type thrown when eieio-error-unsupported-class-tags is nil")
104      )))
105
106 ;;; Abstract base classes
107 ;;
108 (defclass abstract-class ()
109   ((some-slot :initarg :some-slot
110               :initform nil
111               :documentation "A slot."))
112   :documentation "An abstract claptionass."
113   :abstract t)
114
115 (if (condition-case nil
116         (progn
117           (abstract-class "Test")
118           t)
119       (error nil))
120     (error "Instantiation of an abstract class allowed."))
121
122 ;;; Generics (and the definition therof)
123 ;;
124 (defun anormalfunction () "A plain function for error testing." nil)
125
126 (if (condition-case nil
127         (defgeneric anormalfunction () 
128           "Attempt to turn it into a generic.")
129       (error nil))
130     (error "Generic function created over an existing function."))
131
132 (defgeneric generic1 () "First generic function")
133
134 (if (not (generic-p 'generic1))
135     (error "defgeneric did not make a generic method."))
136
137 (defmethod generic1 ((c class-a))
138   "Method on generic1.")
139
140 ;;; Class with a static method
141 ;;
142 (defclass static-method-class ()
143   ((some-slot :initform nil
144               :allocation :class
145               :documentation "A slot."))
146   :documentation "A class used for testing static methods.")
147
148 (defmethod static-method-class-method :STATIC ((c static-method-class) value)
149   "Test static methods.
150 Argument C is the class bound to this static method."
151   (if (object-p c) (setq c (object-class c)))
152   (oset-default c some-slot value))
153
154 (condition-case nil
155     (static-method-class-method static-method-class 'class)
156   (error (error "Failed to call static method on a class.")))
157 (if (not (eq (oref static-method-class some-slot) 'class))
158     (error "Call to static method on a class did not run."))
159
160 (condition-case nil
161     (static-method-class-method (static-method-class "test") 'object)
162   (error (error "Failed to call static method on an object.")))
163 (if (not (eq (oref static-method-class some-slot) 'object))
164     (error "Call to static method on an object did not run."))
165
166 (defclass static-method-class-2 (static-method-class)
167   ()
168   "A second class after the previous for static methods.")
169
170 (defmethod static-method-class-method :STATIC ((c static-method-class-2) value)
171   "Test static methods.
172 Argument C is the class bound to this static method."
173   (if (object-p c) (setq c (object-class c)))
174   (oset-default c some-slot (intern (concat "moose-" (symbol-name value)))))
175
176 (condition-case nil
177     (static-method-class-method static-method-class-2 'class)
178   (error (error "Failed to call 2nd static method on a class.")))
179 (if (not (eq (oref static-method-class-2 some-slot) 'moose-class))
180     (error "Call to 2nd static method on a class did not run."))
181
182 (condition-case nil
183     (static-method-class-method (static-method-class-2 "test") 'object)
184   (error (error "Failed to call 2nd static method on an object.")))
185 (if (not (eq (oref static-method-class-2 some-slot) 'moose-object))
186     (error "Call to 2nd static method on an object did not run."))
187
188 \f
189 ;;; Perform method testing
190 ;;
191
192 ;; allocate an object to use
193 (defvar ab nil)
194 (setq ab (class-ab "abby"))
195 (defvar a nil)
196 (setq a (class-a "aye"))
197 (defvar b nil)
198 (setq b (class-b "fooby"))
199
200 (condition-case nil
201     (progn
202       ;; Try make-instance on these guys...
203       (make-instance 'class-ab)
204       (make-instance 'class-a :water 'cho)
205       (make-instance 'class-b "a name")
206       )
207   (error "make-instance error."))
208
209 ;; Play with call-next-method
210 (defmethod class-cn ((a class-a))
211   "Try calling `call-next-method' when there isn't one.
212 Argument A is object of type symbol `class-a'."
213   (call-next-method)
214   )
215
216 (defmethod no-next-method ((a class-a))
217   "Override signal throwing for variable `class-a'.
218 Argument A is the object of class variable `class-a'."
219   'moose)
220
221 (if (eq (class-cn ab) 'moose)
222     nil
223   (error "no-next-method return value failure."))
224
225 ;; Non-existing methods.
226 (defmethod no-applicable-method ((b class-b) method)
227   "No need.
228 Argument B is for booger.
229 METHOD is the method that was attempting to be called."
230   'moose)
231
232 (if (eq (class-cn b) 'moose)
233     nil
234   (error "no-applicable-method return value failure."))
235
236 ;;; play with methods and mi
237 (defmethod class-fun ((a class-a))
238   "Fun with class A."
239   'moose)
240
241 (defmethod class-fun ((b class-b))
242   "Fun with class B."
243   (error "Class B fun should not be called")
244   )
245
246 (if (eq (class-fun ab) 'moose)
247     nil
248   (error "Inheritance method check."))
249
250 (defmethod class-fun-foo ((b class-b))
251   "Foo Fun with class B."
252   'moose)
253
254 (if (eq (class-fun-foo ab) 'moose)
255     nil
256   (error "Multiple inheritance method check."))
257
258 ;; Play with next-method and mi
259 (defmethod class-fun2 ((a class-a))
260   "More fun with class A."
261   'moose)
262
263 (defmethod class-fun2 ((b class-b))
264   "More fun with class B."
265   (error "Class B fun2 should not be called")
266   )
267
268 (defmethod class-fun2 ((ab class-ab))
269   "More fun with class AB."
270   (call-next-method))
271
272 (if (eq (class-fun2 ab) 'moose)
273     nil
274   (error "Call next method inheritance check failed."))
275
276 ;; How about if B is the only slot?
277 (defmethod class-fun3 ((b class-b))
278   "Even More fun with class B."
279   'moose)
280
281 (defmethod class-fun3 ((ab class-ab))
282   "Even More fun with class AB."
283   (call-next-method))
284
285 (if (eq (class-fun3 ab) 'moose)
286     nil
287   (error "Call next method MI check failed."))
288
289 ;; Try the self referencing test
290 (oset a self a)
291 (oset ab self ab)
292
293 \f
294 ;;; Test the BEFORE, PRIMARY, and AFTER method tags.
295 ;;
296 (load-library "eieio-test-methodinvoke.el")
297
298 ;;; Test value of a generic function call
299 ;;
300 (defvar class-fun-value-seq '())
301
302 (defmethod class-fun-value :BEFORE ((a class-a))
303   "Return `before', and push `before' in `class-fun-value-seq'."
304   (push 'before class-fun-value-seq)
305   'before)
306
307 (defmethod class-fun-value :PRIMARY ((a class-a))
308   "Return `primary', and push `primary' in `class-fun-value-seq'."
309   (push 'primary class-fun-value-seq)
310   'primary)
311
312 (defmethod class-fun-value :AFTER ((a class-a))
313   "Return `after', and push `after' in `class-fun-value-seq'."
314   (push 'after class-fun-value-seq)
315   'after)
316
317 (let* ((class-fun-value-seq nil)
318        (value (class-fun-value a)))
319   (unless (eq value 'primary)
320     (error
321      "Value of the generic function call isn't the primary method value [%S]."
322      value))
323   (unless (equal class-fun-value-seq '(after primary before))
324     (error "Methods were not called from :BEFORE to :AFTER.")))
325
326 \f
327 ;;; Test initialization methods
328 ;;
329 (defmethod initialize-instance ((a class-a) &rest slots)
330   "Initialize the slots of class-a."
331   (call-next-method)
332   (if (/= (oref a test-tag) 1)
333       (error "shared-initialize test failed."))
334   (oset a test-tag 2))
335
336 (defmethod shared-initialize ((a class-a) &rest slots)
337   "Shared initialize method for class-a."
338   (call-next-method)
339   (oset a test-tag 1))
340
341 (let ((ca (class-a "class act")))
342   (if (/=  (oref ca test-tag) 2)
343       (error "initialize-instance test failed."))
344   )
345
346 \f
347 ;;; Perform slot testing
348 ;;
349 (if (and (oref ab water)
350          (oref ab land)
351          (oref ab amphibian))
352     nil
353   (error "Slot checks failed"))
354
355 (defmethod slot-missing ((ab class-ab) &rest foo)
356   "If a slot in AB is unbound, return something cool.  FOO."
357   'moose)
358
359 (if (eq (oref ab ooga-booga) 'moose)
360     nil
361   (error "Missing slot override failed."))
362
363 (condition-case nil
364     (progn
365       (oref a ooga-booga)
366       (error "No invalid slot error thrown."))
367   (invalid-slot-name nil))
368
369 (slot-makeunbound a 'water)
370
371 (if (slot-boundp a 'water)
372     (error "Slot makeunbound failed slot-bound-p test"))
373
374 (if (and (slot-exists-p a 'water)
375          (not (slot-exists-p a 'moose)))
376     nil
377   (error "Slot exists-p failed"))
378
379 (condition-case nil
380     (progn
381       (oref a water)
382       (error ""))
383   (unbound-slot nil)
384   (error (error "Oref of unbound slot succeeded.")))
385   
386
387 (defmethod slot-unbound ((a class-a) &rest foo)
388   "If a slot in A is unbound, ignore FOO."
389   'moose)
390
391 (if (eq (oref a water) 'moose)
392     nil
393   (error "Unbound slot reference failed."))
394
395 (oset a water 'moose)
396 (if (eq (oref a water) 'moose)
397     nil
398   (error "Oset of unbound failed."))
399
400 (if (not (eq (oref a water) (oref-default a water)))
401     nil
402   (error "oref/oref-default comparison failed."))
403
404 (oset-default (object-class a) water 'moose)
405 (if (eq (oref a water) (oref-default a water))
406     nil
407   (error "oset-default -> oref/oref-default comparison failed."))
408
409 ;; After setting 'water to 'moose, make sure a new object has
410 ;; the right stuff.
411 (oset-default (object-class a) water 'penguin)
412 (if (eq (oref (class-a "foo") water) 'penguin)
413     nil
414   (error "oset-default, new instance value failed."))
415
416 (defmethod slot-unbound ((a class-a) &rest foo)
417   "If a slot in A is unbound, ignore FOO."
418   ;; Disable the old slot-unbound so we can run this test
419   ;; more than once
420   (call-next-method))
421
422 ;; Slot type checking
423 (condition-case nil
424     (progn
425       (oset ab water "a string, not a symbol")
426       (error "Slot set to invalid type successfully."))
427   (invalid-slot-type nil))
428
429 (condition-case nil
430     (progn
431       (oset ab classslot "a string, not a symbol")
432       (error "Slot set to invalid type successfully."))
433   (invalid-slot-type nil))
434
435 (condition-case nil
436     (progn
437       (class-a "broken-type-a" :water "a string not a symbol")
438       (error "Slot set to invalid type at creation successfully."))
439   (invalid-slot-type nil))
440
441 ;; Test out class allocated slots
442 (defvar aa nil)
443 (setq aa (class-a "another"))
444
445 (let ((newval 'moose))
446   (oset aa classslot newval)
447   (if (and (eq (oref a classslot) newval)
448            (eq (oref aa classslot) newval))
449       nil
450     (error "Class slots are tracking between objects")))
451
452 (if (not (slot-boundp a 'classslot))
453     (error "Class allocatd slot thought unbound when it is bound."))
454
455 (if (not (slot-boundp class-a 'classslot))
456     (error "Class allocatd slot thought unbound when it is bound."))
457
458 (slot-makeunbound a 'classslot)
459
460 (if (slot-boundp a 'classslot)
461     (error "Class allocatd slot thought bound when it is unbound."))
462
463 (if (slot-boundp class-a 'classslot)
464     (error "Class allocatd slot thought bound when it is unbound."))
465
466 \f
467 ;;; Test function type in a class
468 ;;
469 (defvar class-typep-var 0
470   "A variable used in an initform.")
471
472 (setq class-typep-var 1)
473
474 (defclass class-typep ()
475   ((slot1 :type function
476           :initform <
477           )
478    (slot2 :type integer
479           :initform (lambda () class-typep-var)
480           )
481    (slot4 :type function
482           :initform (lambda-default () 2)
483           )
484    )
485   "Test different types in a class.")
486
487 (setq class-typep-var 2)
488
489 (defvar ct nil)
490 (setq ct (class-typep "foo"))
491
492 (if (/= (oref ct slot2) 2)
493     (error "Default value for slot2 incorrect.")) 
494
495 \f
496 ;;; Inheritance status
497 ;;
498 (if (and
499      (child-of-class-p class-ab class-a)
500      (child-of-class-p class-ab class-b)
501      (object-of-class-p a class-a)
502      (object-of-class-p ab class-a)
503      (object-of-class-p ab class-b)
504      (object-of-class-p ab class-ab)
505      (eq (class-parents class-a) nil)
506      (equal (class-parents class-ab) '(class-a class-b))
507      (same-class-p a class-a)
508      (class-a-p a)
509      (not (class-a-p ab))
510      (class-a-child-p a)
511      (class-a-child-p ab)
512      (not (class-a-p "foo"))
513      (not (class-a-child-p "foo"))
514      )
515     nil
516   (error "Inheritance tests: failed"))
517
518 \f
519 ;;; Slot parameter testing
520 ;;
521 (defclass class-c ()
522   ((slot-1 :initarg :moose
523            :initform moose
524            :type symbol
525            :allocation :instance
526            :documentation "Fisrt slot testing slot arguments."
527            :custom symbol
528            :label "Wild Animal"
529            :group borg
530            :protection :public)
531    (slot-2 :initarg :penguin
532            :initform "penguin"
533            :type string
534            :allocation :instance
535            :documentation "Second slot testing slot arguments."
536            :custom string
537            :label "Wild bird"
538            :group vorlon
539            :accessor get-slot-2
540            :protection :private)
541    (slot-3 :initarg :emu
542            :initform emu
543            :type symbol
544            :allocation :class
545            :documentation "Third slot test class allocated accessor"
546            :custom symbol
547            :label "Fuzz"
548            :group tokra
549            :accessor get-slot-3
550            :protection :private)
551    )
552   (:custom-groups (foo))
553   "A class for testing slot arguments."
554   )
555
556 (defvar t1 nil)
557 (setq t1 (class-c "C1"))
558
559 (if (not (and (eq (oref t1 slot-1) 'moose)
560               (eq (oref t1 :moose) 'moose)))
561     (error "Initialization of slot failed."))
562
563 (condition-case nil
564     (progn
565       (oref t1 slot-2)
566       (error "Reference of private slot passed."))
567   (invalid-slot-name nil))
568
569 (if (not (string= (get-slot-2 t1) "penguin"))
570     (error "Accessor to private slot returned bad value."))
571
572 (condition-case nil
573     (progn
574       (class-c "C2" :moose "not a symbol")
575       (error "A string was set on a symbol slot during init."))
576   (invalid-slot-type nil))
577
578 (if (not (eq (get-slot-3 t1) 'emu))
579     (error "Accessor to private :class slot returned bad value from object."))
580
581 (if (not (eq (get-slot-3 class-c) 'emu))
582     (error "Accessor to private :class slot returned bad value from class."))
583
584 (setf (get-slot-3 t1) 'moose)
585 (if (not (eq (get-slot-3 t1) 'moose))
586     (error "setf and get through accessor failed!"))
587
588 ;; Slot protection
589 (defclass prot-0 ()
590   ()
591   "Protection testing baseclass.")
592
593 (defmethod prot0-slot-2 ((s2 prot-0))
594   "Try to access slot-2 from this class which doesn't have it.
595 The object S2 passed in will be of class prot-1, which does have
596 the slot.  This could be allowed, and currently is in EIEIO.
597 Needed by the eieio persistant base class."
598   (oref s2 slot-2))
599
600 (defclass prot-1 (prot-0)
601   ((slot-1 :initarg :slot-1
602            :initform nil
603            :protection :public)
604    (slot-2 :initarg :slot-2
605            :initform nil
606            :protection :protected)
607    (slot-3 :initarg :slot-3
608            :initform nil
609            :protection :private))
610   "A class for testing the :protection option.")
611
612 (defclass prot-2 (prot-1)
613   nil
614   "A class for testing the :protection option.")
615
616 (defmethod prot1-slot-2 ((s2 prot-1))
617   "Try to access slot-2 in S2."
618   (oref s2 slot-2))
619
620 (defmethod prot1-slot-2 ((s2 prot-2))
621   "Try to access slot-2 in S2."
622   (oref s2 slot-2))
623
624 (defmethod prot1-slot-3-only ((s2 prot-1))
625   "Try to access slot-3 in S2.
626 Do not override for `prot-2'."
627   (oref s2 slot-3))
628
629 (defmethod prot1-slot-3 ((s2 prot-1))
630   "Try to access slot-3 in S2."
631   (oref s2 slot-3))
632
633 (defmethod prot1-slot-3 ((s2 prot-2))
634   "Try to access slot-3 in S2."
635   (oref s2 slot-3))
636
637 (defvar p1 nil)
638 (setq p1 (prot-1 ""))
639 (defvar p2 nil)
640 (setq p2 (prot-2 ""))
641
642 (condition-case nil
643     (oref p1 slot-1)
644   (error (error "Error accessing public slot.")))
645 (condition-case nil
646     (oref p2 slot-1)
647   (error (error "Error accessing public slot.")))
648
649 (condition-case nil
650     (progn
651       (oref p1 slot-2)
652       (error "Accessing protected slot out of context succeeded."))
653   (error nil))
654 (condition-case nil
655     (prot1-slot-2 p1)
656   (error (error "Error accessing protected slot in a method.")))
657 (condition-case nil
658     (prot1-slot-2 p2)
659   (error (error "Error accessing protected slot in a subclass method.")))
660 (condition-case nil
661     (prot0-slot-2 p1)
662   (error (error "Error accessing protected slot from parent class method.")))
663
664 (condition-case nil
665     (progn
666       (oref p1 slot-3)
667       (error "Accessing private slot out of context succeeded."))
668   (error nil))
669 (condition-case nil
670     (prot1-slot-3 p1)
671   (error (error "Error accessing private slot in a method.")))
672 (condition-case nil
673     (progn
674       (prot1-slot-3 p2)
675       (error "Accessing private slot in a subclass method succeeded."))
676   (error nil))
677
678 (condition-case nil
679     (prot1-slot-3-only p1)
680   (error (error "Accessing private slot by same class failed.")))
681
682 (condition-case nil
683     (prot1-slot-3-only p2)
684   (error (error "Accessing private slot by subclass in sameclass method failed.")))
685
686 ;;; eieio-instance-inheritor
687 ;; Test to make sure this works.
688 (defclass II (eieio-instance-inheritor)
689   ((slot1 :initform 1)
690    (slot2)
691    (slot3))
692   "Instance Inheritor test class.")
693
694 (defvar II1 nil)
695 (setq II1 (II "II Test."))
696 (oset II1 slot2 'cat)
697 (defvar II2 nil)
698 (setq II2 (clone II1 "II2 Test."))
699 (oset II2 slot1 'moose)
700 (defvar II3 nil)
701 (setq II3 (clone II2 "II3 Test."))
702 (oset II3 slot3 'penguin)
703
704 (cond ((not (eq (oref II3 slot1) 'moose))
705        (error "Instance inheritor: Level one inheritance failed."))
706       ((not (eq (oref II3 slot2) 'cat))
707        (error "Instance inheritor: Level two inheritance failed."))
708       ((not (eq (oref II3 slot3) 'penguin))
709        (error "Instance inheritor: Level zero inheritance failed."))
710       (t t))
711
712 ;;; Test clone on boring objects too!
713 ;;
714 (defvar CLONETEST1 nil)
715 (defvar CLONETEST2 nil)
716 ;; A simple make instance with EIEIO extension
717 (setq CLONETEST1 (make-instance 'class-a "a"))
718 (setq CLONETEST2 (clone CLONETEST1))
719
720 ;; CLOS form of make-instance
721 (setq CLONETEST1 (make-instance 'class-a))
722 (setq CLONETEST2 (clone CLONETEST1))
723
724 \f
725 ;;; Test the persistent object, and object-write by side-effect.
726 ;;
727 (defclass PO (eieio-persistent)
728   ((slot1 :initarg :slot1
729           :initform 2)
730    (slot2 :initarg :slot2
731           :initform "foo"))
732   "A Persistent object with two initializable slots.")
733
734 (defvar PO1 nil)
735 (setq PO1 (PO "persist" :slot1 4 :slot2 "testing"
736               :file (concat default-directory "test-p.el")))
737
738 (eieio-persistent-save PO1)
739
740 (eieio-persistent-read "test-p.el")
741
742 \f
743 ;;; Test the instance tracker
744 ;;
745 (defclass IT (eieio-instance-tracker)
746   ((tracking-symbol :initform IT-list)
747    (slot1 :initform 'die))
748   "Instance Tracker test object.")
749
750 (defvar IT-list nil)
751 (defvar IT1 nil)
752 (setq IT1 (IT "trackme"))
753
754 (if (not (eieio-instance-tracker-find 'die 'slot1 'IT-list))
755     (error "Instance tracker lost an instance."))
756
757 (delete-instance IT1)
758
759 (if (eieio-instance-tracker-find 'die 'slot1 'IT-list)
760     (error "Instance tracker delete failed."))
761
762 \f
763 ;;; Test singletons
764 ;;
765 (defclass SINGLE (eieio-singleton)
766   ((a-slot :initarg :a-slot :initform t))
767   "A Singleton test object.")
768
769 (let ((obj1 (SINGLE "Moose"))
770       (obj2 (SINGLE "Cow")))
771   (if (not (and (object-p obj1)
772                 (object-p obj2)
773                 (eq obj1 obj2)
774                 (oref obj1 a-slot)))
775       (error "Two instances of a singleton")))
776
777 \f
778 ;;; Test the named object.
779 ;;
780 (defclass NAMED (eieio-named)
781   ((some-slot :initform nil)
782    )
783   "A class inheriting from eieio-named.")
784
785 (defvar N nil)
786 (setq N (NAMED "Foo"))
787
788 (if (not (string= "Foo" (oref N object-name)))
789     (error "Named object `object-name' slot ref failed."))
790
791 (condition-case err
792     (progn
793       (oref N missing-slot)
794       (error "Access to missing slot passed."))
795   (invalid-slot-name nil))
796
797 (oset N object-name "NewName")
798
799 (if (not (string= "NewName" (oref N object-name)))
800     (error "Named object `object-name' slot set/ref failed."))
801
802 \f
803 ;;; Test some utilities in EIEIO-OPT
804 ;;
805 (defclass opt-test1 ()
806   ()
807   "Abstract base class"
808   :abstract t)
809
810 (defclass opt-test2 (opt-test1)
811   ()
812   "Instantiable child")
813
814 (require 'eieio-opt)
815
816 (if (/= (length (eieio-build-class-alist opt-test1 nil)) 2)
817     (error "eieio-build-class-alist did not return all possible classes"))
818
819 (if (/= (length (eieio-build-class-alist opt-test1 t)) 1)
820     (error "eieio-build-class-alist did not filter on INSTANTIABLE-ONLY"))
821
822 \f
823 ;;;
824 (message "All tests passed.")
825
826 (provide 'eieio-tests)
827
828 ;;; eieio-tests.el ends here