exceptions.test 9.8 KB

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