+ ;; Check that ctor set up slot values correctly.
+ (format t "~&/checking constructed structure~%")
+ (assert (string= "some id" (read-slot cn "ID" *instance*)))
+ (assert (eql (find-package :cl) (read-slot cn "HOME" *instance*)))
+ (assert (string= "" (read-slot cn "COMMENT" *instance*)))
+ (assert (= 1.0 (read-slot cn "WEIGHT" *instance*)))
+ (assert (eql (+ 14 most-positive-fixnum)
+ (read-slot cn "HASH" *instance*)))
+ (assert (= 1 (read-slot cn "REFCOUNT" *instance*)))
+
+ ;; There should be no writers for read-only slots.
+ (format t "~&/checking no read-only writers~%")
+ (assert (not (fboundp `(setf ,(symbol+ cn "HOME")))))
+ (assert (not (fboundp `(setf ,(symbol+ cn "HASH")))))
+ ;; (Read-only slot values are checked in the loop below.)
+
+ (dolist (inlinep '(t nil))
+ (format t "~&/doing INLINEP=~S~%" inlinep)
+ ;; Fiddle with writable slot values.
+ (let ((new-id (format nil "~S" (random 100)))
+ (new-comment (format nil "~X" (random 5555)))
+ (new-weight (random 10.0)))
+ (write-slot new-id cn "ID" *instance* inlinep)
+ (write-slot new-comment cn "COMMENT" *instance* inlinep)
+ (write-slot new-weight cn "WEIGHT" *instance* inlinep)
+ (assert (eql new-id (read-slot cn "ID" *instance*)))
+ (assert (eql new-comment (read-slot cn "COMMENT" *instance*)))
+ ;;(unless (eql new-weight (read-slot cn "WEIGHT" *instance*))
+ ;; (error "WEIGHT mismatch: ~S vs. ~S"
+ ;; new-weight (read-slot cn "WEIGHT" *instance*)))
+ (assert (eql new-weight (read-slot cn "WEIGHT" *instance*)))))
+ (format t "~&/done with INLINEP loop~%")
+
+ ;; :TYPE FOO objects don't go in the Lisp type system, so we
+ ;; can't test TYPEP stuff for them.
+ ;;
+ ;; FIXME: However, when they're named, they do define
+ ;; predicate functions, and we could test those.
+ ,@(unless colontype
+ `(;; Fiddle with predicate function.
+ (let ((pred-name (symbol+ ',defstructname "-P")))
+ (format t "~&/doing tests on PRED-NAME=~S~%" pred-name)
+ (assert (funcall pred-name *instance*))
+ (assert (not (funcall pred-name 14)))
+ (assert (not (funcall pred-name "test")))
+ (assert (not (funcall pred-name (make-hash-table))))
+ (let ((compiled-pred
+ (compile nil `(lambda (x) (,pred-name x)))))
+ (format t "~&/doing COMPILED-PRED tests~%")
+ (assert (funcall compiled-pred *instance*))
+ (assert (not (funcall compiled-pred 14)))
+ (assert (not (funcall compiled-pred #()))))
+ ;; Fiddle with TYPEP.
+ (format t "~&/doing TYPEP tests, COLONTYPE=~S~%" ',colontype)
+ (assert (typep *instance* ',defstructname))
+ (assert (not (typep 0 ',defstructname)))
+ (assert (funcall (symbol+ "TYPEP") *instance* ',defstructname))
+ (assert (not (funcall (symbol+ "TYPEP") nil ',defstructname)))
+ (let* ((typename ',defstructname)
+ (compiled-typep
+ (compile nil `(lambda (x) (typep x ',typename)))))
+ (assert (funcall compiled-typep *instance*))
+ (assert (not (funcall compiled-typep nil))))))))
+
+ (format t "~&/done with PROGN for COLONTYPE=~S~%" ',colontype)))
+
+(test-variant vanilla-struct)
+(test-variant vector-struct :colontype vector)
+(test-variant list-struct :colontype list)
+(test-variant vanilla-struct :boa-constructor-p t)
+(test-variant vector-struct :colontype vector :boa-constructor-p t)
+(test-variant list-struct :colontype list :boa-constructor-p t)
+
+\f
+;;;; testing raw slots harder
+;;;;
+;;;; The offsets of raw slots need to be rescaled during the punning
+;;;; process which is used to access them. That seems like a good
+;;;; place for errors to lurk, so we'll try hunting for them by
+;;;; verifying that all the raw slot data gets written successfully
+;;;; into the object, can be copied with the object, and can then be
+;;;; read back out (with none of it ending up bogusly outside the
+;;;; object, so that it couldn't be copied, or bogusly overwriting
+;;;; some other raw slot).
+
+(defstruct manyraw
+ (a (expt 2 30) :type (unsigned-byte 32))
+ (b 0.1 :type single-float)
+ (c 0.2d0 :type double-float)
+ (d #c(0.3 0.3) :type (complex single-float))
+ unraw-slot-just-for-variety
+ (e #c(0.4d0 0.4d0) :type (complex double-float))
+ (aa (expt 2 30) :type (unsigned-byte 32))
+ (bb 0.1 :type single-float)
+ (cc 0.2d0 :type double-float)
+ (dd #c(0.3 0.3) :type (complex single-float))
+ (ee #c(0.4d0 0.4d0) :type (complex double-float)))
+
+(defvar *manyraw* (make-manyraw))
+
+(assert (eql (manyraw-a *manyraw*) (expt 2 30)))
+(assert (eql (manyraw-b *manyraw*) 0.1))
+(assert (eql (manyraw-c *manyraw*) 0.2d0))
+(assert (eql (manyraw-d *manyraw*) #c(0.3 0.3)))
+(assert (eql (manyraw-e *manyraw*) #c(0.4d0 0.4d0)))
+(assert (eql (manyraw-aa *manyraw*) (expt 2 30)))
+(assert (eql (manyraw-bb *manyraw*) 0.1))
+(assert (eql (manyraw-cc *manyraw*) 0.2d0))
+(assert (eql (manyraw-dd *manyraw*) #c(0.3 0.3)))
+(assert (eql (manyraw-ee *manyraw*) #c(0.4d0 0.4d0)))
+
+(setf (manyraw-aa *manyraw*) (expt 2 31)
+ (manyraw-bb *manyraw*) 0.11
+ (manyraw-cc *manyraw*) 0.22d0
+ (manyraw-dd *manyraw*) #c(0.33 0.33)
+ (manyraw-ee *manyraw*) #c(0.44d0 0.44d0))
+
+(let ((copy (copy-manyraw *manyraw*)))
+ (assert (eql (manyraw-a copy) (expt 2 30)))
+ (assert (eql (manyraw-b copy) 0.1))
+ (assert (eql (manyraw-c copy) 0.2d0))
+ (assert (eql (manyraw-d copy) #c(0.3 0.3)))
+ (assert (eql (manyraw-e copy) #c(0.4d0 0.4d0)))
+ (assert (eql (manyraw-aa copy) (expt 2 31)))
+ (assert (eql (manyraw-bb copy) 0.11))
+ (assert (eql (manyraw-cc copy) 0.22d0))
+ (assert (eql (manyraw-dd copy) #c(0.33 0.33)))
+ (assert (eql (manyraw-ee copy) #c(0.44d0 0.44d0))))
+\f
+;;;; miscellaneous old bugs
+
+(defstruct ya-struct)
+(when (ignore-errors (or (ya-struct-p) 12))
+ (error "YA-STRUCT-P of no arguments should signal an error."))
+(when (ignore-errors (or (ya-struct-p 'too 'many 'arguments) 12))
+ (error "YA-STRUCT-P of three arguments should signal an error."))
+\f