envelope.scm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. ;; This file is part of scheme-GNUnet.
  2. ;; Copyright (C) 2021 GNUnet e.V.
  3. ;;
  4. ;; scheme-GNUnet is free software: you can redistribute it and/or modify it
  5. ;; under the terms of the GNU Affero General Public License as published
  6. ;; by the Free Software Foundation, either version 3 of the License,
  7. ;; or (at your option) any later version.
  8. ;;
  9. ;; scheme-GNUnet is distributed in the hope that it will be useful, but
  10. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; Affero General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU Affero General Public License
  15. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. ;;
  17. ;; SPDX-License-Identifier: AGPL-3.0-or-later
  18. (use-modules (ice-9 control)
  19. (srfi srfi-26)
  20. ((rnrs base) #:select (assert))
  21. ((rnrs conditions) #:select (&assertion))
  22. (tests utils) ; for conservative-gc?
  23. (gnu gnunet mq envelope)
  24. (gnu gnunet mq prio-prefs)
  25. (gnu gnunet mq prio-prefs2))
  26. (define *msg* (cons #f #t))
  27. (define (no-cancel!)
  28. (error "cancel?"))
  29. (define (no-notify-sent!)
  30. (error "notify-sent?"))
  31. (test-begin "notify-sent!")
  32. ;; First test things without any kind of concurrency,
  33. ;; and without stack overflows and OOM.
  34. ;; (No recursion, no asynchronics, no threads, no interrupts.)
  35. (test-assert "notify-sent!: called by attempt-irrevocable-sent! (before 'go')"
  36. (let/ec ec
  37. (attempt-irrevocable-sent!
  38. (make-envelope no-cancel! *msg*
  39. #:notify-sent!
  40. (lambda () (ec #t)))
  41. ((go message priority) (error "unreachable"))
  42. ((cancelled) (error "cancelled?"))
  43. ((already-sent) (error "already sent?")))
  44. (ec #f)))
  45. (test-eq "notify-sent!: only called once (--> already-sent)"
  46. 'already-sent
  47. (let* ((notify-sent!? #f)
  48. (first-part-done? #f)
  49. (notify-sent!
  50. (lambda ()
  51. (if notify-sent!?
  52. (error "called twice")
  53. (set! notify-sent!? #t)))))
  54. (let ((envelope (make-envelope no-cancel! *msg*
  55. #:notify-sent! notify-sent!)))
  56. (attempt-irrevocable-sent!
  57. envelope
  58. ((go message priority)
  59. (assert notify-sent!?)
  60. (assert (eq? message *msg*))
  61. (assert (= priority 0))
  62. ;; the assignment should only be done once
  63. (assert (not first-part-done?))
  64. (set! first-part-done? #t))
  65. ((cancelled) (error "cancelled?"))
  66. ((already-sent) (error "done?")))
  67. (assert first-part-done?)
  68. (attempt-irrevocable-sent!
  69. envelope
  70. ((go message priority) (error "go?/2"))
  71. ((cancelled) (error "cancelled?/2"))
  72. ((already-sent) 'already-sent)))))
  73. (test-equal "notify-sent!: not called if cancelled (--> cancelled)"
  74. '(seems-ok . seems-ok/2)
  75. (let* ((cancelled? #f)
  76. (cancel!
  77. (lambda ()
  78. (if cancelled?
  79. (error "what")
  80. (set! cancelled? #t))))
  81. (envelope (make-envelope cancel! *msg* #:notify-sent!
  82. no-notify-sent!))
  83. (result/1
  84. (attempt-cancel!
  85. envelope
  86. ((now-cancelled)
  87. (assert cancelled?)
  88. 'seems-ok)
  89. ((already-cancelled) (error "what/cancelled"))
  90. ((already-sent) (error "what/sent"))))
  91. (result/2
  92. (attempt-irrevocable-sent!
  93. envelope
  94. ((go message priority) (error "go?"))
  95. ((cancelled) 'seems-ok/2)
  96. ((already-sent) (error "what/sent/2")))))
  97. (cons result/1 result/2)))
  98. ;; Concurrency by recursion.
  99. (test-eq "notify-sent!: not called if cancelled (inside post-cancellation)"
  100. 'seems-ok
  101. (let* ((cancel-ok? (make-parameter #t))
  102. (cancel!
  103. (lambda ()
  104. (unless (cancel-ok?)
  105. (error "what"))))
  106. (envelope
  107. (make-envelope cancel! *msg* #:notify-sent! no-notify-sent!)))
  108. (attempt-cancel!
  109. envelope
  110. ((now-cancelled)
  111. (parameterize ((cancel-ok? #f))
  112. (attempt-irrevocable-sent!
  113. envelope
  114. ((go message priority) (error "go?"))
  115. ((cancelled) 'seems-ok)
  116. ((already-sent) (error "what/sent/2")))))
  117. ((already-cancelled) (error "what/cancelled"))
  118. ((already-sent) (error "what/sent")))))
  119. (test-eq "notify-sent!: only called once (nested)"
  120. 'seems-ok
  121. (let* ((sent? #f)
  122. (notify-sent!
  123. (lambda ()
  124. (if sent?
  125. (error "but I was already sent!")
  126. (set! sent? #t))))
  127. (envelope (make-envelope no-cancel! *msg* #:notify-sent! notify-sent!)))
  128. (attempt-irrevocable-sent!
  129. envelope
  130. ((go message priority)
  131. (assert sent?)
  132. (attempt-irrevocable-sent!
  133. envelope
  134. ((go message priority) (error "but I was already sent!"))
  135. ((cancelled) (error "cancelled/2?"))
  136. ((already-sent) 'seems-ok)))
  137. ((cancelled) (error "cancelled/1"))
  138. ((already-sent) (error "aleady-sent?")))))
  139. ;; TODO: asynchronics, multi-threading.
  140. ;; How does one reliably test these things anyways?
  141. ;; Maybe the VM trap interface can be used
  142. ;; (to delay asynchronics to inopportune times).
  143. ;; This seems a project of its own though.
  144. (test-end "notify-sent!")
  145. (test-begin "cancel!")
  146. (test-eq "cancel!: only called once (nested)"
  147. 'seems-ok
  148. (let* ((cancelled? #f)
  149. (cancel! (lambda ()
  150. (if cancelled?
  151. (error "cancelled at wrong time / too often")
  152. (set! cancelled? #t))))
  153. (envelope
  154. (make-envelope cancel! *msg* #:notify-sent! no-notify-sent!)))
  155. (attempt-cancel!
  156. envelope
  157. ((now-cancelled)
  158. (assert cancelled?)
  159. (attempt-cancel!
  160. envelope
  161. ((now-cancelled) 'twice-now-cancelled)
  162. ((already-cancelled) 'seems-ok)
  163. ((already-sent) (error "what send/1"))))
  164. ((already-cancelled) 'too-early-cancel)
  165. ((already-sent) (error "what send/2")))))
  166. (test-eq "cancel!: not after sent (sequential)"
  167. 'ok-already-sent
  168. (let* ((envelope (make-envelope no-cancel! *msg*))
  169. (first-step-done? #f)
  170. (second-step-done? #f))
  171. (attempt-irrevocable-sent!
  172. envelope
  173. ((go message priority)
  174. (assert (not first-step-done?))
  175. (set! first-step-done? #t))
  176. ((cancelled) (error "what / cancelled"))
  177. ((already-sent) (error "what / sent")))
  178. (assert first-step-done?)
  179. (attempt-cancel!
  180. envelope
  181. ((now-cancelled) (error "but I was sent"))
  182. ((already-cancelled) (error "cancelled?"))
  183. ((already-sent)
  184. (assert (not second-step-done?))
  185. (set! second-step-done? #t)
  186. 'ok-already-sent))))
  187. (test-eq "cancel!: not after sent (nested)"
  188. 'ok-already-sent
  189. (let* ((envelope (make-envelope no-cancel! *msg*)))
  190. (attempt-irrevocable-sent!
  191. envelope
  192. ((go message priority)
  193. (attempt-cancel!
  194. envelope
  195. ((now-cancelled) (error "but I was sent"))
  196. ((already-cancelled) (error "cancelled?"))
  197. ((already-sent) 'ok-already-sent)))
  198. ((cancelled) (error "what / cancelled"))
  199. ((already-sent) (error "what / sent")))))
  200. (test-eq "cancel!: only called once (sequential)"
  201. 'ok
  202. (let* ((cancelled? #f)
  203. (cancel! (lambda ()
  204. (if cancelled?
  205. (error "cancelled at wrong time / too often")
  206. (set! cancelled? #t))))
  207. (first-step-done? #f)
  208. (second-step-done? #f)
  209. (envelope
  210. (make-envelope cancel! *msg* #:notify-sent! no-notify-sent!)))
  211. (attempt-cancel!
  212. envelope
  213. ((now-cancelled)
  214. (assert cancelled?)
  215. (assert (not first-step-done?))
  216. (set! first-step-done? #t))
  217. ((already-cancelled) (error "too early already cancelled"))
  218. ((already-sent) (error "too early send")))
  219. (assert cancelled?)
  220. (assert first-step-done?)
  221. (attempt-cancel!
  222. envelope
  223. ((now-cancelled) 'double-cancel)
  224. ((already-cancelled)
  225. (assert (not second-step-done?))
  226. (set! second-step-done? #t)
  227. 'ok)
  228. ((already-sent) (error "should not have been sent")))))
  229. (test-end "cancel!")
  230. ;; We will now test whether references
  231. ;; to the notify-sent, cancel and message are dropped
  232. ;; when the message is marked as sent.
  233. (test-begin "gc")
  234. ;; Compilation of the source code of this test file
  235. ;; prevents procedures made by writing (lambda () STUFF)
  236. ;; from being garbage-collected.
  237. (define (fresh-gc-thunk)
  238. (eval '(lambda () 'fresh) (current-module)))
  239. (define (do-nothing) 'nothing)
  240. (test-skip (if (conservative-gc?) 4 0))
  241. (test-equal "references dropped after cancel"
  242. '(#t #t #t)
  243. (let* ((fresh-message (vector 0 1 2 3))
  244. (fresh-cancel (fresh-gc-thunk))
  245. (fresh-notify-sent (fresh-gc-thunk))
  246. (message-guard (make-guardian))
  247. (cancel-guard (make-guardian))
  248. (notify-sent-guard (make-guardian))
  249. (envelope (make-envelope fresh-cancel fresh-message
  250. #:notify-sent! fresh-notify-sent)))
  251. (message-guard fresh-message)
  252. (cancel-guard fresh-cancel)
  253. (notify-sent-guard fresh-notify-sent)
  254. (attempt-cancel!
  255. envelope
  256. ((now-cancelled)
  257. (gc)
  258. (list (->bool (message-guard))
  259. (->bool (cancel-guard))
  260. (->bool (notify-sent-guard))))
  261. ((already-cancelled) (error "what/cancelled"))
  262. ((already-sent) (error "what/sent")))))
  263. (test-equal "references dropped after sent"
  264. '(#t #t #t)
  265. (let* ((fresh-message (vector 0 1 2 3))
  266. (fresh-cancel (fresh-gc-thunk))
  267. (fresh-notify-sent (fresh-gc-thunk))
  268. (message-guard (make-guardian))
  269. (cancel-guard (make-guardian))
  270. (notify-sent-guard (make-guardian))
  271. (envelope (make-envelope fresh-cancel fresh-message
  272. #:notify-sent! fresh-notify-sent)))
  273. (message-guard fresh-message)
  274. (cancel-guard fresh-cancel)
  275. (notify-sent-guard fresh-notify-sent)
  276. (attempt-irrevocable-sent!
  277. envelope
  278. ((go message priority)
  279. (gc)
  280. (list (->bool (message-guard))
  281. (->bool (cancel-guard))
  282. (->bool (notify-sent-guard))))
  283. ((cancelled) (error "cancelled"))
  284. ((already-sent) (error "what/cancelled")))))
  285. (test-assert "reference to envelope dropped after cancel"
  286. (let ((envelope (make-envelope (lambda () 'ok) *msg*))
  287. (envelope-guard (make-guardian)))
  288. (envelope-guard envelope)
  289. (attempt-cancel!
  290. envelope
  291. ((now-cancelled)
  292. (gc)
  293. (list (->bool (envelope-guard))))
  294. ((already-cancelled) (error "what/cancelled"))
  295. ((already-sent) (error "what/sent")))))
  296. (test-assert "reference to envelope dropped after send"
  297. (let ((envelope (make-envelope no-cancel! *msg*))
  298. (envelope-guard (make-guardian)))
  299. (envelope-guard envelope)
  300. (attempt-irrevocable-sent!
  301. envelope
  302. ((go message priority)
  303. (gc)
  304. (list (->bool (envelope-guard))))
  305. ((cancelled) (error "what/cancelled"))
  306. ((already-sent) (error "what/sent")))))
  307. (test-end "gc")
  308. (test-begin "arguments")
  309. (define %max-prio (- (expt 2 9) 1))
  310. (test-equal "non-standard priority"
  311. %max-prio
  312. (attempt-irrevocable-sent!
  313. (make-envelope no-cancel! *msg* #:priority %max-prio)
  314. ((go message priority) *msg* %max-prio)
  315. ((cancelled) (error "what/cancelled"))
  316. ((already-sent) (error "what/sent"))))
  317. (test-error "no negative priority"
  318. &assertion
  319. (make-envelope no-cancel! *msg* #:priority -1))
  320. (test-error "no inexact priority"
  321. &assertion
  322. (make-envelope no-cancel! *msg* #:priority 0.0))
  323. (test-error "no fractional priority"
  324. &assertion
  325. (make-envelope no-cancel! *msg* #:priority 5/7))
  326. (test-error "no overly large priority"
  327. &assertion
  328. (make-envelope no-cancel! *msg* #:priority 512))
  329. (test-end "arguments")
  330. ;; TODO for completeness: test recursion from
  331. ;; the notify-sent! callback and from cancel!
  332. ;; callback and that references are dropped
  333. ;; there as well.