X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=tests%2Finterface.impure.lisp;h=da179ede3f0ee3c2e62c2b33dc50f1c09e7f0571;hb=cf49f2d086069a9c1b57f501df9a6a0bd3a34c3c;hp=ea21552ecb74f32016bc11c429e10f0ecd3c26b3;hpb=ed3295bc583cd14104130441e9ff1ad40fa5e484;p=sbcl.git diff --git a/tests/interface.impure.lisp b/tests/interface.impure.lisp index ea21552..da179ed 100644 --- a/tests/interface.impure.lisp +++ b/tests/interface.impure.lisp @@ -12,7 +12,9 @@ ;;;; more information. (load "assertoid.lisp") +(load "test-util.lisp") (use-package "ASSERTOID") +(use-package "TEST-UTIL") (defun (setf foo) (x) "(setf foo) documentation" @@ -28,25 +30,82 @@ (assert (string= (documentation #'(setf foo) 'function) "(setf foo) documentation")) +(with-test (:name :disassemble) ;;; DISASSEMBLE shouldn't fail on closures or unpurified functions -(defun disassemble-fun (x) x) -(disassemble 'disassemble-fun) + (defun disassemble-fun (x) x) + (disassemble 'disassemble-fun) + + (let ((x 1)) (defun disassemble-closure (y) (if y (setq x y) x))) + (disassemble 'disassemble-closure) + + #+sb-eval + (progn + ;; Nor should it fail on interpreted functions + (let ((sb-ext:*evaluator-mode* :interpret)) + (eval `(defun disassemble-eval (x) x)) + (disassemble 'disassemble-eval)) + + ;; disassemble-eval should still be an interpreted function. + ;; clhs disassemble: "(If that function is an interpreted function, + ;; it is first compiled but the result of this implicit compilation + ;; is not installed.)" + (assert (sb-eval:interpreted-function-p #'disassemble-eval))) + + ;; nor should it fail on generic functions or other funcallable instances + (defgeneric disassemble-generic (x)) + (disassemble 'disassemble-generic) + (let ((fin (make-instance 'sb-mop:funcallable-standard-object))) + (disassemble fin))) + +;;; while we're at it, much the same applies to +;;; FUNCTION-LAMBDA-EXPRESSION: +(defun fle-fun (x) x) + +(let ((x 1)) (defun fle-closure (y) (if y (setq x y) x))) + +(with-test (:name :function-lambda-expression) + (flet ((fle-name (x) + (nth-value 2 (function-lambda-expression x)))) + (assert (eql (fle-name #'fle-fun) 'fle-fun)) + (assert (eql (fle-name #'fle-closure) 'fle-closure)) + (assert (eql (fle-name #'disassemble-generic) 'disassemble-generic)) + (function-lambda-expression + (make-instance 'sb-mop:funcallable-standard-object)) + (function-lambda-expression + (make-instance 'generic-function)) + (function-lambda-expression + (make-instance 'standard-generic-function)) + #+sb-eval + (progn + (let ((sb-ext:*evaluator-mode* :interpret)) + (eval `(defun fle-eval (x) x)) + (assert (eql (fle-name #'fle-eval) 'fle-eval))) + + ;; fle-eval should still be an interpreted function. + (assert (sb-eval:interpreted-function-p #'fle-eval))))) -(let ((x 1)) (defun disassemble-closure (y) (if y (setq x y) x))) -(disassemble 'disassemble-closure) ;;; support for DESCRIBE tests (defstruct to-be-described a b) (defclass forward-describe-class (forward-describe-ref) (a)) +(let ((sb-ext:*evaluator-mode* :compile)) + (eval `(let (x) (defun closure-to-describe () (incf x))))) + +(with-test (:name :describe-empty-gf) + (describe (make-instance 'generic-function)) + (describe (make-instance 'standard-generic-function))) ;;; DESCRIBE should run without signalling an error. -(describe (make-to-be-described)) -(describe 12) -(describe "a string") -(describe 'symbolism) -(describe (find-package :cl)) -(describe '(a list)) -(describe #(a vector)) +(with-test (:name (describe :no-error)) + (describe (make-to-be-described)) + (describe 12) + (describe "a string") + (describe 'symbolism) + (describe (find-package :cl)) + (describe '(a list)) + (describe #(a vector)) +;; bug 824974 + (describe 'closure-to-describe)) ;;; The DESCRIBE-OBJECT methods for built-in CL stuff should do ;;; FRESH-LINE and TERPRI neatly. @@ -68,15 +127,206 @@ (let ((s (with-output-to-string (s) (write-char #\x s) (describe i s)))) - (unless (and (char= #\x (char s 0)) - ;; one leading #\NEWLINE from FRESH-LINE or the like, no more - (char= #\newline (char s 1)) - (char/= #\newline (char s 2)) - ;; one trailing #\NEWLINE from TERPRI or the like, no more - (let ((n (length s))) - (and (char= #\newline (char s (- n 1))) - (char/= #\newline (char s (- n 2)))))) - (error "misbehavior in DESCRIBE of ~S" i)))) + (macrolet ((check (form) + `(or ,form + (error "misbehavior in DESCRIBE of ~S:~% ~S" i ',form)))) + (check (char= #\x (char s 0))) + ;; one leading #\NEWLINE from FRESH-LINE or the like, no more + (check (char= #\newline (char s 1))) + (check (char/= #\newline (char s 2))) + ;; one trailing #\NEWLINE from TERPRI or the like, no more + (let ((n (length s))) + (check (char= #\newline (char s (- n 1)))) + (check (char/= #\newline (char s (- n 2)))))))) + + +;;; Tests of documentation on types and classes +(defclass foo () + () + (:documentation "FOO")) +(defstruct bar "BAR") +(define-condition baz () + () + (:documentation "BAZ")) +(deftype quux () + "QUUX" + 't) +(defstruct (frob (:type vector)) "FROB") +(macrolet + ((do-class (name expected &optional structurep) + `(progn + (assert (string= (documentation ',name 'type) ,expected)) + (assert (string= (documentation (find-class ',name) 'type) ,expected)) + (assert (string= (documentation (find-class ',name) 't) ,expected)) + ,@(when structurep + `((assert (string= (documentation ',name 'structure) ,expected)))) + (let ((new1 (symbol-name (gensym "NEW1"))) + (new2 (symbol-name (gensym "NEW2"))) + (new3 (symbol-name (gensym "NEW3"))) + (new4 (symbol-name (gensym "NEW4")))) + (declare (ignorable new4)) + (setf (documentation ',name 'type) new1) + (assert (string= (documentation (find-class ',name) 'type) new1)) + (setf (documentation (find-class ',name) 'type) new2) + (assert (string= (documentation (find-class ',name) 't) new2)) + (setf (documentation (find-class ',name) 't) new3) + (assert (string= (documentation ',name 'type) new3)) + ,@(when structurep + `((assert (string= (documentation ',name 'structure) new3)) + (setf (documentation ',name 'structure) new4) + (assert (string= (documentation ',name 'structure) new4)))))))) + (do-class foo "FOO") + (do-class bar "BAR" t) + (do-class baz "BAZ")) + +(assert (string= (documentation 'quux 'type) "QUUX")) +(setf (documentation 'quux 'type) "NEW4") +(assert (string= (documentation 'quux 'type) "NEW4")) + +(assert (string= (documentation 'frob 'structure) "FROB")) +(setf (documentation 'frob 'structure) "NEW5") +(assert (string= (documentation 'frob 'structure) "NEW5")) + +(define-compiler-macro cmacro (x) + "compiler macro" + x) + +(define-compiler-macro (setf cmacro) (y x) + "setf compiler macro" + y) + +(with-test (:name (documentation compiler-macro)) + (unless (equal "compiler macro" + (documentation 'cmacro 'compiler-macro)) + (error "got ~S for cmacro" + (documentation 'cmacro 'compiler-macro))) + (unless (equal "setf compiler macro" + (documentation '(setf cmacro) 'compiler-macro)) + (error "got ~S for setf macro" (documentation '(setf cmacro) 'compiler-macro)))) + +(with-test (:name (documentation lambda)) + (let ((f (lambda () "aos the zos" t)) + (g (sb-int:named-lambda fii () "zoot the fruit" t))) + (dolist (doc-type '(t function)) + (assert (string= (documentation f doc-type) "aos the zos")) + (assert (string= (documentation g doc-type) "zoot the fruit"))) + (setf (documentation f t) "fire") + (assert (string= (documentation f t) "fire")) + (assert (string= (documentation g t) "zoot the fruit")))) + +(with-test (:name (documentation flet)) + (assert + (string= (documentation + (flet ((quux (x) + "this is FLET quux" + (/ x 2))) + #'quux) + t) + "this is FLET quux"))) + +(with-test (:name (documentation labels)) + (assert + (string= (documentation + (labels ((rec (x) + "this is LABELS rec" + (if (plusp x) + (* x (rec (1- x))) + 1))) + #'rec) + t) + "this is LABELS rec"))) + +(let ((x 1)) + (defun docfoo (y) + "bar" + (incf x y))) + +(with-test (:name (documentation :closure)) + (assert (string= (documentation 'docfoo 'function) "bar")) + (assert (string= (setf (documentation 'docfoo 'function) "baz") "baz")) + (assert (string= (documentation 'docfoo 'function) "baz")) + (assert (string= (documentation #'docfoo t) "baz")) + (assert (string= (setf (documentation #'docfoo t) "zot") "zot")) + (assert (string= (documentation #'docfoo t) "zot")) + (assert (string= (documentation 'docfoo 'function) "zot")) + (assert (not (setf (documentation 'docfoo 'function) nil))) + (assert (not (documentation 'docfoo 'function)))) + +(with-test (:name (documentation :built-in-macro) :skipped-on '(not :sb-doc)) + (assert (documentation 'trace 'function))) + +(with-test (:name (documentation :built-in-function) :skipped-on '(not :sb-doc)) + (assert (documentation 'cons 'function))) + +(with-test (:name :describe-generic-function-with-assumed-type) + ;; Signalled an error at one point + (flet ((zoo () (gogo))) + (defmethod gogo () nil) + (describe 'gogo))) + +(defmacro bug-643958-test () + "foo" + :ding!) + +(with-test (:name :bug-643958) + (assert (equal "foo" (documentation 'bug-643958-test 'function))) + (setf (documentation 'bug-643958-test 'function) "bar") + (assert (equal "bar" (documentation 'bug-643958-test 'function)))) + +(defclass cannot-print-this () + ()) +(defmethod print-object ((oops cannot-print-this) stream) + (error "No go!")) +(with-test (:name :describe-suppresses-print-errors) + (handler-bind ((error #'continue)) + (with-output-to-string (s) + (describe (make-instance 'cannot-print-this) s)))) +(with-test (:name :backtrace-suppresses-print-errors) + (handler-bind ((error #'continue)) + (with-output-to-string (s) + (labels ((foo (n x) + (when (plusp n) + (foo (1- n) x)) + (when (zerop n) + (sb-debug:backtrace 100 s)))) + (foo 100 (make-instance 'cannot-print-this)))))) +(with-test (:name :backtrace-and-circles) + (handler-bind ((error #'continue)) + (with-output-to-string (s) + (labels ((foo (n x) + (when (plusp n) + (foo (1- n) x)) + (when (zerop n) + (sb-debug:backtrace 100 s)))) + (foo 100 (let ((list (list t))) + (nconc list list))))))) + +(with-test (:name :endianness-in-features) + (assert + (or (member :big-endian *features*) + (member :little-endian *features*)))) + +(with-test (:name :function-documentation-mismatch) + (defun test () + "X" + nil) + (setf (symbol-function 'test2) #'test) + (setf (documentation 'test 'function) "Y") + (assert (equal (documentation #'test t) + (documentation 'test 'function))) + (setf (documentation 'test2 'function) "Z") + (assert (not + (equal (documentation 'test 'function) + (documentation 'test2 'function))))) + +(with-test (:name :setf-documentation-on-nil) + (assert + (handler-case + (assert (equal (setf (documentation nil 'function) "foo") "foo")) + (style-warning () t) + (:no-error (x) + (declare (ignore x)) + nil)))) ;;;; success