;;;; Standard-instance-access tests and update-protocol abuse ;;;; This software is part of the SBCL system. See the README file for ;;;; more information. ;;;; ;;;; While most of SBCL is derived from the CMU CL system, the test ;;;; files (like this one) were written from scratch after the fork ;;;; from CMU CL. ;;;; ;;;; This software is in the public domain and is provided with ;;;; absolutely no warranty. See the COPYING and CREDITS files for ;;;; more information. (in-package :cl-user) (load "test-util.lisp") (defpackage :mop-test-30 (:use :sb-pcl :sb-ext :cl :test-util)) (in-package :mop-test-30) (defclass foo () ((bar :initarg :bar) (quux :initarg :quux))) (defclass foomagic () ()) (defun find-slot (name class) (let ((class (find-class class))) (unless (class-finalized-p class) (finalize-inheritance class)) (find name (class-slots class) :key #'slot-definition-name))) (add-dependent (find-class 'foo) (find-class 'foomagic)) (defglobal **bar-loc** (slot-definition-location (find-slot 'bar 'foo))) (defglobal **quux-loc** (slot-definition-location (find-slot 'quux 'foo))) (defmethod update-dependent ((meta (eql (find-class 'foo))) (dep (eql (find-class 'foomagic))) &key) (setf **bar-loc** (slot-definition-location (find-slot 'bar 'foo)) **quux-loc** (slot-definition-location (find-slot 'quux 'foo)))) (defun foo-bar/quux (foo) (declare (type foo foo)) (values (standard-instance-access foo **bar-loc**) (standard-instance-access foo **quux-loc**))) (defun swap-bar/quux (foo) (declare (type foo foo)) (rotatef (standard-instance-access foo **bar-loc**) (standard-instance-access foo **quux-loc**))) (with-test (:name :standard-instance-access) (let ((bar (cons t t)) (quux (cons nil nil))) (multiple-value-bind (bar? quux?) (foo-bar/quux (make-instance 'foo :bar bar :quux quux)) (assert (eq bar bar?)) (assert (eq quux quux?))))) (with-test (:name :standard-instance-access/setf) (let* ((bar (cons t t)) (quux (cons nil nil)) (foo (make-instance 'foo :bar bar :quux quux))) (multiple-value-bind (bar? quux?) (foo-bar/quux foo) (assert (eq bar bar?)) (assert (eq quux quux?))) (swap-bar/quux foo) (multiple-value-bind (bar? quux?) (foo-bar/quux foo) (assert (eq quux bar?)) (assert (eq bar quux?))))) ;;; Sneaky redefinition reorders slots! (defclass foo () ((quux :initarg :quux) (bar :initarg :bar))) (with-test (:name :standard-instance-access/updated) (let ((bar (cons t t)) (quux (cons nil nil))) (multiple-value-bind (bar? quux?) (foo-bar/quux (make-instance 'foo :bar bar :quux quux)) (assert (eq bar bar?)) (assert (eq quux quux?))))) (with-test (:name :standard-instance-access/slot-unbound) (let ((bar (cons t t))) (multiple-value-bind (bar? quux?) (foo-bar/quux (make-instance 'foo :bar bar)) (assert (eq bar bar?)) (assert (eq +slot-unbound+ quux?)))))