1 (in-package :trees-tests)
3 (defconstant +max-upper-bound+ (expt 2 15))
5 (defvar *execution-trace*)
7 (defvar *print-while-building* nil)
8 (defvar *validate-while-building* nil)
9 (defvar *building-uses-delete* nil)
10 (defvar *let-pred-determine-equivalency* nil)
12 (defun make-integer-tree (tree-kind)
13 ;; Use explicit lambdes to make SBCL emit calls to GENERIC assembly
14 ;; procedures, rather than the full functions; the GENERIC versions
15 ;; will be faster, as they contain early outs for fixnums.
16 (trees:make-binary-tree tree-kind #'(lambda (x y)
19 :test (unless *let-pred-determine-equivalency*
20 #'(lambda (x y) (= x y)))))
22 (defun make-bitset (upper-bound)
23 (make-array upper-bound :element-type 'bit :initial-element 0))
25 (defun make-trace-buffer (&optional (size 400))
26 (make-array size :element-type '(unsigned-byte 16)
30 (defun add-trace-action (insertp element)
31 (vector-push-extend (dpb insertp (byte 1 15) element) *execution-trace*))
33 (defun insert-action-p (bits)
34 (not (logbitp 15 bits)))
36 (defun action-element (bits)
37 (ldb (byte 15 0) bits))
39 (defun test-with-randomly-built-tree (kind test &optional (size 200))
40 (multiple-value-bind (tree bitvector count)
41 (build-random-tree kind size :delete t)
42 (declare (ignore count))
43 (funcall test tree bitvector)))
45 (defun check-equivalency (tree bitvector)
46 (declare (type simple-bit-vector bitvector))
48 for start = 0 then (1+ x)
49 for x = (position 1 bitvector :start start)
51 do (assert (trees:find x tree))
54 (defun check-selection (tree bitvector)
55 (declare (type simple-bit-vector bitvector))
56 (unless (zerop (trees:size tree))
57 (loop for start = 0 then (1+ x)
58 for x = (position 1 bitvector :start start)
61 do (assert (= x (trees:select tree i)))
64 (defun check-forward-position-t (tree bitvector)
65 (declare (type simple-bit-vector bitvector))
66 (loop for start = 0 then (1+ x)
67 for x = (position 1 bitvector :start start)
70 do (assert (= i (trees:position x tree)))
73 (defun check-forward-position-nil (tree bitvector)
74 (declare (type simple-bit-vector bitvector))
75 (loop for start = 0 then (1+ x)
76 for x = (position 0 bitvector :start start)
78 do (assert (eq (trees:position x tree) nil))
81 (defun check-backward-position-t (tree bitvector)
82 (declare (type simple-bit-vector bitvector))
83 (loop for end = nil then x
84 for x = (position 1 bitvector :from-end t :end end)
85 for i downfrom (1- (trees:size tree))
87 do (assert (= i (trees:position x tree)))
90 (defun check-backward-position-nil (tree bitvector)
91 (declare (type simple-bit-vector bitvector))
92 (loop for end = nil then x
93 for x = (position 0 bitvector :from-end t :end end)
95 do (assert (eq (trees:position x tree :from-end t) nil))
98 (defun check-forward-iteration (tree bitvector)
99 (declare (type simple-bit-vector bitvector))
100 (loop with iter = (trees::make-iterator tree :forwardp t)
101 for start = 0 then (1+ x)
102 for x = (position 1 bitvector :start start)
103 for z = (funcall iter)
105 do (assert (= (trees::datum z) x))
108 (defun check-backward-iteration (tree bitvector)
109 (declare (type simple-bit-vector bitvector))
110 (loop with iter = (trees::make-iterator tree :forwardp nil)
112 for y = (position 1 bitvector :from-end t :end end)
113 for w = (funcall iter)
115 do (assert (= y (trees::datum w)))
118 (defun check-dotree (tree bitvector)
119 (declare (type simple-bit-vector bitvector))
120 (let ((new (bit-xor bitvector bitvector)))
121 (trees:dotree (x tree)
122 (setf (aref new x) 1))
123 (assert (not (mismatch new bitvector)))
126 (defun check-reduce (tree bitvector)
127 (declare (type simple-bit-vector bitvector))
128 (loop with tree-sum = (trees:reduce tree #'+)
129 for start = 0 then (1+ x)
130 for x = (position 1 bitvector :start start)
134 (assert (= tree-sum sum))
137 (defun check-reduce-from-end (tree bitvector)
138 (declare (type simple-bit-vector bitvector))
139 (loop with tree-diff = (trees:reduce tree #'- :initial-value 0 :from-end t)
140 for start = 0 then (1+ x)
141 for x = (position 1 bitvector :start start)
145 (assert (= tree-diff (reduce #'- list :initial-value 0 :from-end t)))
148 (defparameter *tree-checkers*
149 (list #'check-equivalency
151 #'check-forward-position-t
152 #'check-forward-position-nil
153 #'check-backward-position-t
154 #'check-backward-position-nil
155 #'check-forward-iteration
156 #'check-backward-iteration
159 #'check-reduce-from-end))
161 (defun build-random-tree (tree-type upper-bound
162 &key (delete *building-uses-delete*)
164 (when (> upper-bound +max-upper-bound+)
165 (error "upper bound ~A is too large" upper-bound))
166 (let ((*execution-trace* (when trace (make-trace-buffer))))
167 (loop with tree = (make-integer-tree tree-type)
168 with bitvector of-type simple-bit-vector = (make-bitset upper-bound)
170 with insert-count = 0
171 with delete-count = 0
172 with insert-limit = (truncate upper-bound 2)
173 with delete-limit = (if delete (truncate upper-bound 2) 0)
174 with validatep = *validate-while-building*
175 until (and (>= insert-count insert-limit)
176 (>= delete-count delete-limit))
177 do (let ((element (random upper-bound))
178 (which (if delete (random 2) 0)))
181 (multiple-value-bind (key insertedp) (trees:insert element tree)
184 (when trace (add-trace-action which element))
185 (assert (= 0 (aref bitvector element)))
186 (setf (aref bitvector element) 1)
190 (assert (= 1 (aref bitvector element)))))
191 (assert (= key element))
192 (assert (trees:find element tree))))
194 (multiple-value-bind (data successp) (trees:delete element tree)
197 (when trace (add-trace-action which element))
198 (assert (= element data))
199 (assert (= (aref bitvector element) 1))
200 (setf (aref bitvector element) 0)
204 (assert (= (aref bitvector element) 0))))
205 (assert (not (trees:find element tree))))))
207 (assert (validate-tree tree)))
208 (assert (= size (trees:size tree))))
209 finally (check-equivalency tree bitvector)
211 (return (values tree bitvector (+ insert-count delete-count))))))
213 (defun build-tree-from-trace (tree-type trace maker insert delete printer)
214 (loop with tree = (funcall maker tree-type)
215 for action across trace
217 do (funcall (if (insert-action-p action) insert delete)
218 (action-element action) tree)
219 (when *print-while-building*
220 (format *trace-output* "step ~D: ~A ~D~%" i
221 (if (insert-action-p action) "insert" "delete")
222 (action-element action))
223 (funcall printer tree *trace-output*))
224 finally (return tree)))
226 (defun build-new-tree-from-trace (tree-type trace)
227 (build-tree-from-trace tree-type trace
231 #'trees::pprint-tree))
233 (defun build-and-compare (tree-type deletionp)
234 (handler-bind ((error #'(lambda (c)
235 (assert *execution-trace*)
236 (setf *saved-trace* *execution-trace*)
237 (let ((*print-while-building* t))
238 (build-new-tree-from-trace tree-type *execution-trace*))
240 (build-random-tree tree-type 200 :delete deletionp :trace t)))
242 (defun build-and-run-checkers (tree-kind)
243 (flet ((build-and-run (x)
244 (let ((*let-pred-determine-equivalency* x))
245 (multiple-value-bind (tree bitvector count)
246 (build-random-tree tree-kind 200 :delete t)
247 (declare (ignore count))
248 (dolist (test *tree-checkers* t)
249 (funcall (the function test) tree bitvector))))))
251 (loop repeat 1000 always (and (build-and-run t) (build-and-run nil)))
253 (:no-error (value) value))))
255 (rtest:deftest :normal (build-and-run-checkers :normal) t)
257 (rtest:deftest :avl (build-and-run-checkers :avl) t)
259 (rtest:deftest :red-black (build-and-run-checkers :red-black) t)
261 (rtest:deftest :aa (build-and-run-checkers :aa) t)