exceptions.test 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. ;;;; exceptions.test --- tests for Guile's exception handling -*- scheme -*-
  2. ;;;; Copyright (C) 2001, 2003, 2004, 2006, 2010 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. (define-module (test-suite exceptions)
  18. #:use-module (test-suite lib))
  19. (define-syntax-parameter push
  20. (lambda (stx)
  21. (syntax-violation 'push "push used outside of throw-test" stx)))
  22. (define-syntax-rule (throw-test title result expr ...)
  23. (pass-if title
  24. (equal? result
  25. (let ((stack '()))
  26. (syntax-parameterize ((push (syntax-rules ()
  27. ((push val)
  28. (set! stack (cons val stack))))))
  29. expr ...
  30. ;;(format #t "~a: ~s~%" title (reverse stack))
  31. (reverse stack))))))
  32. (with-test-prefix "throw/catch"
  33. (with-test-prefix "wrong type argument"
  34. (pass-if-exception "(throw 1)"
  35. exception:wrong-type-arg
  36. (throw 1)))
  37. (with-test-prefix "wrong number of arguments"
  38. (pass-if-exception "(throw)"
  39. exception:wrong-num-args
  40. (throw))
  41. (pass-if-exception "throw 1 / catch 0"
  42. exception:wrong-num-args
  43. (catch 'a
  44. (lambda () (throw 'a))
  45. (lambda () #f)))
  46. (pass-if-exception "throw 2 / catch 1"
  47. exception:wrong-num-args
  48. (catch 'a
  49. (lambda () (throw 'a 2))
  50. (lambda (x) #f)))
  51. (pass-if-exception "throw 1 / catch 2"
  52. exception:wrong-num-args
  53. (catch 'a
  54. (lambda () (throw 'a))
  55. (lambda (x y) #f)))
  56. (pass-if-exception "throw 3 / catch 2"
  57. exception:wrong-num-args
  58. (catch 'a
  59. (lambda () (throw 'a 2 3))
  60. (lambda (y x) #f)))
  61. (pass-if-exception "throw 1 / catch 2+"
  62. exception:wrong-num-args
  63. (catch 'a
  64. (lambda () (throw 'a))
  65. (lambda (x y . rest) #f))))
  66. (with-test-prefix "with pre-unwind handler"
  67. (pass-if "pre-unwind fluid state"
  68. (equal? '(inner outer arg)
  69. (let ((fluid-parm (make-fluid))
  70. (inner-val #f))
  71. (fluid-set! fluid-parm 'outer)
  72. (catch 'misc-exc
  73. (lambda ()
  74. (with-fluids ((fluid-parm 'inner))
  75. (throw 'misc-exc 'arg)))
  76. (lambda (key . args)
  77. (list inner-val
  78. (fluid-ref fluid-parm)
  79. (car args)))
  80. (lambda (key . args)
  81. (set! inner-val (fluid-ref fluid-parm))))))))
  82. (throw-test "normal catch"
  83. '(1 2)
  84. (catch 'a
  85. (lambda ()
  86. (push 1)
  87. (throw 'a))
  88. (lambda (key . args)
  89. (push 2))))
  90. (throw-test "catch and with-throw-handler"
  91. '(1 2 3 4)
  92. (catch 'a
  93. (lambda ()
  94. (push 1)
  95. (with-throw-handler
  96. 'a
  97. (lambda ()
  98. (push 2)
  99. (throw 'a))
  100. (lambda (key . args)
  101. (push 3))))
  102. (lambda (key . args)
  103. (push 4))))
  104. (throw-test "catch with rethrowing throw-handler"
  105. '(1 2 3 4)
  106. (catch 'a
  107. (lambda ()
  108. (push 1)
  109. (with-throw-handler
  110. 'a
  111. (lambda ()
  112. (push 2)
  113. (throw 'a))
  114. (lambda (key . args)
  115. (push 3)
  116. (apply throw key args))))
  117. (lambda (key . args)
  118. (push 4))))
  119. (throw-test "catch with pre-unwind handler"
  120. '(1 3 2)
  121. (catch 'a
  122. (lambda ()
  123. (push 1)
  124. (throw 'a))
  125. (lambda (key . args)
  126. (push 2))
  127. (lambda (key . args)
  128. (push 3))))
  129. (throw-test "catch with rethrowing pre-unwind handler"
  130. '(1 3 2)
  131. (catch 'a
  132. (lambda ()
  133. (push 1)
  134. (throw 'a))
  135. (lambda (key . args)
  136. (push 2))
  137. (lambda (key . args)
  138. (push 3)
  139. (apply throw key args))))
  140. (throw-test "catch with throw handler"
  141. '(1 2 3 4)
  142. (catch 'a
  143. (lambda ()
  144. (push 1)
  145. (with-throw-handler 'a
  146. (lambda ()
  147. (push 2)
  148. (throw 'a))
  149. (lambda (key . args)
  150. (push 3))))
  151. (lambda (key . args)
  152. (push 4))))
  153. (throw-test "catch with rethrowing throw handler"
  154. '(1 2 3 4)
  155. (catch 'a
  156. (lambda ()
  157. (push 1)
  158. (with-throw-handler 'a
  159. (lambda ()
  160. (push 2)
  161. (throw 'a))
  162. (lambda (key . args)
  163. (push 3)
  164. (apply throw key args))))
  165. (lambda (key . args)
  166. (push 4))))
  167. (throw-test "effect of with-throw-handler not-unwinding on throw to another key"
  168. '(1 2 3 5 4 6)
  169. (catch 'a
  170. (lambda ()
  171. (push 1)
  172. (with-throw-handler 'b
  173. (lambda ()
  174. (push 2)
  175. (catch 'a
  176. (lambda ()
  177. (push 3)
  178. (throw 'b))
  179. (lambda (key . args)
  180. (push 4))))
  181. (lambda (key . args)
  182. (push 5)
  183. (throw 'a)))
  184. (push 6))
  185. (lambda (key . args)
  186. (push 7))))
  187. (throw-test "with-throw-handler chaining"
  188. '(1 2 3 4 6 8)
  189. (catch 'a
  190. (lambda ()
  191. (push 1)
  192. (with-throw-handler 'a
  193. (lambda ()
  194. (push 2)
  195. (with-throw-handler 'a
  196. (lambda ()
  197. (push 3)
  198. (throw 'a))
  199. (lambda (key . args)
  200. (push 4)))
  201. (push 5))
  202. (lambda (key . args)
  203. (push 6)))
  204. (push 7))
  205. (lambda (key . args)
  206. (push 8))))
  207. (throw-test "throw handlers throwing to each other recursively"
  208. '(1 2 3 4 8 6 10 12)
  209. (catch #t
  210. (lambda ()
  211. (push 1)
  212. (with-throw-handler 'a
  213. (lambda ()
  214. (push 2)
  215. (with-throw-handler 'b
  216. (lambda ()
  217. (push 3)
  218. (with-throw-handler 'c
  219. (lambda ()
  220. (push 4)
  221. (throw 'b)
  222. (push 5))
  223. (lambda (key . args)
  224. (push 6)
  225. (throw 'a)))
  226. (push 7))
  227. (lambda (key . args)
  228. (push 8)
  229. (throw 'c)))
  230. (push 9))
  231. (lambda (key . args)
  232. (push 10)
  233. (throw 'b)))
  234. (push 11))
  235. (lambda (key . args)
  236. (push 12))))
  237. (throw-test "throw handler throwing to lexically inside catch"
  238. '(1 2 7 5 4 6 9)
  239. (with-throw-handler 'a
  240. (lambda ()
  241. (push 1)
  242. (catch 'b
  243. (lambda ()
  244. (push 2)
  245. (throw 'a)
  246. (push 3))
  247. (lambda (key . args)
  248. (push 4))
  249. (lambda (key . args)
  250. (push 5)))
  251. (push 6))
  252. (lambda (key . args)
  253. (push 7)
  254. (throw 'b)
  255. (push 8)))
  256. (push 9))
  257. (throw-test "reuse of same throw handler after lexically inside catch"
  258. '(0 1 2 7 5 4 6 7 10)
  259. (catch 'b
  260. (lambda ()
  261. (push 0)
  262. (with-throw-handler 'a
  263. (lambda ()
  264. (push 1)
  265. (catch 'b
  266. (lambda ()
  267. (push 2)
  268. (throw 'a)
  269. (push 3))
  270. (lambda (key . args)
  271. (push 4))
  272. (lambda (key . args)
  273. (push 5)))
  274. (push 6)
  275. (throw 'a))
  276. (lambda (key . args)
  277. (push 7)
  278. (throw 'b)
  279. (push 8)))
  280. (push 9))
  281. (lambda (key . args)
  282. (push 10))))
  283. (throw-test "again but with two chained throw handlers"
  284. '(0 1 11 2 13 7 5 4 12 13 7 10)
  285. (catch 'b
  286. (lambda ()
  287. (push 0)
  288. (with-throw-handler 'a
  289. (lambda ()
  290. (push 1)
  291. (with-throw-handler 'a
  292. (lambda ()
  293. (push 11)
  294. (catch 'b
  295. (lambda ()
  296. (push 2)
  297. (throw 'a)
  298. (push 3))
  299. (lambda (key . args)
  300. (push 4))
  301. (lambda (key . args)
  302. (push 5)))
  303. (push 12)
  304. (throw 'a))
  305. (lambda (key . args)
  306. (push 13)))
  307. (push 6))
  308. (lambda (key . args)
  309. (push 7)
  310. (throw 'b)))
  311. (push 9))
  312. (lambda (key . args)
  313. (push 10))))
  314. )
  315. (with-test-prefix "false-if-exception"
  316. (pass-if (false-if-exception #t))
  317. (pass-if (not (false-if-exception #f)))
  318. (pass-if (not (false-if-exception (error "xxx"))))
  319. ;; Not yet working.
  320. ;;
  321. ;; (with-test-prefix "in empty environment"
  322. ;; ;; an environment with no bindings at all
  323. ;; (define empty-environment
  324. ;; (make-module 1))
  325. ;;
  326. ;; (pass-if "#t"
  327. ;; (eval `(,false-if-exception #t)
  328. ;; empty-environment))
  329. ;; (pass-if "#f"
  330. ;; (not (eval `(,false-if-exception #f)
  331. ;; empty-environment)))
  332. ;; (pass-if "exception"
  333. ;; (not (eval `(,false-if-exception (,error "xxx"))
  334. ;; empty-environment))))
  335. )
  336. (with-test-prefix "delimited exception handlers"
  337. (define (catch* key thunk)
  338. (let ((tag (make-prompt-tag)))
  339. (call-with-prompt tag
  340. (lambda ()
  341. (catch key
  342. (lambda ()
  343. (abort-to-prompt tag)
  344. (thunk))
  345. (lambda args args)))
  346. (lambda (k) k))))
  347. (pass-if-equal '(foo)
  348. (let ((thunk (catch* 'foo (lambda () (throw 'foo)))))
  349. (thunk)))
  350. (pass-if-equal '(foo)
  351. (let* ((thunk1 (catch* 'foo (lambda () (throw 'foo))))
  352. (thunk2 (catch* 'bar (lambda () (thunk1)))))
  353. (thunk1)))
  354. (pass-if-equal '(foo)
  355. (let* ((thunk1 (catch* 'foo (lambda () (throw 'foo))))
  356. (thunk2 (catch* 'bar (lambda () (thunk1)))))
  357. (thunk2)))
  358. (pass-if-equal '(bar)
  359. (let* ((thunk1 (catch* 'foo (lambda () (throw 'bar))))
  360. (thunk2 (catch* 'bar (lambda () (thunk1)))))
  361. (thunk2))))