changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/std/tests.lisp

changeset 355: 09f056e9a789
parent: 00d1c8afcdbb
child: 49c3f3d11432
author: Richard Westhaver <ellis@rwest.io>
date: Tue, 14 May 2024 18:33:03 -0400
permissions: -rw-r--r--
description: bugfixes, x test
1 ;;; tests.lisp --- std system tests
2 
3 ;;; Commentary:
4 
5 ;; TODO: fix false positives when using (eval-test)
6 
7 ;;; Code:
8 (in-package :std-user)
9 (defpkg :std/tests
10  (:use :cl :std :rt :sb-thread :std/fu))
11 (in-package :std/tests)
12 (defsuite :std)
13 (in-suite :std)
14 (in-readtable :std)
15 ;; prevent threadlocks
16 ;; (setf sb-unix::*on-dangerous-wait* :error)
17 
18 ;; TODO 2024-05-14: fix compilation order of std/fu vs std/readtables
19 (deftest readtables (:disabled nil)
20  "Test :std readtable"
21  (is (typep #`(,a1 ,a1 ',a1 ,@a1) 'function))
22  (is (string= #"test "foo" "# "test \"foo\" "))
23  ;; from curry-compose-reader-macros test suite
24  (is (equal (funcall {list 1} 2) '(1 2))) ;; curry.1
25  (is (equal (mapcar {+ 1} '(1 2 3 4)) '(2 3 4 5))) ;; curry.2
26  (is (equal (funcall {1 list 1} 2) '(1 2))) ;; curry.fixed-arity
27  (is (equal (funcall {2 list _ 2} 3 4) '(3 4 2))) ;; curry.fixed-arity.2
28  (signals error
29  (locally (declare (optimize safety))
30  (let ((f {1 list 1}))
31  (progn (funcall f) nil)))) ;; curry.fixed-arity.1
32  (signals error
33  (locally (declare (optimize safety))
34  (let ((f {1 list 1}))
35  (progn (funcall f 'a 'b) nil)))) ;; curry.fixed-arity-error.2
36  (is (equal (funcall {list _ 1} 2) '(2 1))) ;; rcurry.1
37  (is (equal (mapcar {- _ 1} '(1 2 3 4)) '(0 1 2 3))) ;; rcurry.2
38  (is (equal (funcall [{* 3} #'1+] 1) 6)) ;; compose.1
39  (is (equal (funcall ['1+ '1+] 1) 3)) ;; compose.2
40  (is (equal (funcall [#'1+] 1) 2)) ;; compose.3
41  (is (equal (funcall [#'values] 1 2 3) (values 1 2 3))) ;; compose.4
42  (is (equal (funcall «list {* 2} {* 3}» 4) '(8 12))) ;; join.1
43  (is (equal (mapcar «and {< 2} 'evenp (constantly t)» '(1 2 3 4)) (list nil nil nil t))) ;; join.2
44  ;; typecase-bracket
45  (is (equal (mapcar typecase (number #'1+) (string :str) '(1 "this" 2 "that")) '(2 :str 3 :str)))
46  ;; cond-bracket
47  (is (equal (mapcar cond (#'evenp {+ 100}) (#'oddp {+ 200}) '(1 2 3 4)) '(201 102 203 104)))
48  ;; if-bracket
49  (is (equal (mapcar if #'evenp {list :a} {list :b} '(1 2 3 4))
50  '((:b 1) (:a 2) (:b 3) (:a 4))))
51  ;; when-bracket
52  (is (equal (mapcar when 'evenp {+ 4} '(1 2 3 4)) (list nil 6 nil 8)))
53  ;; unless-bracket
54  (is (equal (mapcar unless 'evenp {+ 4} '(1 2 3 4)) (list 5 nil 7 nil))))
55 
56 (deftest sym ()
57  "Test standard symbol utils"
58  ;; gensyms
59  (is (not (equalp (make-gensym 'a) (make-gensym 'a))))
60  (is (eq 'std/tests::foo (format-symbol :std/tests "~A" 'foo)))
61  (is (eq (make-keyword 'fizz) :fizz)))
62 
63 ;;;; TODO
64 (deftest string ()
65  "Test standard string utils"
66  (is (typep "test" 'string-designator))
67  (is (typep 'test 'string-designator))
68  (is (typep #\C 'string-designator))
69  (is (not (typep 0 'string-designator))))
70 
71 (deftest list ()
72  "Test standard list utils"
73  ;; same object - a literal
74  (is (eq (ensure-car '(0)) (ensure-car 0)))
75  (is (eq (ensure-car '(nil)) (ensure-car nil)))
76  ;; different objects
77  (is (not (eq (ensure-cons 0) (ensure-cons 0))))
78  (is (equal (ensure-cons 0) (ensure-cons 0))))
79 
80 (deftest err ()
81  "Test standard error handlers"
82  (is (eql 'testing-err (deferror testing-err (std-error) nil (:auto t) (:documentation "testing")))))
83 
84 (deftest threads ()
85  "Test standard thread functionality."
86  (is (eq *current-thread*
87  (find (thread-name *current-thread*) (list-all-threads)
88  :key #'thread-name :test #'equal)))
89  (is (find-thread-by-id (car (thread-id-list))))
90  (is (not (zerop (thread-count))))
91  (let ((threads
92  (make-threads 4 (lambda () (is (= 42 (1+ 41)))) :name "threads")))
93  (loop for th in threads
94  do (sb-thread:join-thread th))
95  (loop for th in threads
96  collect (is (not (sb-thread:thread-alive-p th)))))
97  (let ((m (make-mutex :name "mutex-test")))
98  (is
99  (and (not
100  (with-mutex (m)
101  (join-thread
102  (make-thread (lambda ()
103  (with-mutex (m :timeout 0.1)
104  t))))))
105  (join-thread
106  (make-thread (lambda ()
107  (with-mutex (m :timeout 0.1)
108  t)))))))
109  (let* ((sym (gensym))
110  (s (make-semaphore :name "semaphore-test"))
111  (th (make-thread (lambda () (wait-on-semaphore s)))))
112  (is (equal (multiple-value-list (join-thread th :timeout .001 :default sym))
113  (list sym :timeout)))
114  (signal-semaphore s)
115  (is (join-thread th)))
116  (signals join-thread-error (join-thread *current-thread*))
117  (is
118  (let ((m (make-mutex :name "rlock-test")))
119  (is (not (with-mutex (m) (join-thread (make-thread (lambda () (with-recursive-lock (m :wait-p nil) t)))))))
120  (join-thread (make-thread (lambda () (with-recursive-lock (m :wait-p nil) t))))))
121  (let ((queue (make-waitqueue :name "queue-test"))
122  (lock (make-mutex :name "lock-test"))
123  (n 0)
124  th)
125  (labels ((in-new-thread ()
126  (with-mutex (lock)
127  (assert (eql (mutex-owner lock) *current-thread*))
128  (log:info! (condition-wait queue lock))
129  (assert (eql (mutex-owner lock) *current-thread*))
130  (is (= n 1))
131  (decf n))))
132  (setf th (make-thread #'in-new-thread))
133  (sleep 1)
134  (is (null (mutex-owner lock)))
135  (with-mutex (lock)
136  (incf n)
137  (condition-notify queue))
138  (is (= 0 (join-thread th))))))
139 
140 (deftest timers ()
141  "Test various timer functionality."
142  (sb-int:with-progressive-timeout (ttl :seconds 2)
143  (sleep 0.1)
144  (is (/= (ttl) 2.0))))
145 
146 (deftest tasks ()
147  "Test task-pools, oracles, and workers."
148  (let ((pool1 (make-task-pool)))))
149 
150 (deftest fmt ()
151  "Test standard formatters"
152  (is (string= (format nil "| 1 | 2 | 3 |~%") (fmt-row '(1 2 3))))
153  (is (string=
154  ;; note the read-time-eval..
155  #.(fmt-tree nil '(foobar (:a) (:b) (c) (d)) :layout :down)
156  #"FOOBAR
157  ├─ :A
158  ├─ :B
159  ├─ C
160  ╰─ D
161 "#))
162  ;; with plist option
163  (is (string=
164  #.(std:fmt-tree nil '(sk-project :name "foobar" :path "/a/b/c.asd" :vc :hg) :layout :down :plist t)
165  #"SK-PROJECT
166  ├─ :NAME
167  │ ╰─ "foobar"
168  ├─ :PATH
169  │ ╰─ "/a/b/c.asd"
170  ╰─ :VC
171  ╰─ :HG
172 "#)))
173 
174 (deftest ana ()
175  "Test standard anaphoric macros"
176  (is (= 8
177  (aif (+ 2 2)
178  (+ it it))))
179  (is (= 42 (awhen 42 it)))
180  (is (= 3 (acond ((1+ 1) (1+ it)))))
181  (loop for x in '(1 2 3)
182  for y in (funcall (alet ((a 1) (b 2) (c 3))
183  (lambda () (mapc #'1+ (list a b c)))))
184  collect (is (= x y))))
185 
186 (deftest pan (:disabled t)
187  "Test standard pandoric macros"
188  (let ((p
189  (plambda (a) (b c)
190  (if (not a)
191  (setq b 0
192  c 0)
193  (progn (incf b a) (incf c a))))))
194  (with-pandoric (b c) p
195  (is (= 0 (funcall p nil)))
196  (is (= 1 (funcall p 1)))
197  (is (= 1 b c)))))
198 
199 (deftest alien ()
200  "Test standard alien utils"
201  (is (= 0 (foreign-int-to-integer 0 4)))
202  (is (= 1 (bool-to-foreign-int t))))
203 
204 (deftest curry ()
205  "Test curry functions from Alexandria, found in std/fu.
206 These tests are copied directly from the Alexandria test suite."
207  ;; curry.1
208  (let ((curried (curry '+ 3)))
209  (is (= (funcall curried 1 5) 9)))
210  ;; curry.2
211  (let ((curried (locally (declare (notinline curry))
212  (curry '* 2 3))))
213  (is (= (funcall curried 7) 42)))
214  ;; curry.3
215  (let ((curried-form (funcall (compiler-macro-function 'curry)
216  '(curry '/ 8)
217  nil)))
218  (let ((fun (funcall (compile nil `(lambda () ,curried-form)))))
219  (is (= (funcall fun 2) 4)))) ;; maybe fails?
220  ;; curry.4
221  (let* ((x 1)
222  (curried (curry (progn
223  (incf x)
224  (lambda (y z) (* x y z)))
225  3)))
226  (is (equal (list (funcall curried 7)
227  (funcall curried 7)
228  x)
229  '(42 42 2))))
230  ;; rcurry.1
231  (let ((r (rcurry '/ 2)))
232  (is (= (funcall r 8) 4)))
233  ;; rcurry.2
234  (let* ((x 1)
235  (curried (rcurry (progn
236  (incf x)
237  (lambda (y z) (* x y z)))
238  3)))
239  (is (equalp
240  (list (funcall curried 7) ;; 42
241  (funcall curried 7) ;; 42
242  x) ;; 2
243  '(42 42 2)))))
244 
245 (deftest bits (:disabled t)
246  (define-bitfield testbits
247  (a boolean)
248  (b (signed-byte 2))
249  (c (unsigned-byte 3) :initform 1)
250  (d (integer -100 100))
251  (e (member foo bar baz)))
252  (let ((bits (make-testbits)))
253  (is (not (testbits-a bits)))
254  (is (= 0 (testbits-b bits)))
255  (is (= 1 (testbits-c bits)))
256  (is (= -100 (testbits-d bits)))
257  (is (eql 'foo (testbits-e bits)))))