78.upstream.scm 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. ; <PLAINTEXT>
  2. ; Copyright (c) 2005-2006 Sebastian Egner.
  3. ;
  4. ; Permission is hereby granted, free of charge, to any person obtaining
  5. ; a copy of this software and associated documentation files (the
  6. ; ``Software''), to deal in the Software without restriction, including
  7. ; without limitation the rights to use, copy, modify, merge, publish,
  8. ; distribute, sublicense, and/or sell copies of the Software, and to
  9. ; permit persons to whom the Software is furnished to do so, subject to
  10. ; the following conditions:
  11. ;
  12. ; The above copyright notice and this permission notice shall be
  13. ; included in all copies or substantial portions of the Software.
  14. ;
  15. ; THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
  16. ; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. ; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. ; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. ; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. ; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. ; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. ;
  23. ; -----------------------------------------------------------------------
  24. ;
  25. ; Lightweight testing (reference implementation)
  26. ; ==============================================
  27. ;
  28. ; Sebastian.Egner@philips.com
  29. ; in R5RS + SRFI 23 (error) + SRFI 42 (comprehensions)
  30. ;
  31. ; history of this file:
  32. ; SE, 25-Oct-2004: first version based on code used in SRFIs 42 and 67
  33. ; SE, 19-Jan-2006: (arg ...) made optional in check-ec
  34. ;
  35. ; Naming convention "check:<identifier>" is used only internally.
  36. ; -- portability --
  37. ; PLT: (require (lib "23.ss" "srfi") (lib "42.ss" "srfi"))
  38. ; Scheme48: ,open srfi-23 srfi-42
  39. ; -- utilities --
  40. (define check:write write)
  41. ; You can also use a pretty printer if you have one.
  42. ; However, the output might not improve for most cases
  43. ; because the pretty printers usually output a trailing
  44. ; newline.
  45. ; PLT: (require (lib "pretty.ss")) (define check:write pretty-print)
  46. ; Scheme48: ,open pp (define check:write p)
  47. ; -- mode --
  48. (define check:mode #f)
  49. (define (check-set-mode! mode)
  50. (set! check:mode
  51. (case mode
  52. ((off) 0)
  53. ((summary) 1)
  54. ((report-failed) 10)
  55. ((report) 100)
  56. (else (error "unrecognized mode" mode)))))
  57. (check-set-mode! 'report)
  58. ; -- state --
  59. (define check:correct #f)
  60. (define check:failed #f)
  61. (define (check-reset!)
  62. (set! check:correct 0)
  63. (set! check:failed '()))
  64. (define (check:add-correct!)
  65. (set! check:correct (+ check:correct 1)))
  66. (define (check:add-failed! expression actual-result expected-result)
  67. (set! check:failed
  68. (cons (list expression actual-result expected-result)
  69. check:failed)))
  70. (check-reset!)
  71. ; -- reporting --
  72. (define (check:report-expression expression)
  73. (newline)
  74. (check:write expression)
  75. (display " => "))
  76. (define (check:report-actual-result actual-result)
  77. (check:write actual-result)
  78. (display " ; "))
  79. (define (check:report-correct cases)
  80. (display "correct")
  81. (if (not (= cases 1))
  82. (begin (display " (")
  83. (display cases)
  84. (display " cases checked)")))
  85. (newline))
  86. (define (check:report-failed expected-result)
  87. (display "*** failed ***")
  88. (newline)
  89. (display " ; expected result: ")
  90. (check:write expected-result)
  91. (newline))
  92. (define (check-report)
  93. (if (>= check:mode 1)
  94. (begin
  95. (newline)
  96. (display "; *** checks *** : ")
  97. (display check:correct)
  98. (display " correct, ")
  99. (display (length check:failed))
  100. (display " failed.")
  101. (if (or (null? check:failed) (<= check:mode 1))
  102. (newline)
  103. (let* ((w (car (reverse check:failed)))
  104. (expression (car w))
  105. (actual-result (cadr w))
  106. (expected-result (caddr w)))
  107. (display " First failed example:")
  108. (newline)
  109. (check:report-expression expression)
  110. (check:report-actual-result actual-result)
  111. (check:report-failed expected-result))))))
  112. (define (check-passed? expected-total-count)
  113. (and (= (length check:failed) 0)
  114. (= check:correct expected-total-count)))
  115. ; -- simple checks --
  116. (define (check:proc expression thunk equal expected-result)
  117. (case check:mode
  118. ((0) #f)
  119. ((1)
  120. (let ((actual-result (thunk)))
  121. (if (equal actual-result expected-result)
  122. (check:add-correct!)
  123. (check:add-failed! expression actual-result expected-result))))
  124. ((10)
  125. (let ((actual-result (thunk)))
  126. (if (equal actual-result expected-result)
  127. (check:add-correct!)
  128. (begin
  129. (check:report-expression expression)
  130. (check:report-actual-result actual-result)
  131. (check:report-failed expected-result)
  132. (check:add-failed! expression actual-result expected-result)))))
  133. ((100)
  134. (check:report-expression expression)
  135. (let ((actual-result (thunk)))
  136. (check:report-actual-result actual-result)
  137. (if (equal actual-result expected-result)
  138. (begin (check:report-correct 1)
  139. (check:add-correct!))
  140. (begin (check:report-failed expected-result)
  141. (check:add-failed! expression
  142. actual-result
  143. expected-result)))))
  144. (else (error "unrecognized check:mode" check:mode)))
  145. (if #f #f))
  146. (define-syntax check
  147. (syntax-rules (=>)
  148. ((check expr => expected)
  149. (check expr (=> equal?) expected))
  150. ((check expr (=> equal) expected)
  151. (if (>= check:mode 1)
  152. (check:proc 'expr (lambda () expr) equal expected)))))
  153. ; -- parametric checks --
  154. (define (check:proc-ec w)
  155. (let ((correct? (car w))
  156. (expression (cadr w))
  157. (actual-result (caddr w))
  158. (expected-result (cadddr w))
  159. (cases (car (cddddr w))))
  160. (if correct?
  161. (begin (if (>= check:mode 100)
  162. (begin (check:report-expression expression)
  163. (check:report-actual-result actual-result)
  164. (check:report-correct cases)))
  165. (check:add-correct!))
  166. (begin (if (>= check:mode 10)
  167. (begin (check:report-expression expression)
  168. (check:report-actual-result actual-result)
  169. (check:report-failed expected-result)))
  170. (check:add-failed! expression
  171. actual-result
  172. expected-result)))))
  173. (define-syntax check-ec:make
  174. (syntax-rules (=>)
  175. ((check-ec:make qualifiers expr (=> equal) expected (arg ...))
  176. (if (>= check:mode 1)
  177. (check:proc-ec
  178. (let ((cases 0))
  179. (let ((w (first-ec
  180. #f
  181. qualifiers
  182. (:let equal-pred equal)
  183. (:let expected-result expected)
  184. (:let actual-result
  185. (let ((arg arg) ...) ; (*)
  186. expr))
  187. (begin (set! cases (+ cases 1)))
  188. (if (not (equal-pred actual-result expected-result)))
  189. (list (list 'let (list (list 'arg arg) ...) 'expr)
  190. actual-result
  191. expected-result
  192. cases))))
  193. (if w
  194. (cons #f w)
  195. (list #t
  196. '(check-ec qualifiers
  197. expr (=> equal)
  198. expected (arg ...))
  199. (if #f #f)
  200. (if #f #f)
  201. cases)))))))))
  202. ; (*) is a compile-time check that (arg ...) is a list
  203. ; of pairwise disjoint bound variables at this point.
  204. (define-syntax check-ec
  205. (syntax-rules (nested =>)
  206. ((check-ec expr => expected)
  207. (check-ec:make (nested) expr (=> equal?) expected ()))
  208. ((check-ec expr (=> equal) expected)
  209. (check-ec:make (nested) expr (=> equal) expected ()))
  210. ((check-ec expr => expected (arg ...))
  211. (check-ec:make (nested) expr (=> equal?) expected (arg ...)))
  212. ((check-ec expr (=> equal) expected (arg ...))
  213. (check-ec:make (nested) expr (=> equal) expected (arg ...)))
  214. ((check-ec qualifiers expr => expected)
  215. (check-ec:make qualifiers expr (=> equal?) expected ()))
  216. ((check-ec qualifiers expr (=> equal) expected)
  217. (check-ec:make qualifiers expr (=> equal) expected ()))
  218. ((check-ec qualifiers expr => expected (arg ...))
  219. (check-ec:make qualifiers expr (=> equal?) expected (arg ...)))
  220. ((check-ec qualifiers expr (=> equal) expected (arg ...))
  221. (check-ec:make qualifiers expr (=> equal) expected (arg ...)))
  222. ((check-ec (nested q1 ...) q etc ...)
  223. (check-ec (nested q1 ... q) etc ...))
  224. ((check-ec q1 q2 etc ...)
  225. (check-ec (nested q1 q2) etc ...))))