64.body.scm 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. ;; Copyright (c) 2005, 2006, 2007, 2012, 2013 Per Bothner
  2. ;; Added "full" support for Chicken, Gauche, Guile and SISC.
  3. ;; Alex Shinn, Copyright (c) 2005.
  4. ;; Modified for Scheme Spheres by Álvaro Castro-Castilla, Copyright (c) 2012.
  5. ;; Support for Guile 2 by Mark H Weaver <mhw@netris.org>, Copyright (c) 2014.
  6. ;; Made an R7RS library by Taylan Ulrich Bayırlı/Kammer, Copyright (c) 2014.
  7. ;;
  8. ;; Permission is hereby granted, free of charge, to any person
  9. ;; obtaining a copy of this software and associated documentation
  10. ;; files (the "Software"), to deal in the Software without
  11. ;; restriction, including without limitation the rights to use, copy,
  12. ;; modify, merge, publish, distribute, sublicense, and/or sell copies
  13. ;; of the Software, and to permit persons to whom the Software is
  14. ;; furnished to do so, subject to the following conditions:
  15. ;;
  16. ;; The above copyright notice and this permission notice shall be
  17. ;; included in all copies or substantial portions of the Software.
  18. ;;
  19. ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20. ;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  21. ;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22. ;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  23. ;; BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  24. ;; ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  25. ;; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  26. ;; SOFTWARE.
  27. ;;; Test runner type
  28. (define-record-type <test-runner>
  29. (make-test-runner) test-runner?
  30. (result-alist test-result-alist test-result-alist!)
  31. (pass-count test-runner-pass-count test-runner-pass-count!)
  32. (fail-count test-runner-fail-count test-runner-fail-count!)
  33. (xpass-count test-runner-xpass-count test-runner-xpass-count!)
  34. (xfail-count test-runner-xfail-count test-runner-xfail-count!)
  35. (skip-count test-runner-skip-count test-runner-skip-count!)
  36. (total-count %test-runner-total-count %test-runner-total-count!)
  37. ;; Stack (list) of (count-at-start . expected-count):
  38. (count-list %test-runner-count-list %test-runner-count-list!)
  39. ;; Normally #f, except when in a test-apply.
  40. (run-list %test-runner-run-list %test-runner-run-list!)
  41. (skip-list %test-runner-skip-list %test-runner-skip-list!)
  42. (fail-list %test-runner-fail-list %test-runner-fail-list!)
  43. (skip-save %test-runner-skip-save %test-runner-skip-save!)
  44. (fail-save %test-runner-fail-save %test-runner-fail-save!)
  45. (group-stack test-runner-group-stack test-runner-group-stack!)
  46. ;; Note: on-test-begin and on-test-end are *not* related to test-begin and
  47. ;; test-end. They're called at the beginning/end of each individual test,
  48. ;; whereas test-begin/test-end demarcate whole test suites.
  49. (on-group-begin test-runner-on-group-begin test-runner-on-group-begin!)
  50. (on-test-begin test-runner-on-test-begin test-runner-on-test-begin!)
  51. (on-test-end test-runner-on-test-end test-runner-on-test-end!)
  52. (on-group-end test-runner-on-group-end test-runner-on-group-end!)
  53. (on-final test-runner-on-final test-runner-on-final!)
  54. (on-bad-count test-runner-on-bad-count test-runner-on-bad-count!)
  55. (on-bad-end-name test-runner-on-bad-end-name test-runner-on-bad-end-name!)
  56. (aux-value test-runner-aux-value test-runner-aux-value!))
  57. (define (test-runner-reset runner)
  58. (test-result-alist! runner '())
  59. (test-runner-pass-count! runner 0)
  60. (test-runner-fail-count! runner 0)
  61. (test-runner-xpass-count! runner 0)
  62. (test-runner-xfail-count! runner 0)
  63. (test-runner-skip-count! runner 0)
  64. (%test-runner-total-count! runner 0)
  65. (%test-runner-count-list! runner '())
  66. (%test-runner-run-list! runner #f)
  67. (%test-runner-skip-list! runner '())
  68. (%test-runner-fail-list! runner '())
  69. (%test-runner-skip-save! runner '())
  70. (%test-runner-fail-save! runner '())
  71. (test-runner-group-stack! runner '()))
  72. (define (test-runner-group-path runner)
  73. (reverse (test-runner-group-stack runner)))
  74. (define test-result-ref
  75. (case-lambda
  76. ((runner key)
  77. (test-result-ref runner key #f))
  78. ((runner key default)
  79. (let ((entry (assq key (test-result-alist runner))))
  80. (if entry (cdr entry) default)))))
  81. (define (test-result-set! runner key value)
  82. (let* ((alist (test-result-alist runner))
  83. (entry (assq key alist)))
  84. (if entry
  85. (set-cdr! entry value)
  86. (test-result-alist! runner (cons (cons key value) alist)))))
  87. (define (test-result-clear runner)
  88. (test-result-alist! runner '()))
  89. (define (test-result-remove runner key)
  90. (test-result-alist! runner (remove (lambda (entry)
  91. (eq? key (car entry)))
  92. (test-result-alist runner))))
  93. (define test-result-name
  94. (case-lambda
  95. (() (test-result-name (test-runner-get)))
  96. ((runner) (test-result-ref runner 'test-name ""))))
  97. (define test-result-name!
  98. (case-lambda
  99. ((name) (test-result-name (test-runner-get) name))
  100. ((runner name) (test-result-set! runner 'test-name name))))
  101. (define test-result-expression
  102. (case-lambda
  103. (() (test-result-expression (test-runner-get)))
  104. ((runner) (test-result-ref runner 'expression))))
  105. (define test-result-expression!
  106. (case-lambda
  107. ((expression) (test-result-expression! (test-runner-get) expression))
  108. ((runner expression) (test-result-set! runner 'expression expression))))
  109. (define test-result-kind
  110. (case-lambda
  111. (() (test-result-kind (test-runner-get)))
  112. ((runner) (test-result-ref runner 'result-kind))))
  113. (define test-result-kind!
  114. (case-lambda
  115. ((kind) (test-result-kind! (test-runner-get) kind))
  116. ((runner kind) (test-result-set! runner 'result-kind kind))))
  117. (define test-passed?
  118. (case-lambda
  119. (() (test-passed? (test-runner-get)))
  120. ((runner) (memq (test-result-kind runner) '(pass xpass)))))
  121. (define test-runner-test-name test-result-name)
  122. (define test-runner-factory (make-parameter #f))
  123. (define (test-runner-create) ((test-runner-factory)))
  124. (define test-runner-current (make-parameter #f))
  125. (define (test-runner-get)
  126. (or (test-runner-current)
  127. (error "test-runner not initialized - test-begin missing?")))
  128. (define test-match-nth
  129. (case-lambda
  130. ((n) (test-match-nth n 1))
  131. ((n count)
  132. (let ((i 0))
  133. (lambda (runner)
  134. (set! i (+ i 1))
  135. (and (>= i n) (< i (+ n count))))))))
  136. (define (test-match-name name)
  137. (lambda (runner)
  138. (equal? name (test-result-name runner))))
  139. (define (make-pred spec)
  140. (cond ((procedure? spec) spec)
  141. ((integer? spec) (test-match-nth 1 spec))
  142. ((string? spec) (test-match-name spec))
  143. (else
  144. (error "not a valid test specifier" spec))))
  145. (define (any-pred preds object)
  146. (any (lambda (pred) (pred object)) preds))
  147. (define (every-pred preds object)
  148. (every (lambda (pred) (pred object)) preds))
  149. (define (test-match-all . specs)
  150. (let ((preds (map make-pred specs)))
  151. (lambda (runner)
  152. (every-pred preds runner))))
  153. (define (test-match-any . specs)
  154. (let ((preds (map make-pred specs)))
  155. (lambda (runner)
  156. (any-pred preds runner))))
  157. ;;; Null runner
  158. (define (test-runner-null)
  159. (define (%test-null-callback runner) #f)
  160. (let ((runner (make-test-runner)))
  161. (test-runner-reset runner)
  162. (test-runner-on-group-begin! runner (lambda (runner name count) #f))
  163. (test-runner-on-group-end! runner %test-null-callback)
  164. (test-runner-on-final! runner %test-null-callback)
  165. (test-runner-on-test-begin! runner %test-null-callback)
  166. (test-runner-on-test-end! runner %test-null-callback)
  167. (test-runner-on-bad-count! runner (lambda (runner count expected) #f))
  168. (test-runner-on-bad-end-name! runner (lambda (runner begin end) #f))
  169. runner))
  170. ;;; Simple runner
  171. (define (test-on-group-begin-simple runner name count)
  172. (if (null? (test-runner-group-stack runner))
  173. (format #t "%%%% Test suite begin: ~a\n" name)
  174. (format #t "Group begin: ~a\n" name)))
  175. (define (test-on-test-begin-simple runner)
  176. (values))
  177. (define (test-on-test-end-simple runner)
  178. (let* ((result-kind (test-result-kind runner))
  179. (result-kind-name (case result-kind
  180. ((pass) "PASS") ((fail) "FAIL")
  181. ((xpass) "XPASS") ((xfail) "XFAIL")
  182. ((skip) "SKIP")))
  183. (label (let ((test-name (test-result-name runner)))
  184. (if (string=? "" test-name)
  185. (test-result-expression runner)
  186. test-name))))
  187. (format #t "[~a] ~a\n" result-kind-name label)))
  188. (define (test-on-group-end-simple runner)
  189. (let ((name (car (test-runner-group-stack runner))))
  190. (if (= 1 (length (test-runner-group-stack runner)))
  191. (format #t "%%%% Test suite end: ~a\n" name)
  192. (format #t "Group end: ~a\n" name))))
  193. (define (test-on-final-simple runner)
  194. (define (maybe-display label value)
  195. (when (> value 0)
  196. (display label) (display value) (newline)))
  197. (maybe-display
  198. "# of expected passes " (test-runner-pass-count runner))
  199. (maybe-display
  200. "# of expected failures " (test-runner-xfail-count runner))
  201. (maybe-display
  202. "# of unexpected successes " (test-runner-xpass-count runner))
  203. (maybe-display
  204. "# of unexpected failures " (test-runner-fail-count runner))
  205. (maybe-display
  206. "# of skipped tests " (test-runner-skip-count runner)))
  207. (define (test-on-bad-count-simple runner count expected-count)
  208. (format #t "*** Total number of tests was ~a but should be ~a. ***\n"
  209. count expected-count)
  210. (display "*** Discrepancy indicates testsuite error or exceptions. ***\n"))
  211. (define (test-on-bad-end-name-simple runner begin-name end-name)
  212. (error (format #f "test-end ~a does not match test-begin ~a"
  213. end-name begin-name)))
  214. (define (test-runner-simple)
  215. (let ((runner (make-test-runner)))
  216. (test-runner-reset runner)
  217. (test-runner-on-group-begin! runner test-on-group-begin-simple)
  218. (test-runner-on-group-end! runner test-on-group-end-simple)
  219. (test-runner-on-final! runner test-on-final-simple)
  220. (test-runner-on-test-begin! runner test-on-test-begin-simple)
  221. (test-runner-on-test-end! runner test-on-test-end-simple)
  222. (test-runner-on-bad-count! runner test-on-bad-count-simple)
  223. (test-runner-on-bad-end-name! runner test-on-bad-end-name-simple)
  224. runner))
  225. ;;; Set default factory to simple.
  226. (test-runner-factory test-runner-simple)
  227. ;;; Test execution control
  228. (define-syntax test-begin
  229. (syntax-rules ()
  230. ((_ suite-name)
  231. (test-begin suite-name #f))
  232. ((_ suite-name count)
  233. (let ((name suite-name))
  234. (when (not (test-runner-current))
  235. (test-runner-current (test-runner-create)))
  236. (let ((r (test-runner-current)))
  237. (let ((skip-list (%test-runner-skip-list r))
  238. (skip-save (%test-runner-skip-save r))
  239. (fail-list (%test-runner-fail-list r))
  240. (fail-save (%test-runner-fail-save r))
  241. (total-count (%test-runner-total-count r))
  242. (count-list (%test-runner-count-list r))
  243. (group-stack (test-runner-group-stack r)))
  244. ((test-runner-on-group-begin r) r name count)
  245. (%test-runner-skip-save! r (cons skip-list skip-save))
  246. (%test-runner-fail-save! r (cons fail-list fail-save))
  247. (%test-runner-count-list! r (cons (cons total-count count)
  248. count-list))
  249. (test-runner-group-stack! r (cons name group-stack))))))))
  250. (define-syntax test-end
  251. (syntax-rules ()
  252. ((_)
  253. (test-end #f))
  254. ((_ suite-name)
  255. (let ((name suite-name))
  256. (let* ((r (test-runner-get))
  257. (groups (test-runner-group-stack r)))
  258. (test-result-clear r)
  259. (when (null? groups)
  260. (error "test-end not in a group"))
  261. (when (and name (not (equal? name (car groups))))
  262. ((test-runner-on-bad-end-name r) r name (car groups)))
  263. (let* ((count-list (%test-runner-count-list r))
  264. (expected-count (cdar count-list))
  265. (saved-count (caar count-list))
  266. (group-count (- (%test-runner-total-count r) saved-count)))
  267. (when (and expected-count
  268. (not (= expected-count group-count)))
  269. ((test-runner-on-bad-count r) r group-count expected-count))
  270. ((test-runner-on-group-end r) r)
  271. (test-runner-group-stack! r (cdr (test-runner-group-stack r)))
  272. (%test-runner-skip-list! r (car (%test-runner-skip-save r)))
  273. (%test-runner-skip-save! r (cdr (%test-runner-skip-save r)))
  274. (%test-runner-fail-list! r (car (%test-runner-fail-save r)))
  275. (%test-runner-fail-save! r (cdr (%test-runner-fail-save r)))
  276. (%test-runner-count-list! r (cdr count-list))
  277. (when (null? (test-runner-group-stack r))
  278. ((test-runner-on-final r) r))))))))
  279. (define (test-skip? runner)
  280. (let ((run-list (%test-runner-run-list runner))
  281. (skip-list (%test-runner-skip-list runner)))
  282. (or (and run-list (not (any-pred run-list runner)))
  283. (any-pred skip-list runner))))
  284. (define-syntax test-group
  285. (syntax-rules ()
  286. ((_ suite-name body body* ...)
  287. (let ((runner (test-runner-get))
  288. (name suite-name))
  289. (test-result-clear runner)
  290. (test-result-name! runner name)
  291. (unless (test-skip? runner)
  292. (dynamic-wind
  293. (lambda () (test-begin name))
  294. (lambda () body body* ...)
  295. (lambda () (test-end name))))))))
  296. (define-syntax test-group-with-cleanup
  297. (syntax-rules ()
  298. ((_ suite-name body body* ... cleanup)
  299. (test-group suite-name
  300. (dynamic-wind (lambda () #f)
  301. (lambda () body body* ...)
  302. (lambda () cleanup))))))
  303. (define (test-skip . specs)
  304. (let ((runner (test-runner-get)))
  305. (%test-runner-skip-list!
  306. runner (cons (apply test-match-all specs)
  307. (%test-runner-skip-list runner)))))
  308. (define (test-expect-fail . specs)
  309. (let ((runner (test-runner-get)))
  310. (%test-runner-fail-list!
  311. runner (cons (apply test-match-all specs)
  312. (%test-runner-fail-list runner)))))
  313. (define (test-prelude runner name expression)
  314. (test-result-clear runner)
  315. (when name
  316. (test-result-name! runner name))
  317. (test-result-expression! runner expression)
  318. (let ((skip? (test-skip? runner)))
  319. (if skip?
  320. (test-result-kind! runner 'skip)
  321. (let ((fail-list (%test-runner-fail-list runner)))
  322. (when (any-pred fail-list runner)
  323. (test-result-kind! runner 'xfail)))) ;just for later inspection
  324. ((test-runner-on-test-begin runner) runner)
  325. (not skip?)))
  326. (define (test-postlude runner)
  327. (let ((result-kind (test-result-kind runner)))
  328. (case result-kind
  329. ((pass)
  330. (test-runner-pass-count! runner (+ 1 (test-runner-pass-count runner))))
  331. ((fail)
  332. (test-runner-fail-count! runner (+ 1 (test-runner-fail-count runner))))
  333. ((xpass)
  334. (test-runner-xpass-count! runner (+ 1 (test-runner-xpass-count runner))))
  335. ((xfail)
  336. (test-runner-xfail-count! runner (+ 1 (test-runner-xfail-count runner))))
  337. ((skip)
  338. (test-runner-skip-count! runner (+ 1 (test-runner-skip-count runner)))))
  339. (%test-runner-total-count! runner (+ 1 (%test-runner-total-count runner)))
  340. ((test-runner-on-test-end runner) runner)))
  341. (define (fix-result-kind runner pass?)
  342. (test-result-kind! runner (if (eq? (test-result-kind runner) 'xfail)
  343. (if pass? 'xpass 'xfail)
  344. (if pass? 'pass 'fail))))
  345. (define-syntax false-if-error
  346. (syntax-rules ()
  347. ((_ expression runner)
  348. (guard (error
  349. (else
  350. (test-result-set! runner 'actual-error error)
  351. #f))
  352. expression))))
  353. (define-syntax test-assert
  354. (syntax-rules ()
  355. ((_ expr)
  356. (test-assert #f expr))
  357. ((_ name-expr expr)
  358. (let ((runner (test-runner-get))
  359. (name name-expr))
  360. (when (test-prelude runner name 'expr)
  361. (let ((val (false-if-error expr runner)))
  362. (test-result-set! runner 'actual-value val)
  363. (fix-result-kind runner val)))
  364. (test-postlude runner)))))
  365. (define-syntax test-compare
  366. (syntax-rules ()
  367. ((_ compare expected expr)
  368. (test-compare compare #f expected expr))
  369. ((_ compare name-expr expected-expr expr)
  370. (let ((runner (test-runner-get))
  371. (name name-expr))
  372. (when (test-prelude runner name 'expr)
  373. (let ((expected expected-expr))
  374. (test-result-set! runner 'expected-value expected)
  375. (let ((pass? (false-if-error
  376. (let ((val expr))
  377. (test-result-set! runner 'actual-value val)
  378. (compare expected val))
  379. runner)))
  380. (fix-result-kind runner pass?))))
  381. (test-postlude runner)))))
  382. (define-syntax test-equal
  383. (syntax-rules ()
  384. ((_ . rest)
  385. (test-compare equal? . rest))))
  386. (define-syntax test-eqv
  387. (syntax-rules ()
  388. ((_ . rest)
  389. (test-compare eqv? . rest))))
  390. (define-syntax test-eq
  391. (syntax-rules ()
  392. ((_ . rest)
  393. (test-compare eq? . rest))))
  394. (define (approx= error)
  395. (lambda (value expected)
  396. (let ((rval (real-part value))
  397. (ival (imag-part value))
  398. (rexp (real-part expected))
  399. (iexp (imag-part expected)))
  400. (and (>= rval (- rexp error))
  401. (>= ival (- iexp error))
  402. (<= rval (+ rexp error))
  403. (<= ival (+ iexp error))))))
  404. (define-syntax test-approximate
  405. (syntax-rules ()
  406. ((_ expected expr error)
  407. (test-approximate #f expected expr error))
  408. ((_ test-name expected expr error)
  409. (test-compare (approx= error) test-name expected expr))))
  410. (define (error-matches? error type)
  411. (cond
  412. ((eq? type #t)
  413. #t)
  414. ((condition-type? type)
  415. (and (condition? error) (condition-has-type? error type)))
  416. ((procedure? type)
  417. (type error))
  418. (else
  419. (format #t "WARNING: unknown error type predicate: ~a\n" type)
  420. (format #t " error was: ~a\n" error)
  421. #f)))
  422. (define-syntax test-error
  423. (syntax-rules ()
  424. ((_ expr)
  425. (test-error #f #t expr))
  426. ((_ error-type expr)
  427. ((test-error #f error-type expr)))
  428. ((_ name-expr error-type-expr expr)
  429. (let ((runner (test-runner-get))
  430. (name name-expr))
  431. (when (test-prelude runner name 'expr)
  432. (let ((error-type error-type-expr))
  433. (test-result-set! runner 'expected-error error-type)
  434. (let ((pass? (guard (error (else (test-result-set!
  435. runner 'actual-error error)
  436. (error-matches? error error-type)))
  437. (let ((val expr))
  438. (test-result-set! runner 'actual-value val))
  439. #f)))
  440. (fix-result-kind runner pass?))))
  441. (test-postlude runner)))))
  442. (define (test-apply first . rest)
  443. (let ((runner (if (test-runner? first)
  444. first
  445. (or (test-runner-current) (test-runner-create))))
  446. (run-list (if (test-runner? first)
  447. (drop-right rest 1)
  448. (cons first (drop-right rest 1))))
  449. (proc (last rest)))
  450. (test-with-runner runner
  451. (let ((saved-run-list (%test-runner-run-list runner)))
  452. (%test-runner-run-list! runner run-list)
  453. (proc)
  454. (%test-runner-run-list! runner saved-run-list)))))
  455. (define-syntax test-with-runner
  456. (syntax-rules ()
  457. ((_ runner body body* ...)
  458. (let ((saved-runner (test-runner-current)))
  459. (dynamic-wind
  460. (lambda () (test-runner-current runner))
  461. (lambda () body body* ...)
  462. (lambda () (test-runner-current saved-runner)))))))
  463. (define test-read-eval-string
  464. (case-lambda
  465. ((string)
  466. (test-read-eval-string string (cond-expand
  467. (guile (current-module))
  468. (else #f))))
  469. ((string env)
  470. (let* ((port (open-input-string string))
  471. (form (read port)))
  472. (if (eof-object? (read-char port))
  473. (if env
  474. (eval form env)
  475. (eval form))
  476. (error "(not at eof)"))))))