iou 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. checksums.yaml +7 -0
  2. data/.github/dependabot.yml +12 -0
  3. data/.gitignore +59 -0
  4. data/.gitmodules +3 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +21 -0
  7. data/README.md +106 -0
  8. data/Rakefile +39 -0
  9. data/TODO.md +4 -0
  10. data/examples/echo_server.rb +52 -0
  11. data/examples/event_loop.rb +69 -0
  12. data/examples/http_server.rb +56 -0
  13. data/examples/http_server_multishot.rb +59 -0
  14. data/ext/iou/extconf.rb +71 -0
  15. data/ext/iou/iou.c +729 -0
  16. data/ext/iou/iou.h +66 -0
  17. data/ext/iou/iou_ext.c +9 -0
  18. data/ext/iou/op_spec_data.c +61 -0
  19. data/iou.gemspec +27 -0
  20. data/lib/iou/version.rb +5 -0
  21. data/lib/iou.rb +3 -0
  22. data/test/helper.rb +59 -0
  23. data/test/test_iou.rb +794 -0
  24. data/vendor/liburing/.github/actions/codespell/stopwords +7 -0
  25. data/vendor/liburing/.github/pull_request_template.md +86 -0
  26. data/vendor/liburing/.github/workflows/build.yml +137 -0
  27. data/vendor/liburing/.github/workflows/codespell.yml +25 -0
  28. data/vendor/liburing/.github/workflows/shellcheck.yml +20 -0
  29. data/vendor/liburing/.gitignore +41 -0
  30. data/vendor/liburing/CHANGELOG +111 -0
  31. data/vendor/liburing/CITATION.cff +11 -0
  32. data/vendor/liburing/COPYING +502 -0
  33. data/vendor/liburing/COPYING.GPL +339 -0
  34. data/vendor/liburing/LICENSE +20 -0
  35. data/vendor/liburing/Makefile +96 -0
  36. data/vendor/liburing/Makefile.common +7 -0
  37. data/vendor/liburing/Makefile.quiet +11 -0
  38. data/vendor/liburing/README +106 -0
  39. data/vendor/liburing/SECURITY.md +6 -0
  40. data/vendor/liburing/configure +624 -0
  41. data/vendor/liburing/debian/README.Debian +7 -0
  42. data/vendor/liburing/debian/changelog +38 -0
  43. data/vendor/liburing/debian/control +39 -0
  44. data/vendor/liburing/debian/copyright +49 -0
  45. data/vendor/liburing/debian/liburing-dev.install +4 -0
  46. data/vendor/liburing/debian/liburing-dev.manpages +5 -0
  47. data/vendor/liburing/debian/liburing2.install +1 -0
  48. data/vendor/liburing/debian/liburing2.symbols +56 -0
  49. data/vendor/liburing/debian/patches/series +1 -0
  50. data/vendor/liburing/debian/rules +29 -0
  51. data/vendor/liburing/debian/source/format +1 -0
  52. data/vendor/liburing/debian/source/local-options +2 -0
  53. data/vendor/liburing/debian/source/options +1 -0
  54. data/vendor/liburing/debian/watch +3 -0
  55. data/vendor/liburing/examples/Makefile +53 -0
  56. data/vendor/liburing/examples/helpers.c +62 -0
  57. data/vendor/liburing/examples/helpers.h +7 -0
  58. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  59. data/vendor/liburing/examples/io_uring-cp.c +282 -0
  60. data/vendor/liburing/examples/io_uring-test.c +112 -0
  61. data/vendor/liburing/examples/io_uring-udp.c +403 -0
  62. data/vendor/liburing/examples/link-cp.c +193 -0
  63. data/vendor/liburing/examples/napi-busy-poll-client.c +509 -0
  64. data/vendor/liburing/examples/napi-busy-poll-server.c +450 -0
  65. data/vendor/liburing/examples/poll-bench.c +101 -0
  66. data/vendor/liburing/examples/proxy.c +2461 -0
  67. data/vendor/liburing/examples/proxy.h +102 -0
  68. data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
  69. data/vendor/liburing/examples/send-zerocopy.c +658 -0
  70. data/vendor/liburing/examples/ucontext-cp.c +258 -0
  71. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  72. data/vendor/liburing/liburing.pc.in +12 -0
  73. data/vendor/liburing/liburing.spec +66 -0
  74. data/vendor/liburing/make-debs.sh +55 -0
  75. data/vendor/liburing/src/Makefile +129 -0
  76. data/vendor/liburing/src/arch/aarch64/lib.h +47 -0
  77. data/vendor/liburing/src/arch/aarch64/syscall.h +91 -0
  78. data/vendor/liburing/src/arch/generic/lib.h +17 -0
  79. data/vendor/liburing/src/arch/generic/syscall.h +100 -0
  80. data/vendor/liburing/src/arch/riscv64/lib.h +48 -0
  81. data/vendor/liburing/src/arch/riscv64/syscall.h +100 -0
  82. data/vendor/liburing/src/arch/syscall-defs.h +94 -0
  83. data/vendor/liburing/src/arch/x86/lib.h +11 -0
  84. data/vendor/liburing/src/arch/x86/syscall.h +296 -0
  85. data/vendor/liburing/src/ffi.c +15 -0
  86. data/vendor/liburing/src/include/liburing/barrier.h +81 -0
  87. data/vendor/liburing/src/include/liburing/io_uring.h +818 -0
  88. data/vendor/liburing/src/include/liburing.h +1602 -0
  89. data/vendor/liburing/src/int_flags.h +11 -0
  90. data/vendor/liburing/src/lib.h +52 -0
  91. data/vendor/liburing/src/liburing-ffi.map +211 -0
  92. data/vendor/liburing/src/liburing.map +104 -0
  93. data/vendor/liburing/src/nolibc.c +55 -0
  94. data/vendor/liburing/src/queue.c +468 -0
  95. data/vendor/liburing/src/register.c +374 -0
  96. data/vendor/liburing/src/setup.c +689 -0
  97. data/vendor/liburing/src/setup.h +9 -0
  98. data/vendor/liburing/src/syscall.c +29 -0
  99. data/vendor/liburing/src/syscall.h +53 -0
  100. data/vendor/liburing/src/version.c +21 -0
  101. data/vendor/liburing/test/232c93d07b74.c +305 -0
  102. data/vendor/liburing/test/35fa71a030ca.c +329 -0
  103. data/vendor/liburing/test/500f9fbadef8.c +91 -0
  104. data/vendor/liburing/test/7ad0e4b2f83c.c +94 -0
  105. data/vendor/liburing/test/8a9973408177.c +107 -0
  106. data/vendor/liburing/test/917257daa0fe.c +54 -0
  107. data/vendor/liburing/test/Makefile +297 -0
  108. data/vendor/liburing/test/a0908ae19763.c +59 -0
  109. data/vendor/liburing/test/a4c0b3decb33.c +181 -0
  110. data/vendor/liburing/test/accept-link.c +255 -0
  111. data/vendor/liburing/test/accept-non-empty.c +256 -0
  112. data/vendor/liburing/test/accept-reuse.c +163 -0
  113. data/vendor/liburing/test/accept-test.c +83 -0
  114. data/vendor/liburing/test/accept.c +919 -0
  115. data/vendor/liburing/test/across-fork.c +284 -0
  116. data/vendor/liburing/test/b19062a56726.c +54 -0
  117. data/vendor/liburing/test/b5837bd5311d.c +78 -0
  118. data/vendor/liburing/test/bind-listen.c +408 -0
  119. data/vendor/liburing/test/buf-ring-nommap.c +123 -0
  120. data/vendor/liburing/test/buf-ring-put.c +83 -0
  121. data/vendor/liburing/test/buf-ring.c +473 -0
  122. data/vendor/liburing/test/ce593a6c480a.c +139 -0
  123. data/vendor/liburing/test/close-opath.c +123 -0
  124. data/vendor/liburing/test/config +14 -0
  125. data/vendor/liburing/test/connect-rep.c +204 -0
  126. data/vendor/liburing/test/connect.c +442 -0
  127. data/vendor/liburing/test/coredump.c +60 -0
  128. data/vendor/liburing/test/cq-full.c +97 -0
  129. data/vendor/liburing/test/cq-overflow.c +530 -0
  130. data/vendor/liburing/test/cq-peek-batch.c +103 -0
  131. data/vendor/liburing/test/cq-ready.c +95 -0
  132. data/vendor/liburing/test/cq-size.c +65 -0
  133. data/vendor/liburing/test/d4ae271dfaae.c +96 -0
  134. data/vendor/liburing/test/d77a67ed5f27.c +65 -0
  135. data/vendor/liburing/test/defer-taskrun.c +391 -0
  136. data/vendor/liburing/test/defer-tw-timeout.c +173 -0
  137. data/vendor/liburing/test/defer.c +319 -0
  138. data/vendor/liburing/test/double-poll-crash.c +195 -0
  139. data/vendor/liburing/test/drop-submit.c +94 -0
  140. data/vendor/liburing/test/eeed8b54e0df.c +120 -0
  141. data/vendor/liburing/test/empty-eownerdead.c +45 -0
  142. data/vendor/liburing/test/eploop.c +74 -0
  143. data/vendor/liburing/test/eventfd-disable.c +179 -0
  144. data/vendor/liburing/test/eventfd-reg.c +77 -0
  145. data/vendor/liburing/test/eventfd-ring.c +98 -0
  146. data/vendor/liburing/test/eventfd.c +113 -0
  147. data/vendor/liburing/test/evloop.c +73 -0
  148. data/vendor/liburing/test/exec-target.c +6 -0
  149. data/vendor/liburing/test/exit-no-cleanup.c +117 -0
  150. data/vendor/liburing/test/fadvise.c +202 -0
  151. data/vendor/liburing/test/fallocate.c +265 -0
  152. data/vendor/liburing/test/fc2a85cb02ef.c +132 -0
  153. data/vendor/liburing/test/fd-install.c +500 -0
  154. data/vendor/liburing/test/fd-pass.c +237 -0
  155. data/vendor/liburing/test/fdinfo.c +419 -0
  156. data/vendor/liburing/test/file-register.c +1189 -0
  157. data/vendor/liburing/test/file-update.c +231 -0
  158. data/vendor/liburing/test/file-verify.c +654 -0
  159. data/vendor/liburing/test/files-exit-hang-poll.c +114 -0
  160. data/vendor/liburing/test/files-exit-hang-timeout.c +137 -0
  161. data/vendor/liburing/test/fixed-buf-iter.c +115 -0
  162. data/vendor/liburing/test/fixed-buf-merge.c +101 -0
  163. data/vendor/liburing/test/fixed-hugepage.c +411 -0
  164. data/vendor/liburing/test/fixed-link.c +90 -0
  165. data/vendor/liburing/test/fixed-reuse.c +160 -0
  166. data/vendor/liburing/test/fpos.c +255 -0
  167. data/vendor/liburing/test/fsnotify.c +118 -0
  168. data/vendor/liburing/test/fsync.c +224 -0
  169. data/vendor/liburing/test/futex.c +571 -0
  170. data/vendor/liburing/test/hardlink.c +170 -0
  171. data/vendor/liburing/test/helpers.c +318 -0
  172. data/vendor/liburing/test/helpers.h +108 -0
  173. data/vendor/liburing/test/ignore-single-mmap.c +48 -0
  174. data/vendor/liburing/test/init-mem.c +164 -0
  175. data/vendor/liburing/test/io-cancel.c +561 -0
  176. data/vendor/liburing/test/io_uring_enter.c +264 -0
  177. data/vendor/liburing/test/io_uring_passthrough.c +482 -0
  178. data/vendor/liburing/test/io_uring_register.c +503 -0
  179. data/vendor/liburing/test/io_uring_setup.c +110 -0
  180. data/vendor/liburing/test/iopoll-leak.c +85 -0
  181. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  182. data/vendor/liburing/test/iopoll.c +465 -0
  183. data/vendor/liburing/test/lfs-openat-write.c +119 -0
  184. data/vendor/liburing/test/lfs-openat.c +273 -0
  185. data/vendor/liburing/test/link-timeout.c +1108 -0
  186. data/vendor/liburing/test/link.c +497 -0
  187. data/vendor/liburing/test/link_drain.c +255 -0
  188. data/vendor/liburing/test/madvise.c +195 -0
  189. data/vendor/liburing/test/min-timeout-wait.c +354 -0
  190. data/vendor/liburing/test/min-timeout.c +233 -0
  191. data/vendor/liburing/test/mkdir.c +112 -0
  192. data/vendor/liburing/test/msg-ring-fd.c +331 -0
  193. data/vendor/liburing/test/msg-ring-flags.c +212 -0
  194. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  195. data/vendor/liburing/test/msg-ring.c +467 -0
  196. data/vendor/liburing/test/multicqes_drain.c +429 -0
  197. data/vendor/liburing/test/napi-test.c +215 -0
  198. data/vendor/liburing/test/napi-test.sh +48 -0
  199. data/vendor/liburing/test/no-mmap-inval.c +42 -0
  200. data/vendor/liburing/test/nolibc.c +62 -0
  201. data/vendor/liburing/test/nop-all-sizes.c +99 -0
  202. data/vendor/liburing/test/nop.c +177 -0
  203. data/vendor/liburing/test/nvme.h +169 -0
  204. data/vendor/liburing/test/ooo-file-unreg.c +82 -0
  205. data/vendor/liburing/test/open-close.c +261 -0
  206. data/vendor/liburing/test/open-direct-link.c +188 -0
  207. data/vendor/liburing/test/open-direct-pick.c +180 -0
  208. data/vendor/liburing/test/openat2.c +312 -0
  209. data/vendor/liburing/test/personality.c +204 -0
  210. data/vendor/liburing/test/pipe-bug.c +95 -0
  211. data/vendor/liburing/test/pipe-eof.c +83 -0
  212. data/vendor/liburing/test/pipe-reuse.c +105 -0
  213. data/vendor/liburing/test/poll-cancel-all.c +496 -0
  214. data/vendor/liburing/test/poll-cancel-ton.c +135 -0
  215. data/vendor/liburing/test/poll-cancel.c +228 -0
  216. data/vendor/liburing/test/poll-link.c +221 -0
  217. data/vendor/liburing/test/poll-many.c +230 -0
  218. data/vendor/liburing/test/poll-mshot-overflow.c +265 -0
  219. data/vendor/liburing/test/poll-mshot-update.c +323 -0
  220. data/vendor/liburing/test/poll-race-mshot.c +276 -0
  221. data/vendor/liburing/test/poll-race.c +105 -0
  222. data/vendor/liburing/test/poll-ring.c +48 -0
  223. data/vendor/liburing/test/poll-v-poll.c +353 -0
  224. data/vendor/liburing/test/poll.c +327 -0
  225. data/vendor/liburing/test/probe.c +135 -0
  226. data/vendor/liburing/test/read-before-exit.c +129 -0
  227. data/vendor/liburing/test/read-mshot-empty.c +153 -0
  228. data/vendor/liburing/test/read-mshot.c +404 -0
  229. data/vendor/liburing/test/read-write.c +1013 -0
  230. data/vendor/liburing/test/recv-msgall-stream.c +398 -0
  231. data/vendor/liburing/test/recv-msgall.c +263 -0
  232. data/vendor/liburing/test/recv-multishot.c +602 -0
  233. data/vendor/liburing/test/recvsend_bundle.c +691 -0
  234. data/vendor/liburing/test/reg-fd-only.c +131 -0
  235. data/vendor/liburing/test/reg-hint.c +56 -0
  236. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  237. data/vendor/liburing/test/regbuf-merge.c +91 -0
  238. data/vendor/liburing/test/register-restrictions.c +633 -0
  239. data/vendor/liburing/test/rename.c +132 -0
  240. data/vendor/liburing/test/ring-leak.c +283 -0
  241. data/vendor/liburing/test/ring-leak2.c +249 -0
  242. data/vendor/liburing/test/ringbuf-read.c +196 -0
  243. data/vendor/liburing/test/ringbuf-status.c +242 -0
  244. data/vendor/liburing/test/rsrc_tags.c +461 -0
  245. data/vendor/liburing/test/runtests-loop.sh +16 -0
  246. data/vendor/liburing/test/runtests-quiet.sh +11 -0
  247. data/vendor/liburing/test/runtests.sh +168 -0
  248. data/vendor/liburing/test/rw_merge_test.c +98 -0
  249. data/vendor/liburing/test/self.c +91 -0
  250. data/vendor/liburing/test/send-zerocopy.c +971 -0
  251. data/vendor/liburing/test/send_recv.c +412 -0
  252. data/vendor/liburing/test/send_recvmsg.c +444 -0
  253. data/vendor/liburing/test/shared-wq.c +84 -0
  254. data/vendor/liburing/test/short-read.c +75 -0
  255. data/vendor/liburing/test/shutdown.c +165 -0
  256. data/vendor/liburing/test/sigfd-deadlock.c +88 -0
  257. data/vendor/liburing/test/single-issuer.c +169 -0
  258. data/vendor/liburing/test/skip-cqe.c +428 -0
  259. data/vendor/liburing/test/socket-getsetsock-cmd.c +346 -0
  260. data/vendor/liburing/test/socket-io-cmd.c +237 -0
  261. data/vendor/liburing/test/socket-rw-eagain.c +149 -0
  262. data/vendor/liburing/test/socket-rw-offset.c +149 -0
  263. data/vendor/liburing/test/socket-rw.c +137 -0
  264. data/vendor/liburing/test/socket.c +408 -0
  265. data/vendor/liburing/test/splice.c +512 -0
  266. data/vendor/liburing/test/sq-full-cpp.cc +45 -0
  267. data/vendor/liburing/test/sq-full.c +45 -0
  268. data/vendor/liburing/test/sq-poll-dup.c +211 -0
  269. data/vendor/liburing/test/sq-poll-kthread.c +169 -0
  270. data/vendor/liburing/test/sq-poll-share.c +138 -0
  271. data/vendor/liburing/test/sq-space_left.c +159 -0
  272. data/vendor/liburing/test/sqpoll-disable-exit.c +196 -0
  273. data/vendor/liburing/test/sqpoll-exec.c +132 -0
  274. data/vendor/liburing/test/sqpoll-exit-hang.c +78 -0
  275. data/vendor/liburing/test/sqpoll-sleep.c +69 -0
  276. data/vendor/liburing/test/statx.c +172 -0
  277. data/vendor/liburing/test/stdout.c +232 -0
  278. data/vendor/liburing/test/submit-and-wait.c +108 -0
  279. data/vendor/liburing/test/submit-link-fail.c +156 -0
  280. data/vendor/liburing/test/submit-reuse.c +237 -0
  281. data/vendor/liburing/test/symlink.c +117 -0
  282. data/vendor/liburing/test/sync-cancel.c +235 -0
  283. data/vendor/liburing/test/teardowns.c +58 -0
  284. data/vendor/liburing/test/test.h +36 -0
  285. data/vendor/liburing/test/thread-exit.c +143 -0
  286. data/vendor/liburing/test/timeout-new.c +256 -0
  287. data/vendor/liburing/test/timeout.c +1798 -0
  288. data/vendor/liburing/test/truncate.c +186 -0
  289. data/vendor/liburing/test/tty-write-dpoll.c +60 -0
  290. data/vendor/liburing/test/unlink.c +112 -0
  291. data/vendor/liburing/test/version.c +25 -0
  292. data/vendor/liburing/test/wait-timeout.c +287 -0
  293. data/vendor/liburing/test/waitid.c +373 -0
  294. data/vendor/liburing/test/wakeup-hang.c +162 -0
  295. data/vendor/liburing/test/wq-aff.c +146 -0
  296. data/vendor/liburing/test/xattr.c +442 -0
  297. metadata +402 -0
data/test/test_iou.rb ADDED
@@ -0,0 +1,794 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+ require 'socket'
5
+
6
+ class IOURingTest < IOURingBaseTest
7
+ def test_close
8
+ ring2 = IOU::Ring.new
9
+ refute ring2.closed?
10
+
11
+ ring2.close
12
+ assert ring2.closed?
13
+ end
14
+
15
+ def test_pending_ops
16
+ assert_equal({}, ring.pending_ops)
17
+
18
+ id = ring.prep_timeout(interval: 1)
19
+ spec = ring.pending_ops[id]
20
+ assert_equal id, spec[:id]
21
+ assert_equal :timeout, spec[:op]
22
+ assert_equal 1, spec[:interval]
23
+
24
+ ring.prep_cancel(id)
25
+ ring.submit
26
+ ring.process_completions(true)
27
+
28
+ assert_nil ring.pending_ops[id]
29
+ end
30
+ end
31
+
32
+ class PrepTimeoutTest < IOURingBaseTest
33
+ def test_prep_timeout
34
+ interval = 0.03
35
+
36
+ t0 = monotonic_clock
37
+ id = ring.prep_timeout(interval: interval)
38
+ assert_equal 1, id
39
+
40
+ ring.submit
41
+ c = ring.wait_for_completion
42
+ elapsed = monotonic_clock - t0
43
+ assert_in_range interval..(interval + 0.02), elapsed
44
+
45
+ assert_kind_of Hash, c
46
+ assert_equal id, c[:id]
47
+ assert_equal :timeout, c[:op]
48
+ assert_equal interval, c[:interval]
49
+ assert_equal -Errno::ETIME::Errno, c[:result]
50
+ end
51
+
52
+ def test_prep_timeout_invalid_args
53
+ assert_raises(ArgumentError) { ring.prep_timeout() }
54
+ assert_raises(ArgumentError) { ring.prep_timeout(foo: 1) }
55
+ assert_raises(ArgumentError) { ring.prep_timeout(1) }
56
+ end
57
+ end
58
+
59
+ class PrepCancelTest < IOURingBaseTest
60
+ def test_prep_cancel
61
+ interval = 15
62
+ timeout_id = ring.prep_timeout(interval: interval)
63
+ assert_equal 1, timeout_id
64
+
65
+ cancel_id = ring.prep_cancel(timeout_id)
66
+ assert_equal 2, cancel_id
67
+
68
+ ring.submit
69
+ c = ring.wait_for_completion
70
+ assert_equal cancel_id, c[:id]
71
+ assert_equal 0, c[:result]
72
+
73
+ c = ring.wait_for_completion
74
+ assert_equal timeout_id, c[:id]
75
+ assert_equal :timeout, c[:op]
76
+ assert_equal interval, c[:interval]
77
+ assert_equal -Errno::ECANCELED::Errno, c[:result]
78
+ end
79
+
80
+ def test_prep_cancel_kw
81
+ interval = 15
82
+ timeout_id = ring.prep_timeout(interval: interval)
83
+ assert_equal 1, timeout_id
84
+
85
+ cancel_id = ring.prep_cancel(id: timeout_id)
86
+ assert_equal 2, cancel_id
87
+
88
+ ring.submit
89
+ c = ring.wait_for_completion
90
+ assert_equal cancel_id, c[:id]
91
+ assert_equal 0, c[:result]
92
+
93
+ c = ring.wait_for_completion
94
+ assert_equal timeout_id, c[:id]
95
+ assert_equal :timeout, c[:op]
96
+ assert_equal interval, c[:interval]
97
+ assert_equal -Errno::ECANCELED::Errno, c[:result]
98
+ end
99
+
100
+ def test_prep_cancel_invalid_args
101
+ assert_raises(ArgumentError) { ring.prep_cancel() }
102
+ assert_raises(ArgumentError) { ring.prep_cancel('foo') }
103
+ assert_raises(ArgumentError) { ring.prep_cancel({}) }
104
+ assert_raises(TypeError) { ring.prep_cancel(id: 'bar') }
105
+ end
106
+
107
+ def test_prep_cancel_invalid_id
108
+ cancel_id = ring.prep_cancel(id: 42)
109
+ assert_equal 1, cancel_id
110
+
111
+ ring.submit
112
+ c = ring.wait_for_completion
113
+ assert_equal cancel_id, c[:id]
114
+ assert_equal -Errno::ENOENT::Errno, c[:result]
115
+ end
116
+ end
117
+
118
+ class PrepTimeoutMultishotTest < IOURingBaseTest
119
+ def test_prep_timeout_multishot
120
+ interval = 0.03
121
+ count = 0
122
+ cancelled = false
123
+
124
+ t0 = monotonic_clock
125
+ id = ring.prep_timeout(interval: interval, multishot: true) do |c|
126
+ case c[:result]
127
+ when -Errno::ETIME::Errno
128
+ count += 1
129
+ when -Errno::ECANCELED::Errno
130
+ cancelled = true
131
+ end
132
+ end
133
+ ring.submit
134
+
135
+ ring.process_completions(true)
136
+ elapsed = monotonic_clock - t0
137
+ assert_in_range interval..(interval + 0.02), elapsed
138
+ assert_equal 1, count
139
+
140
+ t0 = monotonic_clock
141
+ ring.process_completions(true)
142
+ elapsed = monotonic_clock - t0
143
+ assert_in_range (interval - 0.01)..(interval + 0.02), elapsed
144
+ assert_equal 2, count
145
+
146
+ t0 = monotonic_clock
147
+ ring.process_completions(true)
148
+ elapsed = monotonic_clock - t0
149
+ assert_in_range (interval - 0.01)..(interval + 0.02), elapsed
150
+ assert_equal 3, count
151
+
152
+ ring.prep_cancel(id)
153
+ ring.submit
154
+ c = ring.process_completions(true)
155
+ assert_equal true, cancelled
156
+ assert_equal 3, count
157
+ assert_nil ring.pending_ops[id]
158
+ end
159
+ end
160
+
161
+ class PrepWriteTest < IOURingBaseTest
162
+ def test_prep_write
163
+ r, w = IO.pipe
164
+ s = 'foobar'
165
+
166
+ id = ring.prep_write(fd: w.fileno, buffer: s)
167
+ assert_equal 1, id
168
+
169
+ ring.submit
170
+ c = ring.wait_for_completion
171
+
172
+ assert_kind_of Hash, c
173
+ assert_equal id, c[:id]
174
+ assert_equal :write, c[:op]
175
+ assert_equal w.fileno, c[:fd]
176
+ assert_equal s.bytesize, c[:result]
177
+
178
+ w.close
179
+ assert_equal s, r.read
180
+ end
181
+
182
+ def test_prep_write_with_len
183
+ r, w = IO.pipe
184
+ s = 'foobar'
185
+
186
+ id = ring.prep_write(fd: w.fileno, buffer: s, len: 3)
187
+ assert_equal 1, id
188
+
189
+ ring.submit
190
+ c = ring.wait_for_completion
191
+
192
+ assert_kind_of Hash, c
193
+ assert_equal id, c[:id]
194
+ assert_equal :write, c[:op]
195
+ assert_equal w.fileno, c[:fd]
196
+ assert_equal 3, c[:result]
197
+
198
+ w.close
199
+ assert_equal s[0..2], r.read
200
+ end
201
+
202
+ def test_prep_write_invalid_args
203
+ assert_raises(ArgumentError) { ring.prep_write() }
204
+ assert_raises(ArgumentError) { ring.prep_write(foo: 1) }
205
+ assert_raises(ArgumentError) { ring.prep_write(fd: 'bar') }
206
+ assert_raises(ArgumentError) { ring.prep_write({}) }
207
+ end
208
+
209
+ def test_prep_write_invalid_fd
210
+ r, w = IO.pipe
211
+ s = 'foobar'
212
+
213
+ id = ring.prep_write(fd: r.fileno, buffer: s)
214
+ assert_equal 1, id
215
+
216
+ ring.submit
217
+ c = ring.wait_for_completion
218
+
219
+ assert_kind_of Hash, c
220
+ assert_equal id, c[:id]
221
+ assert_equal :write, c[:op]
222
+ assert_equal r.fileno, c[:fd]
223
+ assert_equal -Errno::EBADF::Errno, c[:result]
224
+ end
225
+ end
226
+
227
+ class PrepNopTest < IOURingBaseTest
228
+ def test_prep_nop
229
+ id = ring.prep_nop
230
+ assert_equal 1, id
231
+
232
+ ring.submit
233
+ c = ring.wait_for_completion
234
+
235
+ assert_kind_of Hash, c
236
+ assert_equal id, c[:id]
237
+ assert_nil c[:op]
238
+ assert_equal 0, c[:result]
239
+ end
240
+
241
+ def test_nop_as_signal
242
+ s1 = Queue.new
243
+ s2 = Queue.new
244
+ s3 = Queue.new
245
+ s4 = Queue.new
246
+
247
+ signaller = Thread.new do
248
+ s1.pop
249
+ id = ring.prep_nop
250
+ ring.submit
251
+ s2 << id
252
+ end
253
+
254
+ waiter = Thread.new do
255
+ s3.pop
256
+ s4 << ring.wait_for_completion
257
+ end
258
+
259
+ s3 << 'go'
260
+ s1 << 'go'
261
+ id = s2.pop
262
+ c = s4.pop
263
+
264
+ assert_kind_of Hash, c
265
+ assert_equal id, c[:id]
266
+ assert_nil c[:op]
267
+ assert_equal 0, c[:result]
268
+ ensure
269
+ signaller.kill rescue nil
270
+ end
271
+ end
272
+
273
+ class ProcessCompletionsTest < IOURingBaseTest
274
+ def test_process_completions_no_wait
275
+ ret = ring.process_completions
276
+ assert_equal 0, ret
277
+
278
+ (1..3).each do |i|
279
+ id = ring.prep_nop
280
+ assert_equal i, id
281
+ end
282
+
283
+ ring.submit
284
+ sleep 0.001
285
+
286
+ ret = ring.process_completions
287
+ assert_equal 3, ret
288
+ end
289
+
290
+ def test_process_completions_wait
291
+ (1..3).each do |i|
292
+ id = ring.prep_nop
293
+ assert_equal i, id
294
+ end
295
+
296
+ ring.submit
297
+ ret = ring.process_completions(true)
298
+ assert_equal 3, ret
299
+ end
300
+
301
+ def test_process_completions_with_block
302
+ r, w = IO.pipe
303
+
304
+ id1 = ring.prep_write(fd: w.fileno, buffer: 'foo')
305
+ id2 = ring.prep_write(fd: w.fileno, buffer: 'bar')
306
+ id3 = ring.prep_write(fd: w.fileno, buffer: 'baz')
307
+ ring.submit
308
+ sleep 0.01
309
+
310
+ completions = []
311
+
312
+ ret = ring.process_completions do |c|
313
+ completions << c
314
+ end
315
+
316
+ assert_equal 3, ret
317
+ assert_equal 3, completions.size
318
+ assert_equal [1, 2, 3], completions.map { _1[:id] }
319
+ assert_equal [:write], completions.map { _1[:op] }.uniq
320
+ assert_equal 9, completions.inject(0) { |t, c| t + c[:result] }
321
+
322
+ w.close
323
+ assert_equal 'foobarbaz', r.read
324
+ end
325
+
326
+ def test_process_completions_op_with_block
327
+ cc = []
328
+
329
+ id1 = ring.prep_timeout(interval: 0.01) { cc << 1 }
330
+ id2 = ring.prep_timeout(interval: 0.02) { cc << 2 }
331
+ ring.submit
332
+
333
+ ret = ring.process_completions
334
+ assert_equal 0, ret
335
+ assert_equal [], cc
336
+
337
+ sleep 0.02
338
+ ret = ring.process_completions(true)
339
+
340
+ assert_equal 2, ret
341
+ assert_equal [1, 2], cc
342
+ end
343
+
344
+ def test_process_completions_op_with_block_no_submit
345
+ cc = []
346
+
347
+ id1 = ring.prep_timeout(interval: 0.01) { cc << 1 }
348
+ id2 = ring.prep_timeout(interval: 0.02) { cc << 2 }
349
+
350
+ ret = ring.process_completions
351
+ assert_equal 0, ret
352
+ assert_equal [], cc
353
+
354
+ sleep 0.02
355
+ ret = ring.process_completions(true)
356
+ assert_equal 2, ret
357
+ assert_equal [1, 2], cc
358
+ end
359
+ end
360
+
361
+ class PrepReadTest < IOURingBaseTest
362
+ def test_prep_read
363
+ r, w = IO.pipe
364
+ s = 'foobar'
365
+
366
+ id = ring.prep_read(fd: r.fileno, buffer: +'', len: 8192)
367
+ assert_equal 1, id
368
+ ring.submit
369
+
370
+ w << s
371
+
372
+ c = ring.wait_for_completion
373
+
374
+ assert_kind_of Hash, c
375
+ assert_equal id, c[:id]
376
+ assert_equal :read, c[:op]
377
+ assert_equal r.fileno, c[:fd]
378
+ assert_equal s.bytesize, c[:result]
379
+ assert_equal s, c[:buffer]
380
+ end
381
+
382
+ def test_prep_read_empty
383
+ r, w = IO.pipe
384
+
385
+ id = ring.prep_read(fd: r.fileno, buffer: +'', len: 8192)
386
+ assert_equal 1, id
387
+ ring.submit
388
+
389
+ w.close
390
+
391
+ c = ring.wait_for_completion
392
+
393
+ assert_kind_of Hash, c
394
+ assert_equal id, c[:id]
395
+ assert_equal :read, c[:op]
396
+ assert_equal r.fileno, c[:fd]
397
+ assert_equal 0, c[:result]
398
+ assert_equal '', c[:buffer]
399
+ end
400
+
401
+ def test_prep_read_invalid_args
402
+ assert_raises(ArgumentError) { ring.prep_read() }
403
+ assert_raises(ArgumentError) { ring.prep_read(foo: 1) }
404
+ assert_raises(ArgumentError) { ring.prep_read(fd: 'bar', buffer: +'') }
405
+ assert_raises(ArgumentError) { ring.prep_read({}) }
406
+ end
407
+
408
+ def test_prep_read_bad_fd
409
+ r, w = IO.pipe
410
+
411
+ id = ring.prep_read(fd: w.fileno, buffer: +'', len: 8192)
412
+ assert_equal 1, id
413
+
414
+ ring.submit
415
+ c = ring.wait_for_completion
416
+
417
+ assert_kind_of Hash, c
418
+ assert_equal id, c[:id]
419
+ assert_equal :read, c[:op]
420
+ assert_equal w.fileno, c[:fd]
421
+ assert_equal -Errno::EBADF::Errno, c[:result]
422
+ end
423
+
424
+ def test_prep_read_with_block
425
+ r, w = IO.pipe
426
+ w << 'foobar'
427
+
428
+ cc = nil
429
+ id = ring.prep_read(fd: r.fileno, buffer: +'', len: 3) do |c|
430
+ cc = c
431
+ end
432
+
433
+ ring.submit
434
+ ring.process_completions
435
+
436
+ assert_kind_of Hash, cc
437
+ assert_equal id, cc[:id]
438
+ assert_equal :read, cc[:op]
439
+ assert_equal r.fileno, cc[:fd]
440
+ assert_equal 3, cc[:result]
441
+ assert_equal 'foo', cc[:buffer]
442
+
443
+ id = ring.prep_read(fd: r.fileno, buffer: +'', len: 5) do |c|
444
+ cc = c
445
+ end
446
+ assert_equal 'foo', cc[:buffer]
447
+
448
+ ring.submit
449
+ ring.process_completions
450
+
451
+ assert_kind_of Hash, cc
452
+ assert_equal id, cc[:id]
453
+ assert_equal :read, cc[:op]
454
+ assert_equal r.fileno, cc[:fd]
455
+ assert_equal 3, cc[:result]
456
+ assert_equal 'bar', cc[:buffer]
457
+ end
458
+
459
+ def test_prep_read_with_buffer_offset
460
+ buffer = +'foo'
461
+
462
+ r, w = IO.pipe
463
+ w << 'bar'
464
+
465
+ id = ring.prep_read(fd: r.fileno, buffer: buffer, len: 100, buffer_offset: buffer.bytesize)
466
+ ring.submit
467
+ cc = ring.wait_for_completion
468
+
469
+ assert_kind_of Hash, cc
470
+ assert_equal id, cc[:id]
471
+ assert_equal :read, cc[:op]
472
+ assert_equal r.fileno, cc[:fd]
473
+ assert_equal 3, cc[:result]
474
+ assert_equal 'foobar', buffer
475
+ end
476
+
477
+ def test_prep_read_with_negative_buffer_offset
478
+ buffer = +'foo'
479
+
480
+ r, w = IO.pipe
481
+ w << 'bar'
482
+
483
+ id = ring.prep_read(fd: r.fileno, buffer: buffer, len: 100, buffer_offset: -1)
484
+ ring.submit
485
+ cc = ring.wait_for_completion
486
+
487
+ assert_kind_of Hash, cc
488
+ assert_equal id, cc[:id]
489
+ assert_equal :read, cc[:op]
490
+ assert_equal r.fileno, cc[:fd]
491
+ assert_equal 3, cc[:result]
492
+ assert_equal 'foobar', buffer
493
+
494
+
495
+
496
+ buffer = +'foogrr'
497
+
498
+ r, w = IO.pipe
499
+ w << 'bar'
500
+
501
+ id = ring.prep_read(fd: r.fileno, buffer: buffer, len: 100, buffer_offset: -4)
502
+ ring.submit
503
+ cc = ring.wait_for_completion
504
+
505
+ assert_kind_of Hash, cc
506
+ assert_equal id, cc[:id]
507
+ assert_equal :read, cc[:op]
508
+ assert_equal r.fileno, cc[:fd]
509
+ assert_equal 3, cc[:result]
510
+ assert_equal 'foobar', buffer
511
+ end
512
+ end
513
+
514
+ class PrepCloseTest < IOURingBaseTest
515
+ def test_prep_close
516
+ r, w = IO.pipe
517
+ fd = w.fileno
518
+
519
+ id = ring.prep_close(fd: fd)
520
+ assert_equal 1, id
521
+ ring.submit
522
+
523
+ c = ring.wait_for_completion
524
+ assert_kind_of Hash, c
525
+ assert_equal id, c[:id]
526
+ assert_equal :close, c[:op]
527
+ assert_equal fd, c[:fd]
528
+ assert_equal 0, c[:result]
529
+
530
+ assert_raises(Errno::EBADF) { w << 'fail' }
531
+
532
+ id = ring.prep_close(fd: fd)
533
+ assert_equal 2, id
534
+ ring.submit
535
+
536
+ c = ring.wait_for_completion
537
+ assert_kind_of Hash, c
538
+ assert_equal id, c[:id]
539
+ assert_equal :close, c[:op]
540
+ assert_equal fd, c[:fd]
541
+ assert_equal -Errno::EBADF::Errno, c[:result]
542
+
543
+ end
544
+
545
+ def test_prep_close_invalid_args
546
+ assert_raises(ArgumentError) { ring.prep_close() }
547
+ assert_raises(ArgumentError) { ring.prep_close({}) }
548
+ assert_raises(ArgumentError) { ring.prep_close(foo: 1) }
549
+ assert_raises(TypeError) { ring.prep_close(fd: 'bar') }
550
+ end
551
+
552
+ def test_prep_close_invalid_fd
553
+ id = ring.prep_close(fd: 9999)
554
+ assert_equal 1, id
555
+
556
+ ring.submit
557
+ c = ring.wait_for_completion
558
+
559
+ assert_kind_of Hash, c
560
+ assert_equal id, c[:id]
561
+ assert_equal :close, c[:op]
562
+ assert_equal 9999, c[:fd]
563
+ assert_equal -Errno::EBADF::Errno, c[:result]
564
+ end
565
+ end
566
+
567
+ class PrepAcceptTest < IOURingBaseTest
568
+ def setup
569
+ super
570
+ @port = 9000 + rand(1000)
571
+ @server = TCPServer.open('127.0.0.1', @port)
572
+ end
573
+
574
+ def teardown
575
+ @server.close
576
+ super
577
+ end
578
+
579
+ def test_prep_accept
580
+ id = ring.prep_accept(fd: @server.fileno)
581
+ ring.submit
582
+
583
+ t = Thread.new do
584
+ client = TCPSocket.new('127.0.0.1', @port)
585
+ end
586
+
587
+ c = ring.wait_for_completion
588
+ assert_equal id, c[:id]
589
+ assert_equal :accept, c[:op]
590
+ fd = c[:result]
591
+ assert fd > 0
592
+ ensure
593
+ t&.kill rescue nil
594
+ end
595
+
596
+ def test_prep_accept_invalid_args
597
+ assert_raises(ArgumentError) { ring.prep_accept() }
598
+ assert_raises(ArgumentError) { ring.prep_accept(foo: 1) }
599
+ assert_raises(TypeError) { ring.prep_accept(fd: 'bar') }
600
+ assert_raises(ArgumentError) { ring.prep_accept({}) }
601
+ end
602
+
603
+ def test_prep_accept_bad_fd
604
+ id = ring.prep_accept(fd: STDIN.fileno)
605
+ assert_equal 1, id
606
+
607
+ ring.submit
608
+ c = ring.wait_for_completion
609
+
610
+ assert_kind_of Hash, c
611
+ assert_equal id, c[:id]
612
+ assert_equal :accept, c[:op]
613
+ assert_equal STDIN.fileno, c[:fd]
614
+ assert_equal -Errno::ENOTSOCK::Errno, c[:result]
615
+ end
616
+
617
+ def test_prep_accept_multishot
618
+ id = ring.prep_accept(fd: @server.fileno, multishot: true)
619
+ ring.submit
620
+
621
+ tt = []
622
+
623
+ connect = -> {
624
+ tt << Thread.new do
625
+ client = TCPSocket.new('127.0.0.1', @port)
626
+ end
627
+ }
628
+
629
+ fds = []
630
+
631
+ 3.times do |i|
632
+ connect.call
633
+ c = ring.wait_for_completion
634
+ assert_equal id, c[:id]
635
+ assert_equal :accept, c[:op]
636
+ fd = c[:result]
637
+ assert fd > 0
638
+ assert ring.pending_ops[id]
639
+
640
+ fds << fd
641
+ end
642
+
643
+ assert_equal 3, fds.uniq.size
644
+
645
+ ring.prep_cancel(id)
646
+ ring.process_completions
647
+
648
+ assert_nil ring.pending_ops[id]
649
+ ensure
650
+ tt.each { |t| t&.kill rescue nil }
651
+ end
652
+ end
653
+
654
+ class EmitTest < IOURingBaseTest
655
+ def test_emit
656
+ o = { foo: 'bar' }
657
+ id = ring.emit(o)
658
+ assert_equal 1, id
659
+
660
+ c = ring.wait_for_completion
661
+ assert_equal o, c
662
+ assert_equal id, c[:id]
663
+ assert_equal :emit, c[:op]
664
+ assert_equal 0, c[:result]
665
+ end
666
+ end
667
+
668
+ class ProcessCompletionsLoopTest < IOURingBaseTest
669
+ def test_loop_stop
670
+ ring.emit(signal: :stop)
671
+
672
+ cc = []
673
+ ring.process_completions_loop do |c|
674
+ p c
675
+ cc << c
676
+ end
677
+
678
+ assert_equal [], cc
679
+ end
680
+
681
+ def test_loop
682
+ ring.emit(value: 1)
683
+ ring.emit(value: 2)
684
+ ring.emit(value: 3)
685
+ ring.emit(signal: :stop)
686
+ ring.emit(value: 4)
687
+
688
+ cc = []
689
+ ring.process_completions_loop do |c|
690
+ cc << c
691
+ end
692
+ assert_equal (1..3).to_a, cc.map { _1[:value] }
693
+
694
+ c = ring.wait_for_completion
695
+ assert_equal 4, c[:value]
696
+ end
697
+ end
698
+
699
+ class PrepReadMultishotTest < IOURingBaseTest
700
+ def test_prep_read_multishot_invalid_args
701
+ assert_raises(ArgumentError) { ring.prep_read(multishot: true, buffer_group: 1) }
702
+ assert_raises(ArgumentError) { ring.prep_read(multishot: true, foo: 1) }
703
+ assert_raises(ArgumentError) { ring.prep_read(multishot: true, fd: 'bar', buffer: +'') }
704
+ assert_raises(ArgumentError) { ring.prep_read(multishot: true) }
705
+ end
706
+
707
+ def test_prep_read_multishot
708
+ r, w = IO.pipe
709
+
710
+ bb = []
711
+ bgid = ring.setup_buffer_ring(size: 4096, count: 1024)
712
+ assert_equal 0, bgid
713
+
714
+ id = ring.prep_read(fd: r.fileno, multishot: true, buffer_group: bgid)
715
+ assert_equal 1, id
716
+ ring.submit
717
+
718
+ w << 'foo'
719
+ c = ring.wait_for_completion
720
+ assert_kind_of Hash, c
721
+ assert_equal id, c[:id]
722
+ assert_equal :read, c[:op]
723
+ assert_equal r.fileno, c[:fd]
724
+ assert_equal 3, c[:result]
725
+ assert_equal 'foo', c[:buffer]
726
+ assert_equal Encoding::ASCII_8BIT, c[:buffer].encoding
727
+ refute_nil ring.pending_ops[id]
728
+
729
+ w << 'bar'
730
+ c = ring.wait_for_completion
731
+ assert_kind_of Hash, c
732
+ assert_equal id, c[:id]
733
+ assert_equal :read, c[:op]
734
+ assert_equal r.fileno, c[:fd]
735
+ assert_equal 3, c[:result]
736
+ assert_equal 'bar', c[:buffer]
737
+ refute_nil ring.pending_ops[id]
738
+
739
+ w.close
740
+ c = ring.wait_for_completion
741
+ assert_kind_of Hash, c
742
+ assert_equal id, c[:id]
743
+ assert_equal :read, c[:op]
744
+ assert_equal r.fileno, c[:fd]
745
+ assert_equal 0, c[:result]
746
+ assert_nil ring.pending_ops[id]
747
+ end
748
+
749
+ def test_prep_read_multishot_utf8
750
+ # checking for UTF-8 incurs a serious performance degradation. We'll leave
751
+ # it for later...
752
+ skip
753
+
754
+ r, w = IO.pipe
755
+
756
+ bb = []
757
+ bgid = ring.setup_buffer_ring(size: 4096, count: 1024)
758
+ assert_equal 0, bgid
759
+
760
+ id = ring.prep_read(fd: r.fileno, multishot: true, utf8: true, buffer_group: bgid)
761
+ assert_equal 1, id
762
+ ring.submit
763
+
764
+ w << 'foo'
765
+ c = ring.wait_for_completion
766
+ assert_kind_of Hash, c
767
+ assert_equal id, c[:id]
768
+ assert_equal :read, c[:op]
769
+ assert_equal r.fileno, c[:fd]
770
+ assert_equal 3, c[:result]
771
+ assert_equal 'foo', c[:buffer]
772
+ assert_equal Encoding::UTF_8, c[:buffer].encoding
773
+ refute_nil ring.pending_ops[id]
774
+
775
+ w << 'bar'
776
+ c = ring.wait_for_completion
777
+ assert_kind_of Hash, c
778
+ assert_equal id, c[:id]
779
+ assert_equal :read, c[:op]
780
+ assert_equal r.fileno, c[:fd]
781
+ assert_equal 3, c[:result]
782
+ assert_equal 'bar', c[:buffer]
783
+ refute_nil ring.pending_ops[id]
784
+
785
+ w.close
786
+ c = ring.wait_for_completion
787
+ assert_kind_of Hash, c
788
+ assert_equal id, c[:id]
789
+ assert_equal :read, c[:op]
790
+ assert_equal r.fileno, c[:fd]
791
+ assert_equal 0, c[:result]
792
+ assert_nil ring.pending_ops[id]
793
+ end
794
+ end