Mercurial > core / lisp/lib/rt/util.lisp
changeset 632: |
bbd9024f2fe2 |
parent: |
2a4f11c0e8c8
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Sat, 31 Aug 2024 22:34:56 -0400 |
permissions: |
-rw-r--r-- |
description: |
lib/rt upgrades and refactoring |
1 ;;; rt/util.lisp --- Test Utilities 7 ;; some of these are taken from the TEST-UTIL package of SBCL 8 ;; (tests/test-util.lisp) 14 (defmacro with-tmp-directory ((&optional (name (string (gensym "tmp"))) 15 (defaults *default-tmp-directory*)) 17 `(let ((*tmp* (directory-path (merge-pathnames ,name ,defaults)))) 18 (ensure-directories-exist *tmp*) 19 (unwind-protect (progn ,@body) 20 (sb-ext:delete-directory *tmp* :recursive t)))) 22 (defmacro with-tmp-file ((stream-var &key (name (string (gensym "tmp"))) 24 (directory *default-tmp-directory*) 26 (if-exists :supersede) 27 (element-type ''character)) 29 `(let ((*tmp* (make-pathname :name ,name :type ,type :directory ,(namestring directory)))) 30 (with-open-file (,stream-var *tmp* :direction ,direction :element-type ,element-type 31 :if-exists ,if-exists) 32 (unwind-protect (progn ,@body) 33 (delete-file *tmp*))))) 36 (defvar *simple-charset* "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") 38 (defun random-elt (seq) 39 (elt seq (random (length seq)))) 41 (defun random-ref (vec) 42 (aref vec (random (length vec)))) 45 (random-ref *simple-charset*)) 47 (defun random-chars (dim) 48 (let ((r (make-array dim :element-type 'character))) 49 (dotimes (i (array-total-size r) r) 50 (setf (row-major-aref r i) (random-char))))) 52 (defun random-byte () (random 255)) 54 (defun random-bytes (dim) 55 (let ((r (make-array dim :element-type 'octet))) 56 (dotimes (i (array-total-size r) r) 57 (setf (row-major-aref r i) (random-byte))))) 59 (eval-when (:compile-toplevel :load-toplevel :execute) 60 (defun make-test (&rest slots) 61 (apply #'make-instance 'test slots)) 62 (defun make-suite (&rest slots) 63 (apply #'make-instance 'test-suite slots))) 65 ;; TODO 2023-09-04: optimize 66 ;;(declaim (inline do-tests)) 67 (defun do-tests (&optional (suite *test-suite*) force (output *standard-output*)) 68 (if (pathnamep output) 69 (with-open-file (stream output :direction :output) 70 (do-suite (ensure-suite suite) :stream stream :force force)) 71 (do-suite (ensure-suite suite) :stream output :force force))) 73 (defvar *test-output-mutex* (sb-thread:make-mutex :name "tests-output")) 76 (defun do-tests-concurrently (&optional (suite *test-suite*) force (output *standard-output*)) 77 (declare (ignore suite force)) 78 (sb-thread:with-mutex (*test-output-mutex*) 79 (let ((stream (make-synonym-stream output))) 80 (let ((*standard-output* stream) 81 (*error-output* stream)) 90 ;; this assumes that *test-suite* is re-initialized correctly to the 91 ;; correct test-suite object. 92 (defun continue-testing () 93 (if-let ((test *testing*)) 94 (throw '%in-test test) 95 (do-suite *test-suite*))) 97 ;; NOTE 2023-09-01: `pushnew' does not return an indication of whether 98 ;; place is changed - it returns place. This is functionally sound but 99 ;; means that if we want to do something else in the event that place 100 ;; is unchanged, we run into some friction, 101 ;; https://stackoverflow.com/questions/56228832/adapting-common-lisp-pushnew-to-return-success-failure 102 (defun spush (item lst &key (test #'equal)) 103 "Substituting `push'" 104 (declare (type function test)) 106 ((null lst) (push item lst)) 108 (if-let ((found (member item lst 114 #|(or nil '(t (cons item lst)))|#)) 116 ;; FIX 2023-08-31: spush, replace with `add-test' method. 117 ;; (declaim (inline normalize-test-name)) 118 (defun normalize-test-name (a) 119 "Return the normalized `test-suite-designator' of A." 121 (string (string-upcase a)) 122 (symbol (symbol-name a)) 123 (test-object (normalize-test-name (test-name a))) 124 (t (format nil "~A" a)))) 126 (defun test-name= (a b) 127 "Return t if A and B are similar `test-suite-designator's." 128 (let ((a (normalize-test-name a)) 129 (b (normalize-test-name b))) 132 ;; (declaim (inline assert-suite ensure-suite)) 133 (defun ensure-suite (name) 134 (if-let ((ok (member name *test-suite-list* :test #'test-name=))) 136 (when (or (eq name t) (null name)) (make-suite :name *default-test-suite-name*)))) 138 (defun check-suite-designator (suite) (check-type suite test-suite-designator)) 140 (defun assert-suite (name) 141 (check-suite-designator name) 142 (assert (ensure-suite name))) 144 (declaim (inline test-opt-key-p test-opt-valid-p)) 145 (defun test-opt-key-p (k) 146 "Test if K is a `test-opt-key'." 147 (member k '(:profile :save :stream))) 149 (defun test-opt-valid-p (f) 150 "Test if F is a valid `test-opt' form. If so, return F else nil." 151 (when (test-opt-key-p (car f))