basic.scm 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. ;; Fibers: cooperative, event-driven user-space threads.
  2. ;;;; Copyright (C) 2016 Free Software Foundation, Inc.
  3. ;;;;
  4. ;;;; This library is free software; you can redistribute it and/or
  5. ;;;; modify it under the terms of the GNU Lesser General Public
  6. ;;;; License as published by the Free Software Foundation; either
  7. ;;;; version 3 of the License, or (at your option) any later version.
  8. ;;;;
  9. ;;;; This library is distributed in the hope that it will be useful,
  10. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;;; Lesser General Public License for more details.
  13. ;;;;
  14. ;;;; You should have received a copy of the GNU Lesser General Public
  15. ;;;; License along with this library; if not, write to the Free Software
  16. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;;;;
  18. (define-module (tests basic)
  19. #:use-module (fibers))
  20. (define failed? #f)
  21. (define-syntax-rule (assert-equal expected actual)
  22. (let ((x expected))
  23. (format #t "assert ~s equal to ~s: " 'actual x)
  24. (force-output)
  25. (let ((y actual))
  26. (cond
  27. ((equal? x y) (format #t "ok\n"))
  28. (else
  29. (format #t "no (got ~s)\n" y)
  30. (set! failed? #t))))))
  31. (define-syntax-rule (assert-terminates exp)
  32. (begin
  33. (format #t "assert ~s terminates: " 'exp)
  34. (force-output)
  35. exp
  36. (format #t "ok\n")))
  37. (define-syntax-rule (assert-run-fibers-terminates exp kw ...)
  38. (begin
  39. (format #t "assert terminates: ~s: " '(run-fibers (lambda () exp) kw ...))
  40. (force-output)
  41. (let ((start (get-internal-real-time)))
  42. (call-with-values (lambda () (run-fibers (lambda () exp) kw ...))
  43. (lambda vals
  44. (format #t "ok (~a s)\n" (/ (- (get-internal-real-time) start)
  45. 1.0 internal-time-units-per-second))
  46. (apply values vals))))))
  47. (define-syntax-rule (assert-run-fibers-returns (expected ...) exp)
  48. (begin
  49. (call-with-values (lambda ()
  50. (assert-run-fibers-terminates exp #:drain? #t))
  51. (lambda run-fiber-return-vals
  52. (assert-equal '(expected ...) run-fiber-return-vals)))))
  53. (define-syntax-rule (do-times n exp)
  54. (let lp ((count n))
  55. (let ((count (1- count)))
  56. exp
  57. (unless (zero? count) (lp count)))))
  58. (assert-equal #f #f)
  59. (assert-terminates #t)
  60. (assert-equal #f (false-if-exception (begin (run-fibers) #t)))
  61. (assert-run-fibers-terminates (sleep 1) #:drain? #t)
  62. (assert-run-fibers-terminates (do-times 1 (spawn-fiber (lambda () #t))) #:drain? #t)
  63. (assert-run-fibers-terminates (do-times 10 (spawn-fiber (lambda () #t))) #:drain? #t)
  64. (assert-run-fibers-terminates (do-times 100 (spawn-fiber (lambda () #t))) #:drain? #t)
  65. (assert-run-fibers-terminates (do-times 1000 (spawn-fiber (lambda () #t))) #:drain? #t)
  66. (assert-run-fibers-terminates (do-times 10000 (spawn-fiber (lambda () #t))) #:drain? #t)
  67. (assert-run-fibers-terminates (do-times 100000 (spawn-fiber (lambda () #t))) #:drain? #t)
  68. (assert-run-fibers-terminates (do-times 100000
  69. (spawn-fiber (lambda () #t) #:parallel? #t)) #:drain? #t)
  70. (define (loop-to-1e4) (let lp ((i 0)) (when (< i #e1e4) (lp (1+ i)))))
  71. (assert-run-fibers-terminates (do-times 100000 (spawn-fiber loop-to-1e4)) #:drain? #t)
  72. (assert-run-fibers-terminates (do-times 100000 (spawn-fiber loop-to-1e4 #:parallel? #t)) #:drain? #t)
  73. (assert-run-fibers-terminates (do-times 1 (spawn-fiber (lambda () (sleep 1)))) #:drain? #t)
  74. (assert-run-fibers-terminates (do-times 10 (spawn-fiber (lambda () (sleep 1)))) #:drain? #t)
  75. (assert-run-fibers-terminates (do-times 100 (spawn-fiber (lambda () (sleep 1)))) #:drain? #t)
  76. (assert-run-fibers-terminates (do-times 1000 (spawn-fiber (lambda () (sleep 1)))) #:drain? #t)
  77. (assert-run-fibers-terminates (do-times 10000 (spawn-fiber (lambda () (sleep 1)))) #:drain? #t)
  78. (assert-run-fibers-terminates (do-times 20000 (spawn-fiber (lambda () (sleep 1)))) #:drain? #t)
  79. (assert-run-fibers-terminates (do-times 40000 (spawn-fiber (lambda () (sleep 1)))) #:drain? #t)
  80. (define (spawn-fiber-tree n leaf)
  81. (do-times n (spawn-fiber
  82. (lambda ()
  83. (if (= n 1)
  84. (leaf)
  85. (spawn-fiber-tree (1- n) leaf))))))
  86. (assert-run-fibers-terminates (spawn-fiber-tree 5 (lambda () (sleep 1))) #:drain? #t)
  87. (define (spawn-fiber-chain n)
  88. (spawn-fiber
  89. (lambda ()
  90. (unless (zero? (1- n))
  91. (spawn-fiber-chain (1- n))))))
  92. (assert-run-fibers-terminates (spawn-fiber-chain 5) #:drain? #t)
  93. (assert-run-fibers-terminates (spawn-fiber-chain 50) #:drain? #t)
  94. (assert-run-fibers-terminates (spawn-fiber-chain 500) #:drain? #t)
  95. (assert-run-fibers-terminates (spawn-fiber-chain 5000) #:drain? #t)
  96. (assert-run-fibers-terminates (spawn-fiber-chain 50000) #:drain? #t)
  97. (assert-run-fibers-terminates (spawn-fiber-chain 500000) #:drain? #t)
  98. (assert-run-fibers-terminates (spawn-fiber-chain 5000000) #:drain? #t)
  99. (let ((run-order 0))
  100. (define (test-run-order count)
  101. (for-each (lambda (n)
  102. (spawn-fiber
  103. (lambda ()
  104. (unless (eqv? run-order n)
  105. (error "bad run order" run-order n))
  106. (set! run-order (1+ n)))))
  107. (iota count)))
  108. (assert-run-fibers-terminates (test-run-order 10) #:parallelism 1 #:drain? #t))
  109. (let ((run-order 0))
  110. (define (test-wakeup-order count)
  111. (for-each (lambda (n)
  112. (spawn-fiber
  113. (lambda ()
  114. (unless (eqv? run-order n)
  115. (error "bad run order" run-order n))
  116. (set! run-order (1+ n)))))
  117. (iota count)))
  118. (assert-run-fibers-terminates (test-wakeup-order 10) #:parallelism 1 #:drain? #t))
  119. (assert-run-fibers-returns (1) 1)
  120. (define (check-sleep timeout)
  121. (spawn-fiber (lambda ()
  122. (let ((start (get-internal-real-time)))
  123. (sleep timeout)
  124. (let ((elapsed (/ (- (get-internal-real-time) start)
  125. 1.0 internal-time-units-per-second)))
  126. (format #t "assert sleep ~as < actual ~as: ~a (diff: ~a%)\n"
  127. timeout elapsed (<= timeout elapsed)
  128. (* 100 (/ (- elapsed timeout) timeout)))
  129. (set! failed? (< elapsed timeout)))))))
  130. (assert-run-fibers-terminates
  131. (do-times 20 (check-sleep (random 1.0))) #:drain? #t)
  132. ;; exceptions
  133. ;; closing port causes pollerr
  134. ;; live threads list
  135. (exit (if failed? 1 0))