X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=tests%2Ftest-util.lisp;h=20b2c548a0ae9ead12e204a6b3b46d17bb69835a;hb=2e52fa0553c5a256f482ee14e30608acf55e5f48;hp=8381019c7be36d165902be558dfdd26ff3ab93ac;hpb=9ef5527c3db71fcb3a98b5a37a1006789834ac0a;p=sbcl.git diff --git a/tests/test-util.lisp b/tests/test-util.lisp index 8381019..20b2c54 100644 --- a/tests/test-util.lisp +++ b/tests/test-util.lisp @@ -2,7 +2,8 @@ (:use :cl :sb-ext) (:export #:with-test #:report-test-status #:*failures* #:really-invoke-debugger - #:*break-on-failure* #:*break-on-expected-failure*)) + #:*break-on-failure* #:*break-on-expected-failure* + #:make-kill-thread #:make-join-thread)) (in-package :test-util) @@ -12,14 +13,33 @@ (defvar *break-on-failure* nil) (defvar *break-on-expected-failure* nil) +(defvar *threads-to-kill*) +(defvar *threads-to-join*) + +#+sb-thread +(defun make-kill-thread (&rest args) + (let ((thread (apply #'sb-thread:make-thread args))) + (when (boundp '*threads-to-kill*) + (push thread *threads-to-kill*)) + thread)) + +#+sb-thread +(defun make-join-thread (&rest args) + (let ((thread (apply #'sb-thread:make-thread args))) + (when (boundp '*threads-to-join*) + (push thread *threads-to-join*)) + thread)) + (defun log-msg (&rest args) (format *trace-output* "~&::: ") (apply #'format *trace-output* args) (terpri *trace-output*) (force-output *trace-output*)) -(defmacro with-test ((&key fails-on broken-on skipped-on name) &body body) - (let ((block-name (gensym))) +(defmacro with-test ((&key fails-on broken-on skipped-on name) + &body body) + (let ((block-name (gensym)) + (threads (gensym "THREADS"))) `(progn (start-test) (cond @@ -28,18 +48,44 @@ ((skipped-p ,skipped-on) (fail-test :skipped-disabled ',name "Test disabled for this combination of platform and features")) (t - (block ,block-name - (handler-bind ((error (lambda (error) - (if (expected-failure-p ,fails-on) - (fail-test :expected-failure ',name error) - (fail-test :unexpected-failure ',name error)) - (return-from ,block-name)))) - (progn - (log-msg "Running ~S" ',name) - ,@body - (if (expected-failure-p ,fails-on) - (fail-test :unexpected-success ',name nil) - (log-msg "Success ~S" ',name)))))))))) + (let (#+sb-thread (,threads (sb-thread:list-all-threads)) + (*threads-to-join* nil) + (*threads-to-kill* nil)) + (block ,block-name + (handler-bind ((error (lambda (error) + (if (expected-failure-p ,fails-on) + (fail-test :expected-failure ',name error) + (fail-test :unexpected-failure ',name error)) + (return-from ,block-name)))) + (progn + (log-msg "Running ~S" ',name) + ,@body + #+sb-thread + (let ((any-leftover nil)) + (dolist (thread *threads-to-join*) + (ignore-errors (sb-thread:join-thread thread))) + (dolist (thread *threads-to-kill*) + (ignore-errors (sb-thread:terminate-thread thread))) + (setf ,threads (union (union *threads-to-kill* + *threads-to-join*) + ,threads)) + #+(and sb-safepoint-strictly (not win32)) + (dolist (thread (sb-thread:list-all-threads)) + (when (typep thread 'sb-thread:signal-handling-thread) + (ignore-errors (sb-thread:join-thread thread)))) + (dolist (thread (sb-thread:list-all-threads)) + (unless (or (not (sb-thread:thread-alive-p thread)) + (eql thread sb-thread:*current-thread*) + (member thread ,threads) + (sb-thread:thread-emphemeral-p thread)) + (setf any-leftover thread) + (ignore-errors (sb-thread:terminate-thread thread)))) + (when any-leftover + (fail-test :leftover-thread ',name any-leftover) + (return-from ,block-name))) + (if (expected-failure-p ,fails-on) + (fail-test :unexpected-success ',name nil) + (log-msg "Success ~S" ',name))))))))))) (defun report-test-status () (with-standard-io-syntax