uringmachine 0.24.0 → 0.26.0

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 (279) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitmodules +0 -3
  4. data/CHANGELOG.md +13 -0
  5. data/Gemfile +11 -0
  6. data/README.md +266 -112
  7. data/Rakefile +8 -0
  8. data/TODO.md +14 -21
  9. data/benchmark/common.rb +2 -0
  10. data/benchmark/openssl.rb +77 -0
  11. data/benchmark/openssl_socketpair.rb +112 -0
  12. data/benchmark/sqlite.rb +1 -1
  13. data/docs/design/buffer_pool.md +1 -1
  14. data/docs/wroclove.rb.md +52 -0
  15. data/ext/um/extconf.rb +15 -0
  16. data/ext/um/um.c +392 -358
  17. data/ext/um/um.h +48 -23
  18. data/ext/um/um_async_op.c +9 -8
  19. data/ext/um/um_async_op_class.c +34 -3
  20. data/ext/um/um_class.c +705 -19
  21. data/ext/um/um_const.c +31 -0
  22. data/ext/um/um_mutex_class.c +12 -0
  23. data/ext/um/um_op.c +15 -1
  24. data/ext/um/um_queue_class.c +16 -0
  25. data/ext/um/um_ssl.c +109 -0
  26. data/ext/um/um_stream.c +9 -8
  27. data/ext/um/um_sync.c +18 -11
  28. data/ext/um/um_utils.c +17 -8
  29. data/grant-2025/interim-report.md +1 -1
  30. data/grant-2025/journal.md +4 -4
  31. data/grant-2025/tasks.md +6 -4
  32. data/lib/uringmachine/dns_resolver.rb +38 -0
  33. data/lib/uringmachine/fiber_scheduler.rb +7 -5
  34. data/lib/uringmachine/version.rb +1 -1
  35. data/lib/uringmachine.rb +106 -6
  36. data/test/helper.rb +15 -0
  37. data/test/test_async_op.rb +3 -2
  38. data/test/test_fiber_scheduler.rb +41 -1
  39. data/test/test_ssl.rb +85 -0
  40. data/test/test_stream.rb +11 -0
  41. data/test/test_um.rb +445 -11
  42. data/uringmachine.gemspec +1 -7
  43. data/vendor/liburing/examples/send-zerocopy.c +43 -31
  44. data/vendor/liburing/examples/zcrx.c +260 -69
  45. data/vendor/liburing/liburing.spec +1 -1
  46. data/vendor/liburing/src/include/liburing/io_uring.h +12 -0
  47. data/vendor/liburing/src/include/liburing.h +3 -2
  48. data/vendor/liburing/src/liburing-ffi.map +4 -0
  49. data/vendor/liburing/src/liburing.map +4 -0
  50. data/vendor/liburing/src/queue.c +12 -0
  51. data/vendor/liburing/src/register.c +1 -0
  52. data/vendor/liburing/src/setup.c +15 -7
  53. data/vendor/liburing/test/Makefile +8 -4
  54. data/vendor/liburing/test/conn-unreach.c +1 -1
  55. data/vendor/liburing/test/epwait.c +32 -6
  56. data/vendor/liburing/test/io-wq-exit.c +131 -0
  57. data/vendor/liburing/test/iowait.c +1 -1
  58. data/vendor/liburing/test/min-timeout.c +3 -1
  59. data/vendor/liburing/test/open-close.c +39 -0
  60. data/vendor/liburing/test/poll-update-trigger.c +85 -0
  61. data/vendor/liburing/test/recvsend_bundle.c +14 -11
  62. data/vendor/liburing/test/sendzc-bug.c +146 -0
  63. data/vendor/liburing/test/sqe-mixed-nop.c +151 -7
  64. data/vendor/liburing/test/test.h +2 -0
  65. data/vendor/liburing/test/timestamp-bug.c +135 -0
  66. data/vendor/liburing/test/timestamp.c +5 -0
  67. data/vendor/liburing/test/vec-regbuf.c +136 -1
  68. metadata +38 -283
  69. data/vendor/libressl/.github/scripts/changelog.sh +0 -74
  70. data/vendor/libressl/.github/workflows/android.yml +0 -35
  71. data/vendor/libressl/.github/workflows/cifuzz.yml +0 -33
  72. data/vendor/libressl/.github/workflows/cmake-config.yml +0 -98
  73. data/vendor/libressl/.github/workflows/coverity.yml +0 -69
  74. data/vendor/libressl/.github/workflows/emscripten.yml +0 -71
  75. data/vendor/libressl/.github/workflows/fedora-rawhide.yml +0 -39
  76. data/vendor/libressl/.github/workflows/freebsd.yml +0 -71
  77. data/vendor/libressl/.github/workflows/linux.yml +0 -71
  78. data/vendor/libressl/.github/workflows/macos.yml +0 -37
  79. data/vendor/libressl/.github/workflows/release.yml +0 -81
  80. data/vendor/libressl/.github/workflows/rust-openssl.yml +0 -47
  81. data/vendor/libressl/.github/workflows/solaris.yml +0 -37
  82. data/vendor/libressl/.github/workflows/windows.yml +0 -70
  83. data/vendor/libressl/.gitignore +0 -333
  84. data/vendor/libressl/CMakeLists.txt +0 -581
  85. data/vendor/libressl/COPYING +0 -133
  86. data/vendor/libressl/ChangeLog +0 -3280
  87. data/vendor/libressl/FindLibreSSL.cmake +0 -232
  88. data/vendor/libressl/LibreSSLConfig.cmake.in +0 -36
  89. data/vendor/libressl/Makefile.am +0 -60
  90. data/vendor/libressl/Makefile.am.common +0 -20
  91. data/vendor/libressl/OPENBSD_BRANCH +0 -1
  92. data/vendor/libressl/README.md +0 -238
  93. data/vendor/libressl/README.mingw.md +0 -43
  94. data/vendor/libressl/apps/CMakeLists.txt +0 -18
  95. data/vendor/libressl/apps/Makefile.am +0 -5
  96. data/vendor/libressl/apps/nc/CMakeLists.txt +0 -67
  97. data/vendor/libressl/apps/nc/Makefile.am +0 -64
  98. data/vendor/libressl/apps/nc/compat/accept4.c +0 -17
  99. data/vendor/libressl/apps/nc/compat/readpassphrase.c +0 -205
  100. data/vendor/libressl/apps/nc/compat/socket.c +0 -29
  101. data/vendor/libressl/apps/nc/compat/sys/socket.h +0 -30
  102. data/vendor/libressl/apps/ocspcheck/CMakeLists.txt +0 -44
  103. data/vendor/libressl/apps/ocspcheck/Makefile.am +0 -45
  104. data/vendor/libressl/apps/ocspcheck/compat/.gitignore +0 -0
  105. data/vendor/libressl/apps/openssl/CMakeLists.txt +0 -97
  106. data/vendor/libressl/apps/openssl/Makefile.am +0 -108
  107. data/vendor/libressl/apps/openssl/apps_win.c +0 -138
  108. data/vendor/libressl/apps/openssl/certhash_win.c +0 -13
  109. data/vendor/libressl/apps/openssl/compat/clock_gettime_osx.c +0 -26
  110. data/vendor/libressl/apps/openssl/compat/poll_win.c +0 -329
  111. data/vendor/libressl/appveyor.yml +0 -53
  112. data/vendor/libressl/autogen.sh +0 -15
  113. data/vendor/libressl/check-release.sh +0 -86
  114. data/vendor/libressl/cmake_export_symbol.cmake +0 -71
  115. data/vendor/libressl/cmake_uninstall.cmake.in +0 -36
  116. data/vendor/libressl/config +0 -17
  117. data/vendor/libressl/configure.ac +0 -165
  118. data/vendor/libressl/crypto/CMakeLists.txt +0 -863
  119. data/vendor/libressl/crypto/Makefile.am +0 -962
  120. data/vendor/libressl/crypto/Makefile.am.arc4random +0 -46
  121. data/vendor/libressl/crypto/Makefile.am.elf-mips +0 -14
  122. data/vendor/libressl/crypto/Makefile.am.elf-mips64 +0 -14
  123. data/vendor/libressl/crypto/Makefile.am.elf-x86_64 +0 -35
  124. data/vendor/libressl/crypto/Makefile.am.macosx-x86_64 +0 -35
  125. data/vendor/libressl/crypto/Makefile.am.masm-x86_64 +0 -22
  126. data/vendor/libressl/crypto/Makefile.am.mingw64-x86_64 +0 -23
  127. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_darwin.c +0 -60
  128. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_linux.c +0 -62
  129. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_none.c +0 -26
  130. data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_windows.c +0 -36
  131. data/vendor/libressl/crypto/arch/loongarch64/crypto_arch.h +0 -21
  132. data/vendor/libressl/crypto/arch/mips/crypto_arch.h +0 -21
  133. data/vendor/libressl/crypto/bn/arch/loongarch64/bn_arch.h +0 -23
  134. data/vendor/libressl/crypto/bn/arch/mips/bn_arch.h +0 -24
  135. data/vendor/libressl/crypto/compat/.gitignore +0 -31
  136. data/vendor/libressl/crypto/compat/arc4random.h +0 -41
  137. data/vendor/libressl/crypto/compat/b_win.c +0 -55
  138. data/vendor/libressl/crypto/compat/bsd-asprintf.c +0 -96
  139. data/vendor/libressl/crypto/compat/crypto_lock_win.c +0 -56
  140. data/vendor/libressl/crypto/compat/explicit_bzero_win.c +0 -13
  141. data/vendor/libressl/crypto/compat/freezero.c +0 -32
  142. data/vendor/libressl/crypto/compat/getdelim.c +0 -78
  143. data/vendor/libressl/crypto/compat/getline.c +0 -40
  144. data/vendor/libressl/crypto/compat/getopt_long.c +0 -528
  145. data/vendor/libressl/crypto/compat/getpagesize.c +0 -18
  146. data/vendor/libressl/crypto/compat/getprogname_linux.c +0 -23
  147. data/vendor/libressl/crypto/compat/getprogname_unimpl.c +0 -7
  148. data/vendor/libressl/crypto/compat/getprogname_windows.c +0 -13
  149. data/vendor/libressl/crypto/compat/posix_win.c +0 -296
  150. data/vendor/libressl/crypto/compat/syslog_r.c +0 -19
  151. data/vendor/libressl/crypto/compat/ui_openssl_win.c +0 -334
  152. data/vendor/libressl/dist.sh +0 -22
  153. data/vendor/libressl/gen-coverage-report.sh +0 -58
  154. data/vendor/libressl/gen-openbsd-tags.sh +0 -20
  155. data/vendor/libressl/include/CMakeLists.txt +0 -61
  156. data/vendor/libressl/include/Makefile.am +0 -79
  157. data/vendor/libressl/include/arch/loongarch64/opensslconf.h +0 -150
  158. data/vendor/libressl/include/arch/mips/opensslconf.h +0 -150
  159. data/vendor/libressl/include/compat/arpa/inet.h +0 -15
  160. data/vendor/libressl/include/compat/arpa/nameser.h +0 -25
  161. data/vendor/libressl/include/compat/cet.h +0 -19
  162. data/vendor/libressl/include/compat/dirent.h +0 -17
  163. data/vendor/libressl/include/compat/dirent_msvc.h +0 -611
  164. data/vendor/libressl/include/compat/endian.h +0 -161
  165. data/vendor/libressl/include/compat/err.h +0 -95
  166. data/vendor/libressl/include/compat/fcntl.h +0 -32
  167. data/vendor/libressl/include/compat/getopt.h +0 -50
  168. data/vendor/libressl/include/compat/limits.h +0 -25
  169. data/vendor/libressl/include/compat/netdb.h +0 -10
  170. data/vendor/libressl/include/compat/netinet/in.h +0 -19
  171. data/vendor/libressl/include/compat/netinet/ip.h +0 -49
  172. data/vendor/libressl/include/compat/netinet/tcp.h +0 -10
  173. data/vendor/libressl/include/compat/poll.h +0 -63
  174. data/vendor/libressl/include/compat/pthread.h +0 -122
  175. data/vendor/libressl/include/compat/readpassphrase.h +0 -44
  176. data/vendor/libressl/include/compat/resolv.h +0 -24
  177. data/vendor/libressl/include/compat/stdint.h +0 -31
  178. data/vendor/libressl/include/compat/stdio.h +0 -65
  179. data/vendor/libressl/include/compat/stdlib.h +0 -57
  180. data/vendor/libressl/include/compat/string.h +0 -98
  181. data/vendor/libressl/include/compat/sys/_null.h +0 -18
  182. data/vendor/libressl/include/compat/sys/ioctl.h +0 -11
  183. data/vendor/libressl/include/compat/sys/mman.h +0 -19
  184. data/vendor/libressl/include/compat/sys/param.h +0 -15
  185. data/vendor/libressl/include/compat/sys/queue.h +0 -536
  186. data/vendor/libressl/include/compat/sys/select.h +0 -10
  187. data/vendor/libressl/include/compat/sys/socket.h +0 -18
  188. data/vendor/libressl/include/compat/sys/stat.h +0 -129
  189. data/vendor/libressl/include/compat/sys/time.h +0 -37
  190. data/vendor/libressl/include/compat/sys/tree.h +0 -1006
  191. data/vendor/libressl/include/compat/sys/types.h +0 -69
  192. data/vendor/libressl/include/compat/sys/uio.h +0 -17
  193. data/vendor/libressl/include/compat/syslog.h +0 -38
  194. data/vendor/libressl/include/compat/time.h +0 -59
  195. data/vendor/libressl/include/compat/unistd.h +0 -83
  196. data/vendor/libressl/include/compat/win32netcompat.h +0 -57
  197. data/vendor/libressl/include/openssl/Makefile.am.tpl +0 -45
  198. data/vendor/libressl/libcrypto.pc.in +0 -28
  199. data/vendor/libressl/libressl.pub +0 -2
  200. data/vendor/libressl/libssl.pc.in +0 -28
  201. data/vendor/libressl/libtls.pc.in +0 -28
  202. data/vendor/libressl/m4/ax_add_fortify_source.m4 +0 -80
  203. data/vendor/libressl/m4/ax_check_compile_flag.m4 +0 -53
  204. data/vendor/libressl/m4/check-hardening-options.m4 +0 -110
  205. data/vendor/libressl/m4/check-libc.m4 +0 -189
  206. data/vendor/libressl/m4/check-os-options.m4 +0 -181
  207. data/vendor/libressl/m4/disable-compiler-warnings.m4 +0 -44
  208. data/vendor/libressl/man/CMakeLists.txt +0 -26
  209. data/vendor/libressl/man/links +0 -2780
  210. data/vendor/libressl/man/update_links.sh +0 -25
  211. data/vendor/libressl/openssl.pc.in +0 -11
  212. data/vendor/libressl/patches/bn_shift.patch +0 -34
  213. data/vendor/libressl/patches/crypto_arch.h.patch +0 -34
  214. data/vendor/libressl/patches/crypto_namespace.h.patch +0 -22
  215. data/vendor/libressl/patches/netcat.c.patch +0 -178
  216. data/vendor/libressl/patches/openssl.c.patch +0 -12
  217. data/vendor/libressl/patches/opensslfeatures.h.patch +0 -49
  218. data/vendor/libressl/patches/patch-amd64-crypto-cpu-caps.c.patch +0 -20
  219. data/vendor/libressl/patches/patch-i386-crypto-cpu-caps.c.patch +0 -20
  220. data/vendor/libressl/patches/speed.c.patch +0 -114
  221. data/vendor/libressl/patches/ssl_namespace.h.patch +0 -21
  222. data/vendor/libressl/patches/tls.h.patch +0 -16
  223. data/vendor/libressl/patches/tls_config.c.patch +0 -15
  224. data/vendor/libressl/patches/win32_amd64_bn_arch.h.patch +0 -28
  225. data/vendor/libressl/patches/windows_headers.patch +0 -80
  226. data/vendor/libressl/scripts/config.guess +0 -1774
  227. data/vendor/libressl/scripts/config.sub +0 -1907
  228. data/vendor/libressl/scripts/i686-w64-mingw32.cmake +0 -9
  229. data/vendor/libressl/scripts/test +0 -210
  230. data/vendor/libressl/scripts/wrap-compiler-for-flag-check +0 -31
  231. data/vendor/libressl/scripts/x86_64-w64-mingw32.cmake +0 -9
  232. data/vendor/libressl/ssl/CMakeLists.txt +0 -183
  233. data/vendor/libressl/ssl/Makefile.am +0 -187
  234. data/vendor/libressl/tests/CMakeLists.txt +0 -970
  235. data/vendor/libressl/tests/Makefile.am +0 -944
  236. data/vendor/libressl/tests/aeadtest.sh +0 -30
  237. data/vendor/libressl/tests/arc4randomforktest.sh +0 -21
  238. data/vendor/libressl/tests/asn1time_small.test +0 -10
  239. data/vendor/libressl/tests/cmake/CMakeLists.txt +0 -52
  240. data/vendor/libressl/tests/cmake/crypto.c +0 -7
  241. data/vendor/libressl/tests/cmake/ssl.c +0 -6
  242. data/vendor/libressl/tests/cmake/tls.c +0 -6
  243. data/vendor/libressl/tests/compat/pipe2.c +0 -186
  244. data/vendor/libressl/tests/dtlstest.sh +0 -28
  245. data/vendor/libressl/tests/evptest.sh +0 -22
  246. data/vendor/libressl/tests/keypairtest.sh +0 -27
  247. data/vendor/libressl/tests/mlkem_tests.sh +0 -39
  248. data/vendor/libressl/tests/ocsptest.bat +0 -25
  249. data/vendor/libressl/tests/ocsptest.sh +0 -23
  250. data/vendor/libressl/tests/openssl.cnf +0 -29
  251. data/vendor/libressl/tests/optionstest.c +0 -381
  252. data/vendor/libressl/tests/pidwraptest.c +0 -85
  253. data/vendor/libressl/tests/pidwraptest.sh +0 -26
  254. data/vendor/libressl/tests/quictest.bat +0 -27
  255. data/vendor/libressl/tests/quictest.sh +0 -30
  256. data/vendor/libressl/tests/renegotiation_test.bat +0 -27
  257. data/vendor/libressl/tests/renegotiation_test.sh +0 -30
  258. data/vendor/libressl/tests/rfc5280time_small.test +0 -10
  259. data/vendor/libressl/tests/servertest.bat +0 -27
  260. data/vendor/libressl/tests/servertest.sh +0 -30
  261. data/vendor/libressl/tests/shutdowntest.bat +0 -27
  262. data/vendor/libressl/tests/shutdowntest.sh +0 -30
  263. data/vendor/libressl/tests/ssltest.bat +0 -32
  264. data/vendor/libressl/tests/ssltest.sh +0 -48
  265. data/vendor/libressl/tests/testdsa.bat +0 -47
  266. data/vendor/libressl/tests/testdsa.sh +0 -57
  267. data/vendor/libressl/tests/testenc.bat +0 -85
  268. data/vendor/libressl/tests/testenc.sh +0 -93
  269. data/vendor/libressl/tests/testrsa.bat +0 -47
  270. data/vendor/libressl/tests/testrsa.sh +0 -57
  271. data/vendor/libressl/tests/testssl.bat +0 -171
  272. data/vendor/libressl/tests/tlstest.bat +0 -27
  273. data/vendor/libressl/tests/tlstest.sh +0 -28
  274. data/vendor/libressl/tls/CMakeLists.txt +0 -125
  275. data/vendor/libressl/tls/Makefile.am +0 -76
  276. data/vendor/libressl/tls/compat/ftruncate.c +0 -17
  277. data/vendor/libressl/tls/compat/pread.c +0 -29
  278. data/vendor/libressl/tls/compat/pwrite.c +0 -29
  279. data/vendor/libressl/update.sh +0 -460
data/test/test_um.rb CHANGED
@@ -224,11 +224,14 @@ class ScheduleTest < UMBaseTest
224
224
 
225
225
  # the call to schedule means an op is checked out
226
226
  assert_equal 0, machine.metrics[:ops_pending]
227
+ # UM.debug("* before sleep")
227
228
  begin
228
229
  machine.sleep(1)
229
230
  rescue Exception => e2
231
+ # UM.debug("* sleep exception")
230
232
  end
231
- assert_equal 0, machine.metrics[:ops_pending]
233
+ # UM.debug("* after sleep")
234
+ assert_equal 1, machine.metrics[:ops_pending]
232
235
  t1 = monotonic_clock
233
236
 
234
237
  assert_equal e2, e
@@ -251,6 +254,8 @@ class ScheduleTest < UMBaseTest
251
254
  buf << 5
252
255
  end
253
256
 
257
+ assert_equal 1, machine.metrics[:ops_pending]
258
+ machine.snooze
254
259
  assert_equal 0, machine.metrics[:ops_pending]
255
260
  assert_equal [1, 2, 5], buf
256
261
  assert_kind_of TOError, e
@@ -312,7 +317,7 @@ class ScheduleTest < UMBaseTest
312
317
  rescue => e
313
318
  end
314
319
 
315
- assert_equal 2, machine.metrics[:ops_pending]
320
+ assert_equal 3, machine.metrics[:ops_pending]
316
321
  machine.sleep(0.01) # wait for cancelled CQEs
317
322
  assert_equal 0, machine.metrics[:ops_pending]
318
323
 
@@ -325,8 +330,10 @@ class SleepTest < UMBaseTest
325
330
  def test_sleep
326
331
  t0 = monotonic_clock
327
332
  assert_equal 0, machine.metrics[:ops_pending]
333
+ assert_equal 0, machine.metrics[:ops_free]
328
334
  res = machine.sleep(0.1)
329
335
  assert_equal 0, machine.metrics[:ops_pending]
336
+ assert_equal 256, machine.metrics[:ops_free]
330
337
  t1 = monotonic_clock
331
338
  assert_in_range 0.09..0.13, t1 - t0
332
339
  assert_equal 0.1, res
@@ -395,8 +402,9 @@ class PeriodicallyTest < UMBaseTest
395
402
  machine.snooze
396
403
  assert_equal 0, machine.metrics[:ops_pending]
397
404
  t1 = monotonic_clock
398
- assert_in_range 0.05..0.09, t1 - t0
405
+ assert_equal 256, machine.metrics[:ops_free]
399
406
  assert_equal 5, count
407
+ assert_in_range 0.05..0.14, t1 - t0
400
408
  assert_equal 1, cancel
401
409
  end
402
410
 
@@ -410,7 +418,6 @@ class PeriodicallyTest < UMBaseTest
410
418
  machine.timeout(0.05, Cancel) do
411
419
  machine.periodically(0.01) do
412
420
  count += 1
413
- raise Cancel if count >= 5
414
421
  end
415
422
  end
416
423
  rescue Cancel
@@ -420,28 +427,34 @@ class PeriodicallyTest < UMBaseTest
420
427
  t1 = monotonic_clock
421
428
  assert_in_range 0.05..0.08, t1 - t0
422
429
  assert_in_range 4..6, count
423
-
430
+ assert_equal 0, machine.metrics[:ops_pending]
431
+ assert_equal 256, machine.metrics[:ops_free]
424
432
  end
425
433
  end
426
434
 
427
- class StatsTest < UMBaseTest
435
+ class OpCountsTest < UMBaseTest
428
436
  def test_op_counts
429
437
  _r, w = IO.pipe
430
438
 
431
439
  assert_equal 0, machine.metrics[:ops_pending]
440
+ assert_equal 0, machine.metrics[:ops_free]
432
441
  assert_equal 0, machine.metrics[:total_ops]
433
442
  machine.write_async(w.fileno, 'foo')
434
443
  assert_equal 1, machine.metrics[:ops_pending]
444
+ assert_equal 255, machine.metrics[:ops_free]
435
445
  assert_equal 1, machine.metrics[:total_ops]
436
446
  machine.snooze
437
447
  assert_equal 0, machine.metrics[:ops_pending]
448
+ assert_equal 256, machine.metrics[:ops_free]
438
449
  assert_equal 1, machine.metrics[:total_ops]
439
450
 
440
451
  machine.write_async(w.fileno, 'foo')
441
452
  assert_equal 1, machine.metrics[:ops_pending]
453
+ assert_equal 255, machine.metrics[:ops_free]
442
454
  assert_equal 2, machine.metrics[:total_ops]
443
455
  machine.snooze
444
456
  assert_equal 0, machine.metrics[:ops_pending]
457
+ assert_equal 256, machine.metrics[:ops_free]
445
458
  assert_equal 2, machine.metrics[:total_ops]
446
459
  end
447
460
  end
@@ -540,7 +553,7 @@ class ReadTest < UMBaseTest
540
553
 
541
554
  machine.close(w)
542
555
 
543
- res = machine.read(r, read_buffer)
556
+ res = machine.read(r, read_buffer, 6)
544
557
  assert_equal 3, res
545
558
  assert_equal 'bar', read_buffer.get_string(0, 3)
546
559
  end
@@ -570,8 +583,10 @@ class ReadTest < UMBaseTest
570
583
  def test_read_invalid_buffer
571
584
  r, _w = UM.pipe
572
585
  assert_raises(UM::Error) {
573
- machine.read(r, [])
586
+ machine.read(r, [], 3)
574
587
  }
588
+ assert_equal 0, machine.metrics[:ops_pending]
589
+ assert_equal 0, machine.metrics[:ops_free]
575
590
  end
576
591
 
577
592
  def test_read_with_file_offset
@@ -615,6 +630,7 @@ class ReadEachTest < UMBaseTest
615
630
 
616
631
  assert_equal ['foo', 'bar', 'baz'], bufs
617
632
  assert_equal 0, machine.metrics[:ops_pending]
633
+ assert_equal 256, machine.metrics[:ops_free]
618
634
  end
619
635
 
620
636
  # send once and close write fd
@@ -637,6 +653,7 @@ class ReadEachTest < UMBaseTest
637
653
  assert_kind_of RuntimeError, e
638
654
  assert_equal 'hi', e.message
639
655
  assert_equal 0, machine.metrics[:ops_pending]
656
+ assert_equal 256, machine.metrics[:ops_free]
640
657
  end
641
658
 
642
659
  # send once and leave write fd open
@@ -660,6 +677,7 @@ class ReadEachTest < UMBaseTest
660
677
 
661
678
  machine.snooze # in case the final CQE has not yet arrived
662
679
  assert_equal 0, machine.metrics[:ops_pending]
680
+ assert_equal 256, machine.metrics[:ops_free]
663
681
  end
664
682
 
665
683
  # send twice
@@ -684,6 +702,7 @@ class ReadEachTest < UMBaseTest
684
702
 
685
703
  machine.snooze # in case the final CQE has not yet arrived
686
704
  assert_equal 0, machine.metrics[:ops_pending]
705
+ assert_equal 256, machine.metrics[:ops_free]
687
706
  end
688
707
 
689
708
  def test_read_each_break
@@ -706,10 +725,38 @@ class ReadEachTest < UMBaseTest
706
725
  assert_equal ['foo'], bufs
707
726
  machine.snooze # in case the final CQE has not yet arrived
708
727
  assert_equal 0, machine.metrics[:ops_pending]
728
+ assert_equal 256, machine.metrics[:ops_free]
709
729
  ensure
710
730
  t&.kill
711
731
  end
712
732
 
733
+ class TOError < StandardError; end
734
+
735
+ def test_read_each_timeout
736
+ r, w = IO.pipe
737
+ bgid = machine.setup_buffer_ring(4096, 1024)
738
+
739
+ bufs = []
740
+ e = nil
741
+ begin
742
+ machine.timeout(0.01, TOError) do
743
+ machine.read_each(r.fileno, bgid) do |b|
744
+ bufs << b
745
+ end
746
+ end
747
+ rescue => e
748
+ end
749
+
750
+ assert_kind_of TOError, e
751
+ assert_equal [], bufs
752
+ machine.snooze # in case the final CQE has not yet arrived
753
+ assert_equal 0, machine.metrics[:ops_pending]
754
+ assert_equal 256, machine.metrics[:ops_free]
755
+ end
756
+
757
+ def test_read_each_close
758
+ end
759
+
713
760
  def test_read_each_bad_file
714
761
  _r, w = IO.pipe
715
762
  bgid = machine.setup_buffer_ring(4096, 1024)
@@ -717,6 +764,8 @@ class ReadEachTest < UMBaseTest
717
764
  assert_raises(Errno::EBADF) do
718
765
  machine.read_each(w.fileno, bgid)
719
766
  end
767
+ assert_equal 0, machine.metrics[:ops_pending]
768
+ assert_equal 256, machine.metrics[:ops_free]
720
769
  end
721
770
  end
722
771
 
@@ -743,6 +792,7 @@ class WriteTest < UMBaseTest
743
792
  machine.write(r.fileno, 'foo')
744
793
  end
745
794
  assert_equal 0, machine.metrics[:ops_pending]
795
+ assert_equal 256, machine.metrics[:ops_free]
746
796
  end
747
797
 
748
798
  def test_write_zero_length
@@ -809,6 +859,8 @@ class WriteTest < UMBaseTest
809
859
  assert_raises(UM::Error) {
810
860
  machine.write(w, [])
811
861
  }
862
+ assert_equal 0, machine.metrics[:ops_pending]
863
+ assert_equal 0, machine.metrics[:ops_free]
812
864
  end
813
865
 
814
866
  def test_write_with_file_offset
@@ -838,6 +890,8 @@ class WritevTest < UMBaseTest
838
890
  res = machine.writev(w.fileno, 'oofoof', 'rabrab')
839
891
  assert_equal 12, res
840
892
  assert_equal 'oofoofrabrab', r.readpartial(12)
893
+ assert_equal 0, machine.metrics[:ops_pending]
894
+ assert_equal 256, machine.metrics[:ops_free]
841
895
  end
842
896
 
843
897
  def test_writev_incomplete
@@ -870,6 +924,8 @@ class WritevTest < UMBaseTest
870
924
  msg_expected = [prelim_msg, *strs].join
871
925
 
872
926
  assert_equal msg_expected, msg_read
927
+ assert_equal 0, machine.metrics[:ops_pending]
928
+ assert_equal 256, machine.metrics[:ops_free]
873
929
  ensure
874
930
  machine.close(w) rescue nil
875
931
  machine.close(r) rescue nil
@@ -891,6 +947,8 @@ class WritevTest < UMBaseTest
891
947
  }
892
948
 
893
949
  assert_raises(Errno::EBADF) { machine.writev(w, *strs) }
950
+ assert_equal 0, machine.metrics[:ops_pending]
951
+ assert_equal 256, machine.metrics[:ops_free]
894
952
  ensure
895
953
  machine.close(w) rescue nil
896
954
  machine.close(r) rescue nil
@@ -912,6 +970,9 @@ class WritevTest < UMBaseTest
912
970
  machine.writev(w, *strs)
913
971
  }
914
972
  }
973
+
974
+ assert_equal 0, machine.metrics[:ops_pending]
975
+ assert_equal 256, machine.metrics[:ops_free]
915
976
  ensure
916
977
  machine.close(w) rescue nil
917
978
  machine.close(r) rescue nil
@@ -925,6 +986,7 @@ class WritevTest < UMBaseTest
925
986
  machine.writev(r, 'foo', 'bar')
926
987
  end
927
988
  assert_equal 0, machine.metrics[:ops_pending]
989
+ assert_equal 256, machine.metrics[:ops_free]
928
990
  end
929
991
 
930
992
  def test_writev_zero_length
@@ -932,9 +994,13 @@ class WritevTest < UMBaseTest
932
994
 
933
995
  res = machine.write(w.fileno, '')
934
996
  assert_equal 0, res
997
+ assert_equal 0, machine.metrics[:ops_pending]
998
+ assert_equal 0, machine.metrics[:ops_free]
935
999
 
936
1000
  res = machine.writev(w.fileno, '', '')
937
1001
  assert_equal 0, res
1002
+ assert_equal 0, machine.metrics[:ops_pending]
1003
+ assert_equal 0, machine.metrics[:ops_free]
938
1004
 
939
1005
  buf1 = IO::Buffer.new(0)
940
1006
  buf2 = IO::Buffer.new(0)
@@ -943,6 +1009,9 @@ class WritevTest < UMBaseTest
943
1009
 
944
1010
  w.close
945
1011
  assert_equal '', r.read
1012
+
1013
+ assert_equal 0, machine.metrics[:ops_pending]
1014
+ assert_equal 0, machine.metrics[:ops_free]
946
1015
  end
947
1016
 
948
1017
  def test_writev_io_buffer
@@ -992,6 +1061,7 @@ class WriteAsyncTest < UMBaseTest
992
1061
 
993
1062
  machine.snooze while machine.metrics[:ops_pending] > 0
994
1063
  assert_equal 0, machine.metrics[:ops_pending]
1064
+ assert_equal 256, machine.metrics[:ops_free]
995
1065
  assert_equal 'foo', r.readpartial(3)
996
1066
  end
997
1067
 
@@ -1005,9 +1075,11 @@ class WriteAsyncTest < UMBaseTest
1005
1075
  str = nil
1006
1076
  # GC.start
1007
1077
  assert_equal 1, machine.metrics[:ops_pending]
1078
+ assert_equal 255, machine.metrics[:ops_free]
1008
1079
 
1009
1080
  machine.snooze while machine.metrics[:ops_pending] > 0
1010
1081
  assert_equal 0, machine.metrics[:ops_pending]
1082
+ assert_equal 256, machine.metrics[:ops_free]
1011
1083
  assert_equal "foo#{123}#{'bar' * 48}", r.readpartial(len)
1012
1084
  end
1013
1085
 
@@ -1017,8 +1089,10 @@ class WriteAsyncTest < UMBaseTest
1017
1089
  assert_equal 0, machine.metrics[:ops_pending]
1018
1090
  machine.write_async(r.fileno, 'foo')
1019
1091
  assert_equal 1, machine.metrics[:ops_pending]
1092
+ assert_equal 255, machine.metrics[:ops_free]
1020
1093
  machine.snooze
1021
1094
  assert_equal 0, machine.metrics[:ops_pending]
1095
+ assert_equal 256, machine.metrics[:ops_free]
1022
1096
  end
1023
1097
 
1024
1098
  def test_write_async_io_buffer
@@ -1041,6 +1115,8 @@ class WriteAsyncTest < UMBaseTest
1041
1115
  _r, w = UM.pipe
1042
1116
 
1043
1117
  assert_raises(UM::Error) { machine.write_async(w, []) }
1118
+ assert_equal 0, machine.metrics[:ops_pending]
1119
+ assert_equal 0, machine.metrics[:ops_free]
1044
1120
  end
1045
1121
 
1046
1122
  def test_write_async_with_len
@@ -1090,6 +1166,8 @@ class CloseTest < UMBaseTest
1090
1166
  machine.close(w.fileno)
1091
1167
 
1092
1168
  assert_raises(Errno::EBADF) { machine.close(w.fileno) }
1169
+ assert_equal 0, machine.metrics[:ops_pending]
1170
+ assert_equal 256, machine.metrics[:ops_free]
1093
1171
  end
1094
1172
  end
1095
1173
 
@@ -1102,8 +1180,10 @@ class CloseAsyncTest < UMBaseTest
1102
1180
  assert_equal 0, machine.metrics[:ops_pending]
1103
1181
  machine.close_async(w.fileno) # fire and forget
1104
1182
  assert_equal 1, machine.metrics[:ops_pending]
1183
+ assert_equal 255, machine.metrics[:ops_free]
1105
1184
  machine.snooze
1106
1185
  assert_equal 0, machine.metrics[:ops_pending]
1186
+ assert_equal 256, machine.metrics[:ops_free]
1107
1187
  assert_equal '', r.read
1108
1188
  end
1109
1189
  end
@@ -1226,6 +1306,7 @@ class AcceptEachTest < UMBaseTest
1226
1306
 
1227
1307
  assert_equal 3, count
1228
1308
  assert_equal 0, machine.metrics[:ops_pending]
1309
+ assert_equal 256, machine.metrics[:ops_free]
1229
1310
  ensure
1230
1311
  t&.kill
1231
1312
  end
@@ -1253,6 +1334,9 @@ class AcceptEachTest < UMBaseTest
1253
1334
 
1254
1335
  assert f.done?
1255
1336
  assert terminated
1337
+
1338
+ assert_equal 0, machine.metrics[:ops_pending]
1339
+ assert_equal 256, machine.metrics[:ops_free]
1256
1340
  ensure
1257
1341
  s.close
1258
1342
  end
@@ -1289,6 +1373,9 @@ class AcceptEachTest < UMBaseTest
1289
1373
 
1290
1374
  def test_accept_each_bad_fd
1291
1375
  assert_raises(Errno::ENOTSOCK) { machine.accept_each(STDOUT.fileno) }
1376
+
1377
+ assert_equal 0, machine.metrics[:ops_pending]
1378
+ assert_equal 256, machine.metrics[:ops_free]
1292
1379
  end
1293
1380
  end
1294
1381
 
@@ -1321,6 +1408,8 @@ class AcceptIntoQueueTest < UMBaseTest
1321
1408
  t.join
1322
1409
  machine.sleep(0.01)
1323
1410
  assert_equal 3, queue.count
1411
+ assert_equal 1, machine.metrics[:ops_pending]
1412
+ assert_equal 255, machine.metrics[:ops_free]
1324
1413
  ensure
1325
1414
  machine.close(@server_fd)
1326
1415
  machine.schedule(f, nil)
@@ -1348,6 +1437,9 @@ class AcceptIntoQueueTest < UMBaseTest
1348
1437
 
1349
1438
  assert f.done?
1350
1439
  assert terminated
1440
+
1441
+ assert_equal 0, machine.metrics[:ops_pending]
1442
+ assert_equal 256, machine.metrics[:ops_free]
1351
1443
  ensure
1352
1444
  s.close
1353
1445
  end
@@ -1355,10 +1447,14 @@ class AcceptIntoQueueTest < UMBaseTest
1355
1447
  def test_accept_into_queue_bad_fd
1356
1448
  queue = UM::Queue.new
1357
1449
  assert_raises(Errno::ENOTSOCK) { machine.accept_into_queue(STDOUT.fileno, queue) }
1450
+ assert_equal 0, machine.metrics[:ops_pending]
1451
+ assert_equal 256, machine.metrics[:ops_free]
1358
1452
  end
1359
1453
 
1360
1454
  def test_accept_into_queue_bad_queue
1361
1455
  assert_raises(TypeError) { machine.accept_into_queue(@server_fd, nil) }
1456
+ assert_equal 0, machine.metrics[:ops_pending]
1457
+ assert_equal 0, machine.metrics[:ops_free]
1362
1458
  end
1363
1459
  end
1364
1460
 
@@ -1410,8 +1506,10 @@ class ConnectTest < UMBaseTest
1410
1506
  def test_connect_with_bad_addr
1411
1507
  fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0);
1412
1508
  assert_equal 0, machine.metrics[:ops_pending]
1509
+ assert_equal 256, machine.metrics[:ops_free]
1413
1510
  assert_raises(Errno::ENETUNREACH) { machine.connect(fd, 'a.b.c.d', @port) }
1414
1511
  assert_equal 0, machine.metrics[:ops_pending]
1512
+ assert_equal 256, machine.metrics[:ops_free]
1415
1513
  end
1416
1514
  end
1417
1515
 
@@ -1500,6 +1598,9 @@ class SendTest < UMBaseTest
1500
1598
  res = machine.read(fd, buf, 42)
1501
1599
  assert_equal 20, res
1502
1600
  assert_equal 'You said: foobar (6)', buf
1601
+
1602
+ assert_equal 0, machine.metrics[:ops_pending]
1603
+ assert_equal 256, machine.metrics[:ops_free]
1503
1604
  ensure
1504
1605
  t&.kill
1505
1606
  end
@@ -1517,6 +1618,9 @@ class SendTest < UMBaseTest
1517
1618
  assert_equal 0, res
1518
1619
 
1519
1620
  assert_raises(UM::Error) { machine.send(fd, [], -1, 0) }
1621
+
1622
+ assert_equal 0, machine.metrics[:ops_pending]
1623
+ assert_equal 256, machine.metrics[:ops_free]
1520
1624
  ensure
1521
1625
  t&.kill
1522
1626
  end
@@ -1544,6 +1648,8 @@ class SendvTest < UMBaseTest
1544
1648
  ret = machine.read(@s2, buf, 8192)
1545
1649
  assert_equal 9, ret
1546
1650
  assert_equal 'foobarbaz', buf
1651
+ assert_equal 0, machine.metrics[:ops_pending]
1652
+ assert_equal 256, machine.metrics[:ops_free]
1547
1653
  end
1548
1654
 
1549
1655
  def test_sendv_io_buffer
@@ -1562,12 +1668,16 @@ class SendvTest < UMBaseTest
1562
1668
  ret = machine.read(@s2, buf, 8192)
1563
1669
  assert_equal 9, ret
1564
1670
  assert_equal 'foobarbaz', buf
1671
+ assert_equal 0, machine.metrics[:ops_pending]
1672
+ assert_equal 256, machine.metrics[:ops_free]
1565
1673
  end
1566
1674
 
1567
1675
  def test_sendv_invalid_buffer
1568
1676
  skip "Unavailable on kernel version < 6.17" if UM.kernel_version < 617
1569
1677
 
1570
1678
  assert_raises(UM::Error) { machine.sendv(@s1, [], 'abc') }
1679
+ assert_equal 0, machine.metrics[:ops_pending]
1680
+ assert_equal 0, machine.metrics[:ops_free]
1571
1681
  end
1572
1682
  end
1573
1683
 
@@ -1598,6 +1708,8 @@ class RecvTest < UMBaseTest
1598
1708
  res = machine.recv(fd, buf, 42, 0)
1599
1709
  assert_equal 6, res
1600
1710
  assert_equal 'foobar', buf
1711
+ assert_equal 0, machine.metrics[:ops_pending]
1712
+ assert_equal 256, machine.metrics[:ops_free]
1601
1713
  ensure
1602
1714
  t&.kill
1603
1715
  end
@@ -1617,6 +1729,37 @@ class RecvTest < UMBaseTest
1617
1729
  res = machine.recv(fd, buf, 12, 0)
1618
1730
  assert_equal 6, res
1619
1731
  assert_equal 'foobar', buf.get_string(0, 6)
1732
+ assert_equal 0, machine.metrics[:ops_pending]
1733
+ assert_equal 256, machine.metrics[:ops_free]
1734
+ ensure
1735
+ t&.kill
1736
+ end
1737
+
1738
+ def test_recv_invalid_fd
1739
+ buf = IO::Buffer.new(12)
1740
+ assert_raises(Errno::EBADF) {
1741
+ machine.recv(1001, buf, 12, 0)
1742
+ }
1743
+ assert_equal 0, machine.metrics[:ops_pending]
1744
+ assert_equal 256, machine.metrics[:ops_free]
1745
+ end
1746
+
1747
+ def test_recv_invalid_buffer
1748
+ t = Thread.new do
1749
+ conn = @server.accept
1750
+ conn.write('foobar')
1751
+ sleep
1752
+ end
1753
+
1754
+ fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
1755
+ res = machine.connect(fd, '127.0.0.1', @port)
1756
+ assert_equal 0, res
1757
+
1758
+ assert_raises(UM::Error) {
1759
+ res = machine.recv(fd, :foo, 12, 0)
1760
+ }
1761
+ assert_equal 0, machine.metrics[:ops_pending]
1762
+ assert_equal 256, machine.metrics[:ops_free]
1620
1763
  ensure
1621
1764
  t&.kill
1622
1765
  end
@@ -1663,6 +1806,76 @@ class RecvEachTest < UMBaseTest
1663
1806
  bufs << buf
1664
1807
  end
1665
1808
  assert_equal ['abc', 'def', 'ghi'], bufs
1809
+ assert_equal 0, machine.metrics[:ops_pending]
1810
+ assert_equal 256, machine.metrics[:ops_free]
1811
+ ensure
1812
+ t&.kill
1813
+ end
1814
+
1815
+ class TOError < StandardError; end
1816
+
1817
+ def test_recv_each_timeout
1818
+ t = Thread.new do
1819
+ conn = @server.accept
1820
+ sleep
1821
+ end
1822
+
1823
+ fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
1824
+ res = machine.connect(fd, '127.0.0.1', @port)
1825
+ assert_equal 0, res
1826
+
1827
+ bgid = machine.setup_buffer_ring(4096, 1024)
1828
+ assert_equal 0, bgid
1829
+
1830
+ bufs = []
1831
+ e = nil
1832
+ begin
1833
+ machine.timeout(0.01, TOError) do
1834
+ machine.recv_each(fd, bgid, 0) do |buf|
1835
+ bufs << buf
1836
+ end
1837
+ end
1838
+ rescue => e
1839
+ end
1840
+ assert_kind_of TOError, e
1841
+ assert_equal [], bufs
1842
+ assert_equal 0, machine.metrics[:ops_pending]
1843
+ assert_equal 256, machine.metrics[:ops_free]
1844
+ ensure
1845
+ t&.kill
1846
+ end
1847
+
1848
+ def test_recv_each_shutdown
1849
+ t = Thread.new do
1850
+ conn = @server.accept
1851
+ sleep
1852
+ end
1853
+
1854
+ fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
1855
+ res = machine.connect(fd, '127.0.0.1', @port)
1856
+ assert_equal 0, res
1857
+
1858
+ bgid = machine.setup_buffer_ring(4096, 1024)
1859
+ assert_equal 0, bgid
1860
+
1861
+ bufs = []
1862
+ e = nil
1863
+
1864
+ f = machine.spin {
1865
+ machine.sleep(0.01)
1866
+ machine.shutdown(fd, UM::SHUT_RDWR)
1867
+ }
1868
+
1869
+ begin
1870
+ machine.recv_each(fd, bgid, 0) do |buf|
1871
+ bufs << buf
1872
+ end
1873
+ rescue => e
1874
+ end
1875
+ assert_nil e
1876
+ assert_equal [], bufs
1877
+ assert_equal 0, machine.metrics[:ops_pending]
1878
+ assert_equal 256, machine.metrics[:ops_free]
1666
1879
  ensure
1667
1880
  t&.kill
1668
1881
  end
@@ -1699,6 +1912,7 @@ class BindTest < UMBaseTest
1699
1912
  assert_raises(Errno::EBADF) { machine.bind(-3, '127.0.01', 1234) }
1700
1913
 
1701
1914
  assert_equal 0, machine.metrics[:ops_pending]
1915
+ assert_equal 256, machine.metrics[:ops_free]
1702
1916
  end
1703
1917
  end
1704
1918
 
@@ -1768,6 +1982,28 @@ class SynchronizeTest < UMBaseTest
1768
1982
 
1769
1983
  assert_equal [1, 2], buf
1770
1984
  assert_equal 0, machine.metrics[:ops_pending]
1985
+ assert_equal 0, machine.metrics[:ops_free]
1986
+ end
1987
+
1988
+ class MyError < StandardError; end
1989
+
1990
+ def test_synchronize_exception
1991
+ m = UM::Mutex.new
1992
+
1993
+ buf = []
1994
+ assert_raises(MyError) {
1995
+ machine.synchronize(m) do
1996
+ raise MyError
1997
+ buf << 1
1998
+ end
1999
+ }
2000
+ machine.synchronize(m) do
2001
+ buf << 2
2002
+ end
2003
+
2004
+ assert_equal [2], buf
2005
+ assert_equal 0, machine.metrics[:ops_pending]
2006
+ assert_equal 0, machine.metrics[:ops_free]
1771
2007
  end
1772
2008
 
1773
2009
  def test_synchronize_pair
@@ -1800,6 +2036,7 @@ class SynchronizeTest < UMBaseTest
1800
2036
  machine.sleep(0.03)
1801
2037
  assert_equal [11, 12, 13, 21, 22, 23], buf
1802
2038
  assert_equal 0, machine.metrics[:ops_pending]
2039
+ assert_equal 256, machine.metrics[:ops_free]
1803
2040
  end
1804
2041
 
1805
2042
  def test_synchronize_multi
@@ -1819,6 +2056,8 @@ class SynchronizeTest < UMBaseTest
1819
2056
 
1820
2057
  machine.join(*fibers)
1821
2058
  assert_equal [11, 12, 21, 13, 22, 31, 23, 32, 41, 33, 42, 51, 43, 52, 61, 53, 62, 71, 63, 72, 81, 73, 82, 83], buf
2059
+ assert_equal 0, machine.metrics[:ops_pending]
2060
+ assert_equal 256, machine.metrics[:ops_free]
1822
2061
  end
1823
2062
  end
1824
2063
 
@@ -1932,7 +2171,7 @@ class QueueTest < UMBaseTest
1932
2171
  assert_equal :baz, machine.shift(q)
1933
2172
  end
1934
2173
 
1935
- def test_shift_shift_1
2174
+ def test_shift_unshift_1
1936
2175
  q = UM::Queue.new
1937
2176
 
1938
2177
  machine.unshift(q, :foo)
@@ -2176,6 +2415,8 @@ class PollTest < UMBaseTest
2176
2415
 
2177
2416
  def test_poll_bad_fd
2178
2417
  assert_raises(Errno::EBADF) { machine.poll(9876, POLLIN) }
2418
+ assert_equal 0, machine.metrics[:ops_pending]
2419
+ assert_equal 256, machine.metrics[:ops_free]
2179
2420
  end
2180
2421
  end
2181
2422
 
@@ -2219,6 +2460,8 @@ class SelectTest < UMBaseTest
2219
2460
 
2220
2461
  machine.close(rfd1)
2221
2462
  machine.close(rfd2)
2463
+ assert_equal 0, machine.metrics[:ops_pending]
2464
+ assert_equal 256, machine.metrics[:ops_free]
2222
2465
  end
2223
2466
 
2224
2467
  def test_select_single
@@ -2246,15 +2489,27 @@ class SelectTest < UMBaseTest
2246
2489
 
2247
2490
  machine.close(rfd1)
2248
2491
  machine.close(wfd1)
2492
+ assert_equal 0, machine.metrics[:ops_pending]
2493
+ assert_equal 256, machine.metrics[:ops_free]
2249
2494
  end
2250
2495
 
2251
2496
  def test_select_empty
2252
2497
  ret = machine.select([], [], [])
2253
2498
  assert_equal [[], [], []], ret
2499
+ assert_equal 0, machine.metrics[:ops_pending]
2500
+ assert_equal 0, machine.metrics[:ops_free]
2254
2501
  end
2255
2502
 
2256
2503
  def test_select_bad_fd
2257
2504
  assert_raises(Errno::EBADF) { machine.select([9876, 9877], [], []) }
2505
+
2506
+ # we get one CQE with EBADF, the other one is cancelled and discarded
2507
+ assert_equal 0, machine.metrics[:ops_pending]
2508
+ assert_equal 255, machine.metrics[:ops_free]
2509
+
2510
+ # a second CQE with -ECANCELED, released
2511
+ machine.snooze
2512
+ assert_equal 256, machine.metrics[:ops_free]
2258
2513
  end
2259
2514
  end
2260
2515
 
@@ -2272,6 +2527,8 @@ class WaitidTest < UMBaseTest
2272
2527
  pid, status = machine.waitid(UM::P_PID, child_pid, UM::WEXITED)
2273
2528
  assert_equal child_pid, pid
2274
2529
  assert_equal 42, status
2530
+ assert_equal 0, machine.metrics[:ops_pending]
2531
+ assert_equal 256, machine.metrics[:ops_free]
2275
2532
  ensure
2276
2533
  Process.wait(child_pid) rescue nil
2277
2534
  end
@@ -2280,18 +2537,27 @@ class WaitidTest < UMBaseTest
2280
2537
  assert_raises(Errno::ECHILD) {
2281
2538
  machine.waitid(UM::P_PID, Process.pid + 1, UM::WEXITED)
2282
2539
  }
2540
+
2541
+ assert_equal 0, machine.metrics[:ops_pending]
2542
+ assert_equal 256, machine.metrics[:ops_free]
2283
2543
  end
2284
2544
 
2285
2545
  def test_waitid_invalid_idtype
2286
2546
  assert_raises(Errno::EINVAL) {
2287
2547
  machine.waitid(1234, 0, UM::WEXITED)
2288
2548
  }
2549
+
2550
+ assert_equal 0, machine.metrics[:ops_pending]
2551
+ assert_equal 256, machine.metrics[:ops_free]
2289
2552
  end
2290
2553
 
2291
2554
  def test_waitid_invalid_options
2292
2555
  assert_raises(Errno::EINVAL) {
2293
2556
  machine.waitid(P_ALL, 0, 1234)
2294
2557
  }
2558
+
2559
+ assert_equal 0, machine.metrics[:ops_pending]
2560
+ assert_equal 256, machine.metrics[:ops_free]
2295
2561
  end
2296
2562
 
2297
2563
  def test_waitid_P_ALL
@@ -2307,6 +2573,8 @@ class WaitidTest < UMBaseTest
2307
2573
  pid, status = machine.waitid(UM::P_ALL, 0, UM::WEXITED)
2308
2574
  assert_equal child_pid, pid
2309
2575
  assert_equal 42, status
2576
+ assert_equal 0, machine.metrics[:ops_pending]
2577
+ assert_equal 256, machine.metrics[:ops_free]
2310
2578
  ensure
2311
2579
  Process.wait(child_pid) rescue nil
2312
2580
  end
@@ -2324,6 +2592,8 @@ class WaitidTest < UMBaseTest
2324
2592
  pid, status = machine.waitid(UM::P_PGID, Process.getpgrp, UM::WEXITED)
2325
2593
  assert_equal child_pid, pid
2326
2594
  assert_equal 42, status
2595
+ assert_equal 0, machine.metrics[:ops_pending]
2596
+ assert_equal 256, machine.metrics[:ops_free]
2327
2597
  ensure
2328
2598
  Process.wait(child_pid) rescue nil
2329
2599
  end
@@ -2447,6 +2717,9 @@ class StatxTest < UMBaseTest
2447
2717
  assert_equal rstat.atime.to_i, ustat2[:atime].to_i
2448
2718
  assert_equal rstat.ctime.to_i, ustat2[:ctime].to_i
2449
2719
  assert_equal rstat.mtime.to_i, ustat2[:mtime].to_i
2720
+
2721
+ assert_equal 0, machine.metrics[:ops_pending]
2722
+ assert_equal 256, machine.metrics[:ops_free]
2450
2723
  ensure
2451
2724
  io.close
2452
2725
  end
@@ -2458,12 +2731,19 @@ class StatxTest < UMBaseTest
2458
2731
 
2459
2732
  assert_equal rstat.size, ustat[:size]
2460
2733
  assert_equal rstat.mtime.to_i, ustat[:mtime].to_i
2734
+ assert_equal 0, machine.metrics[:ops_pending]
2735
+ assert_equal 256, machine.metrics[:ops_free]
2461
2736
  ensure
2462
2737
  @machine.close_async(fd)
2463
2738
  end
2464
2739
 
2465
2740
  def test_statx_bad_path
2466
- assert_raises(Errno::ENOENT) { machine.statx(UM::AT_FDCWD, 'foobar', 0, UM::STATX_ALL) }
2741
+ assert_raises(Errno::ENOENT) {
2742
+ machine.statx(UM::AT_FDCWD, 'foobar', 0, UM::STATX_ALL)
2743
+ }
2744
+
2745
+ assert_equal 0, machine.metrics[:ops_pending]
2746
+ assert_equal 256, machine.metrics[:ops_free]
2467
2747
  end
2468
2748
  end
2469
2749
 
@@ -2672,7 +2952,7 @@ class MetricsTest < UMBaseTest
2672
2952
  f = machine.spin { machine.sleep(0.001) }
2673
2953
  assert_equal [0, 0, 1, 255, 0], ops_metrics
2674
2954
  machine.snooze
2675
- assert_equal [1, 0, 0, 256, 0], ops_metrics
2955
+ assert_equal [1, 0, 0, 255, 0], ops_metrics
2676
2956
  machine.join(f)
2677
2957
  assert_equal [0, 0, 0, 256, 0], ops_metrics
2678
2958
 
@@ -2725,3 +3005,157 @@ class ProfileModeTest < UMBaseTest
2725
3005
  assert_in_range 0.01..0.015, machine.metrics[:time_total_wait]
2726
3006
  end
2727
3007
  end
3008
+
3009
+ class FileWatchTest < UMBaseTest
3010
+ def setup
3011
+ super
3012
+ @root = "/tmp/um_#{SecureRandom.hex}"
3013
+ make_tmp_file_tree(@root, {
3014
+ 'foo.txt': 'foo',
3015
+ 'bar.txt': 'bar',
3016
+ 'foo': {
3017
+ 'baz.txt': 'baz'
3018
+ }
3019
+ })
3020
+ end
3021
+
3022
+ def test_inotify_get_events
3023
+ fd = UM.inotify_init
3024
+ assert_kind_of Integer, fd
3025
+ assert fd > 0
3026
+
3027
+ mask = UM::IN_CREATE | UM::IN_DELETE | UM::IN_CLOSE_WRITE
3028
+
3029
+ assert_raises(Errno::EBADF) { UM.inotify_add_watch(-1, @root, mask) }
3030
+ assert_raises(Errno::EINVAL) { UM.inotify_add_watch(fd, @root, 0) }
3031
+ non_existent = "/tmp/um_#{SecureRandom.hex}"
3032
+ assert_raises(Errno::ENOENT) { UM.inotify_add_watch(fd, non_existent, mask) }
3033
+
3034
+ wd = UM.inotify_add_watch(fd, @root, mask)
3035
+ assert_equal 1, wd
3036
+
3037
+ fn = File.join(@root, 'foo.txt')
3038
+ IO.write(fn, 'foofoo')
3039
+
3040
+ events = machine.inotify_get_events(fd)
3041
+ assert_equal [
3042
+ {
3043
+ wd: wd,
3044
+ mask: UM::IN_CLOSE_WRITE,
3045
+ name: 'foo.txt'
3046
+ }
3047
+ ], events
3048
+ end
3049
+
3050
+ def write_file(fn, data)
3051
+ File.open(fn, 'w+') { it.sync = true; it.syswrite('foofoo') }
3052
+ end
3053
+
3054
+ def test_file_watch
3055
+ events = []
3056
+ f = machine.spin do
3057
+ mask = UM::IN_CREATE | UM::IN_DELETE | UM::IN_CLOSE_WRITE
3058
+ machine.file_watch(@root, mask) do |evt|
3059
+ events << evt
3060
+ end
3061
+ rescue => e
3062
+ p e
3063
+ p e.backtrace
3064
+ exit!
3065
+ end
3066
+
3067
+ 3.times { machine.snooze }
3068
+ assert_equal [], events
3069
+
3070
+ # modify foo.txt
3071
+ fn = File.join(@root, 'foo.txt')
3072
+ write_file(fn, 'foofoo')
3073
+ machine.sleep(0.05)
3074
+ assert_equal [
3075
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo.txt') }
3076
+ ], events
3077
+
3078
+ # modify foo/baz.txt
3079
+ fn = File.join(@root, 'foo/baz.txt')
3080
+ write_file(fn, 'bazbaz')
3081
+ machine.sleep(0.05)
3082
+ assert_equal [
3083
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo.txt') },
3084
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo/baz.txt') }
3085
+ ], events
3086
+
3087
+ # create bar dir
3088
+ fn = File.join(@root, 'bar')
3089
+ FileUtils.mkdir(fn)
3090
+ machine.sleep(0.05)
3091
+ assert_equal [
3092
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo.txt') },
3093
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo/baz.txt') },
3094
+ { mask: UM::IN_CREATE | UM::IN_ISDIR, fn: File.join(@root, 'bar') }
3095
+ ], events
3096
+
3097
+ # create bar/baz.txt
3098
+ fn = File.join(@root, 'bar/baz.txt')
3099
+ write_file(fn, 'bazbaz')
3100
+ machine.sleep(0.05)
3101
+ assert_equal [
3102
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo.txt') },
3103
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo/baz.txt') },
3104
+ { mask: UM::IN_CREATE | UM::IN_ISDIR, fn: File.join(@root, 'bar') },
3105
+ { mask: UM::IN_CREATE, fn: File.join(@root, 'bar/baz.txt') },
3106
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'bar/baz.txt') },
3107
+ ], events
3108
+
3109
+ # delete foo/baz.txt
3110
+ fn = File.join(@root, 'foo/baz.txt')
3111
+ FileUtils.rm(fn)
3112
+ machine.sleep(0.05)
3113
+ assert_equal [
3114
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo.txt') },
3115
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo/baz.txt') },
3116
+ { mask: UM::IN_CREATE | UM::IN_ISDIR, fn: File.join(@root, 'bar') },
3117
+ { mask: UM::IN_CREATE, fn: File.join(@root, 'bar/baz.txt') },
3118
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'bar/baz.txt') },
3119
+ { mask: UM::IN_DELETE, fn: File.join(@root, 'foo/baz.txt') }
3120
+ ], events
3121
+
3122
+ # delete bar
3123
+ fn = File.join(@root, 'bar')
3124
+ FileUtils.rm_rf(fn)
3125
+ machine.sleep(0.05)
3126
+ assert_equal [
3127
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo.txt') },
3128
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo/baz.txt') },
3129
+ { mask: UM::IN_CREATE | UM::IN_ISDIR, fn: File.join(@root, 'bar') },
3130
+ { mask: UM::IN_CREATE, fn: File.join(@root, 'bar/baz.txt') },
3131
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'bar/baz.txt') },
3132
+ { mask: UM::IN_DELETE, fn: File.join(@root, 'foo/baz.txt') },
3133
+ { mask: UM::IN_DELETE, fn: File.join(@root, 'bar/baz.txt') },
3134
+ { mask: UM::IN_DELETE | UM::IN_ISDIR, fn: File.join(@root, 'bar') }
3135
+ ], events
3136
+
3137
+ # recreate bar, bar/baz.txt
3138
+ fn = File.join(@root, 'bar')
3139
+ FileUtils.mkdir(fn)
3140
+ machine.sleep(0.05)
3141
+ fn = File.join(@root, 'bar/baz.txt')
3142
+ write_file(fn, 'bazbaz')
3143
+ machine.sleep(0.05)
3144
+ assert_equal [
3145
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo.txt') },
3146
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'foo/baz.txt') },
3147
+ { mask: UM::IN_CREATE | UM::IN_ISDIR, fn: File.join(@root, 'bar') },
3148
+ { mask: UM::IN_CREATE, fn: File.join(@root, 'bar/baz.txt') },
3149
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'bar/baz.txt') },
3150
+ { mask: UM::IN_DELETE, fn: File.join(@root, 'foo/baz.txt') },
3151
+ { mask: UM::IN_DELETE, fn: File.join(@root, 'bar/baz.txt') },
3152
+ { mask: UM::IN_DELETE | UM::IN_ISDIR, fn: File.join(@root, 'bar') },
3153
+ { mask: UM::IN_CREATE | UM::IN_ISDIR, fn: File.join(@root, 'bar') },
3154
+ { mask: UM::IN_CREATE, fn: File.join(@root, 'bar/baz.txt') },
3155
+ { mask: UM::IN_CLOSE_WRITE, fn: File.join(@root, 'bar/baz.txt') },
3156
+ ], events
3157
+ ensure
3158
+ machine.schedule(f, UM::Terminate.new)
3159
+ machine.join(f)
3160
+ end
3161
+ end