changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / lisp/std/tests.lisp

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