1.0.21.29: handle alien record type redefinitions (bug 431)
[sbcl.git] / tests / alien.impure.lisp
index 6c6b002..5029774 100644 (file)
                        (sb-alien:deref (sb-alien:slot a1 'u) 8)
                        (sb-alien:deref (sb-alien:slot a1 'u) 9)))))
 
+(handler-bind ((compiler-note (lambda (c)
+                                (error "bad note! ~A" c))))
+  (funcall (compile nil '(lambda () (sb-alien:make-alien sb-alien:int)))))
+
+;;; Test case for unwinding an alien (Win32) exception frame
+;;;
+;;; The basic theory here is that failing to honor a win32
+;;; exception frame during stack unwinding breaks the chain.
+;;; "And if / You don't love me now / You will never love me
+;;; again / I can still hear you saying / You would never break
+;;; the chain."  If the chain is broken and another exception
+;;; occurs (such as an error trap caused by an OBJECT-NOT-TYPE
+;;; error), the system will kill our process.  No mercy, no
+;;; appeal. So, to check that we have done our job properly, we
+;;; need some way to put an exception frame on the stack and then
+;;; unwind through it, then trigger another exception.  (FUNCALL
+;;; 0) will suffice for the latter, and a simple test shows that
+;;; CallWindowProc() establishes a frame and calls a function
+;;; passed to it as an argument.
+#+win32
+(progn
+  (load-shared-object "USER32")
+  (assert
+   (eq :ok
+       (handler-case
+           (tagbody
+              (alien-funcall
+               (extern-alien "CallWindowProcW"
+                             (function unsigned-int
+                                       (* (function int)) unsigned-int
+                                       unsigned-int unsigned-int unsigned-int))
+               (alien-sap
+                (sb-alien::alien-callback (function unsigned-int)
+                                          #'(lambda () (go up))))
+               0 0 0 0)
+            up
+              (funcall 0))
+         (error ()
+           :ok)))))
+
+;;; Unused local alien caused a compiler error
+(with-test (:name unused-local-alien)
+  (let ((fun `(lambda ()
+                (sb-alien:with-alien ((alien1923 (array (sb-alien:unsigned 8) 72)))
+                  (values)))))
+    (assert (not (funcall (compile nil fun))))))
+
+;;; Non-local exit from WITH-ALIEN caused alien stack to be leaked.
+(defvar *sap-int*)
+(defun try-to-leak-alien-stack (x)
+  (with-alien ((alien (array (sb-alien:unsigned 8) 72)))
+    (let ((sap-int (sb-sys:sap-int (alien-sap alien))))
+      (if *sap-int*
+          (assert (= *sap-int* sap-int))
+          (setf *sap-int* sap-int)))
+    (when x
+      (return-from try-to-leak-alien-stack 'going))
+    (never)))
+(with-test (:name :nlx-causes-alien-stack-leak)
+  (let ((*sap-int* nil))
+    (loop repeat 1024
+          do (try-to-leak-alien-stack t))))
+
+;;; bug 431
+(with-test (:name :alien-struct-redefinition)
+  (eval '(progn
+          (define-alien-type nil (struct mystruct (myshort short) (mychar char)))
+          (with-alien ((myst (struct mystruct)))
+            (with-alien ((mysh short (slot myst 'myshort)))
+              (assert (integerp mysh))))))
+  (let ((restarted 0))
+    (handler-bind ((error (lambda (e)
+                            (let ((cont (find-restart 'continue e)))
+                              (when cont
+                                (incf restarted)
+                                (invoke-restart cont))))))
+      (eval '(define-alien-type nil (struct mystruct (myint int) (mychar char)))))
+    (assert (= 1 restarted)))
+  (eval '(with-alien ((myst (struct mystruct)))
+          (with-alien ((myin int (slot myst 'myint)))
+            (assert (integerp myin))))))
+
 ;;; success