queue-check.scm 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Robert Ransom
  3. (define-test-suite queues-tests)
  4. (define-syntax with-queue
  5. (syntax-rules ()
  6. ((with-queue (?var) . ?body)
  7. (let ((?var (make-queue))) . ?body))))
  8. ;;; TODO? - move to utility package?
  9. (define-syntax list*
  10. (syntax-rules (skip)
  11. ((list* (skip ?expr) . ?rest)
  12. (begin ?expr
  13. (list* . ?rest)))
  14. ((list* ?expr . ?rest)
  15. (let ((x ?expr))
  16. (cons x (list* . ?rest))))
  17. ((list*)
  18. '())))
  19. ;;; TODO? - rename to PROVISIONAL-CELL-PUSH! and move to utility package?
  20. (define (prov-cell-push! c x)
  21. (ensure-atomicity!
  22. (provisional-cell-set! c (cons x (provisional-cell-ref c)))))
  23. ;; Test wrapper for ENQUEUE!. Real applications should use
  24. ;; ENQUEUE-MANY!, which is faster.
  25. (define (stuff-queue! q xs)
  26. (ensure-atomicity!
  27. (for-each (lambda (x) (enqueue! q x)) xs)))
  28. (define (devour-queue! q)
  29. (ensure-atomicity
  30. (let loop ((acc '()))
  31. (if (queue-empty? q)
  32. (reverse acc)
  33. (loop (cons (dequeue! q) acc))))))
  34. (define (suck-queue! q n)
  35. (ensure-atomicity
  36. (let loop ((acc '())
  37. (n n))
  38. (if (or (queue-empty? q)
  39. (<= n 0))
  40. (reverse acc)
  41. (loop (cons (dequeue! q) acc)
  42. (- n 1))))))
  43. ;;; Tests for utility functions used by the queues package.
  44. (define-test-case list->queue-list queues-tests
  45. (for-each
  46. (lambda (xs)
  47. (check (receive (head tail) (list->queue-list xs)
  48. (list xs (cdr head)))
  49. => (list xs xs))
  50. (if (not (null? xs))
  51. (check (receive (head tail) (list->queue-list xs)
  52. (list xs tail))
  53. => (list xs (srfi-1:last-pair xs))))
  54. (check (receive (head tail) (list->queue-list xs)
  55. (list xs (eq? (srfi-1:last-pair head) tail)))
  56. => (list xs #t)))
  57. '(() (foo) (foo bar) (foo bar baz) (foo bar baz quux))))
  58. ;;; Tests for the queue operations we plan to keep.
  59. (define (do-basic-tests!)
  60. (check (with-queue (q)
  61. (enqueue! q 'a)
  62. (dequeue! q))
  63. => 'a)
  64. (check (with-queue (q)
  65. (stuff-queue! q '(a b c a b c))
  66. (devour-queue! q))
  67. => '(a b c a b c))
  68. (check (with-queue (q)
  69. (stuff-queue! q '(a b c a b c))
  70. (list* (suck-queue! q 3)
  71. (skip (stuff-queue! q '(d e f)))
  72. (devour-queue! q)))
  73. => '((a b c) (a b c d e f)))
  74. (check (with-queue (q)
  75. (stuff-queue! q '(a b c a b c))
  76. (list* (suck-queue! q 3)
  77. (skip (enqueue-many! q '(d e f)))
  78. (devour-queue! q)))
  79. => '((a b c) (a b c d e f)))
  80. (check (with-queue (q)
  81. (stuff-queue! q '(a b c a b c))
  82. (list* (devour-queue! q)
  83. (maybe-dequeue! q)
  84. (skip (stuff-queue! q '(d e f)))
  85. (maybe-dequeue! q)
  86. (devour-queue! q)))
  87. => '((a b c a b c)
  88. #f
  89. d
  90. (e f))))
  91. (define-test-case basics queues-tests
  92. (do-basic-tests!))
  93. (define-test-case basics-in-big-transaction queues-tests
  94. (ensure-atomicity!
  95. ;; Calling CHECK inside a transaction is normally a *bad* idea, but
  96. ;; this transaction should not need to be restarted.
  97. (do-basic-tests!)))
  98. (define-test-case basics-comment-tests queues-tests
  99. (check (let ((q (make-queue))
  100. (c (make-cell '())))
  101. (enqueue! q 'a)
  102. (ensure-atomicity!
  103. (enqueue! q 'b)
  104. (prov-cell-push! c (maybe-dequeue! q)))
  105. (prov-cell-push! c (maybe-dequeue! q))
  106. (cell-ref c))
  107. => '(b a)))
  108. (define-test-case queue-head queues-tests
  109. (check-exception (with-queue (q) (queue-head q)))
  110. (check (with-queue (q)
  111. (stuff-queue! q '(a b c))
  112. (queue-head q))
  113. => 'a))
  114. (define-test-case list->queue queues-tests
  115. (check (let ((q (list->queue '(a b c d))))
  116. (list* (suck-queue! q 2)
  117. (skip (stuff-queue! q '(e f g)))
  118. (devour-queue! q)))
  119. => '((a b)
  120. (c d e f g))))
  121. ;;; Delenda.
  122. (define-test-case delenda-comment-tests queues-tests
  123. (check (let ((q (make-queue))
  124. (c (make-cell 'OOPS)))
  125. (enqueue! q 'a)
  126. (ensure-atomicity!
  127. (enqueue! q 'b)
  128. (provisional-cell-set! c (queue->list q)))
  129. (cell-ref c))
  130. => '(a b))
  131. (check (let ((q (make-queue))
  132. (c (make-cell 'OOPS)))
  133. (enqueue! q 'a)
  134. (ensure-atomicity!
  135. (enqueue! q 'b)
  136. (provisional-cell-set! c (queue-length q)))
  137. (cell-ref c))
  138. => 2)
  139. (check (let ((q (make-queue))
  140. (c (make-cell 'OOPS)))
  141. (enqueue! q 'a)
  142. (ensure-atomicity!
  143. (enqueue! q 'b)
  144. (provisional-cell-set! c (on-queue? q 'b)))
  145. (cell-ref c))
  146. => #t)
  147. ;; The following test is no longer in a comment, but might as well
  148. ;; stay here.
  149. (check (let ((q (make-queue))
  150. (c (make-cell '())))
  151. (enqueue! q 'a)
  152. (ensure-atomicity!
  153. (enqueue! q 'b)
  154. (prov-cell-push! c (delete-from-queue! q 'b))
  155. (prov-cell-push! c (maybe-dequeue! q))
  156. (prov-cell-push! c (maybe-dequeue! q)))
  157. (cell-ref c))
  158. => '(#f a #t)))
  159. (define-test-case queue-length queues-tests
  160. (for-each
  161. (lambda (n)
  162. (check (with-queue (q)
  163. (stuff-queue! q (srfi-1:iota n))
  164. (queue-length q))
  165. => n))
  166. '(0 1 2 3 4 5 6 7 8 9 10)))
  167. (define-test-case delete-from-queue! queues-tests
  168. (for-each
  169. (lambda (x)
  170. (check (with-queue (q)
  171. (stuff-queue! q '(a b c a b c))
  172. (list* x
  173. (delete-from-queue! q x)
  174. (devour-queue! q)))
  175. => (list x
  176. (x->boolean (memq x '(a b c)))
  177. (append (delq x '(a b c))
  178. '(a b c)))))
  179. '(a b c d))
  180. (for-each
  181. (lambda (x)
  182. (check (with-queue (q)
  183. (stuff-queue! q '(a b c a b c))
  184. (list* x
  185. (delete-from-queue! q x)
  186. (skip (stuff-queue! q '(d e f)))
  187. (devour-queue! q)))
  188. => (list x
  189. (x->boolean (memq x '(a b c)))
  190. (append (delq x '(a b c))
  191. '(a b c d e f)))))
  192. '(a b c d)))
  193. (define-test-case on-queue? queues-tests
  194. (check
  195. (map (lambda (x)
  196. (with-queue (q)
  197. (stuff-queue! q '(a b c))
  198. (on-queue? q x)))
  199. '(a b c d))
  200. => '(#t #t #t #f))
  201. (check
  202. (map (lambda (x)
  203. (with-queue (q)
  204. (on-queue? q x)))
  205. '(a b c d))
  206. => '(#f #f #f #f)))
  207. (define-test-case queue->list queues-tests
  208. (check (with-queue (q)
  209. (stuff-queue! q '(a b c d e f))
  210. (list* (queue->list q)
  211. (suck-queue! q 2)
  212. (skip (stuff-queue! q '(g h)))
  213. (queue->list q)
  214. (devour-queue! q)))
  215. => '((a b c d e f)
  216. (a b)
  217. (c d e f g h)
  218. (c d e f g h))))