uringmachine 0.3 → 0.5
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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +2 -1
- data/CHANGELOG.md +23 -0
- data/README.md +128 -0
- data/TODO.md +14 -0
- data/examples/bm_snooze.rb +89 -0
- data/examples/bm_write.rb +56 -0
- data/examples/dns_client.rb +12 -0
- data/examples/echo_server.rb +18 -40
- data/examples/http_server.rb +42 -43
- data/examples/inout.rb +19 -0
- data/examples/nc.rb +36 -0
- data/examples/server_client.rb +64 -0
- data/examples/snooze.rb +44 -0
- data/examples/write_dev_null.rb +16 -0
- data/ext/um/extconf.rb +24 -23
- data/ext/um/um.c +524 -278
- data/ext/um/um.h +146 -44
- data/ext/um/um_buffer.c +49 -0
- data/ext/um/um_class.c +217 -106
- data/ext/um/um_const.c +213 -0
- data/ext/um/um_ext.c +4 -0
- data/ext/um/um_mutex_class.c +47 -0
- data/ext/um/um_op.c +86 -114
- data/ext/um/um_queue_class.c +58 -0
- data/ext/um/um_sync.c +273 -0
- data/ext/um/um_utils.c +49 -4
- data/lib/uringmachine/dns_resolver.rb +84 -0
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +28 -0
- data/supressions/ruby.supp +71 -0
- data/test/helper.rb +8 -0
- data/test/test_um.rb +685 -46
- data/vendor/liburing/.github/workflows/build.yml +29 -1
- data/vendor/liburing/.gitignore +6 -0
- data/vendor/liburing/CHANGELOG +16 -0
- data/vendor/liburing/CONTRIBUTING.md +165 -0
- data/vendor/liburing/configure +64 -0
- data/vendor/liburing/examples/Makefile +9 -1
- data/vendor/liburing/examples/kdigest.c +405 -0
- data/vendor/liburing/examples/proxy.c +75 -8
- data/vendor/liburing/examples/reg-wait.c +159 -0
- data/vendor/liburing/liburing.pc.in +1 -1
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/Makefile +16 -2
- data/vendor/liburing/src/include/liburing/io_uring.h +77 -0
- data/vendor/liburing/src/include/liburing/sanitize.h +39 -0
- data/vendor/liburing/src/include/liburing.h +59 -6
- data/vendor/liburing/src/int_flags.h +10 -3
- data/vendor/liburing/src/liburing-ffi.map +16 -0
- data/vendor/liburing/src/liburing.map +10 -0
- data/vendor/liburing/src/queue.c +28 -16
- data/vendor/liburing/src/register.c +106 -1
- data/vendor/liburing/src/sanitize.c +176 -0
- data/vendor/liburing/src/setup.c +47 -19
- data/vendor/liburing/src/setup.h +6 -0
- data/vendor/liburing/test/35fa71a030ca.c +7 -0
- data/vendor/liburing/test/500f9fbadef8.c +2 -0
- data/vendor/liburing/test/7ad0e4b2f83c.c +0 -25
- data/vendor/liburing/test/917257daa0fe.c +7 -0
- data/vendor/liburing/test/Makefile +38 -4
- data/vendor/liburing/test/a0908ae19763.c +7 -0
- data/vendor/liburing/test/a4c0b3decb33.c +7 -0
- data/vendor/liburing/test/accept.c +14 -4
- data/vendor/liburing/test/b19062a56726.c +7 -0
- data/vendor/liburing/test/bind-listen.c +2 -2
- data/vendor/liburing/test/buf-ring-nommap.c +10 -3
- data/vendor/liburing/test/buf-ring.c +2 -0
- data/vendor/liburing/test/cmd-discard.c +427 -0
- data/vendor/liburing/test/coredump.c +7 -0
- data/vendor/liburing/test/cq-overflow.c +13 -1
- data/vendor/liburing/test/d4ae271dfaae.c +11 -3
- data/vendor/liburing/test/defer-taskrun.c +2 -2
- data/vendor/liburing/test/defer-tw-timeout.c +4 -1
- data/vendor/liburing/test/defer.c +2 -2
- data/vendor/liburing/test/double-poll-crash.c +1 -1
- data/vendor/liburing/test/eeed8b54e0df.c +2 -0
- data/vendor/liburing/test/eventfd.c +0 -1
- data/vendor/liburing/test/exit-no-cleanup.c +11 -0
- data/vendor/liburing/test/fadvise.c +9 -26
- data/vendor/liburing/test/fdinfo.c +9 -1
- data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
- data/vendor/liburing/test/file-exit-unreg.c +48 -0
- data/vendor/liburing/test/file-register.c +14 -2
- data/vendor/liburing/test/file-update.c +1 -1
- data/vendor/liburing/test/file-verify.c +27 -16
- data/vendor/liburing/test/files-exit-hang-timeout.c +1 -2
- data/vendor/liburing/test/fixed-buf-iter.c +3 -1
- data/vendor/liburing/test/fixed-hugepage.c +12 -1
- data/vendor/liburing/test/fsnotify.c +1 -0
- data/vendor/liburing/test/futex.c +16 -4
- data/vendor/liburing/test/helpers.c +47 -0
- data/vendor/liburing/test/helpers.h +6 -0
- data/vendor/liburing/test/init-mem.c +5 -3
- data/vendor/liburing/test/io-cancel.c +0 -24
- data/vendor/liburing/test/io_uring_passthrough.c +4 -0
- data/vendor/liburing/test/io_uring_register.c +38 -8
- data/vendor/liburing/test/iopoll-leak.c +4 -0
- data/vendor/liburing/test/iopoll-overflow.c +1 -1
- data/vendor/liburing/test/iopoll.c +3 -3
- data/vendor/liburing/test/kallsyms.c +203 -0
- data/vendor/liburing/test/link-timeout.c +159 -0
- data/vendor/liburing/test/linked-defer-close.c +224 -0
- data/vendor/liburing/test/madvise.c +12 -25
- data/vendor/liburing/test/min-timeout-wait.c +0 -25
- data/vendor/liburing/test/min-timeout.c +0 -25
- data/vendor/liburing/test/mkdir.c +6 -0
- data/vendor/liburing/test/msg-ring.c +8 -2
- data/vendor/liburing/test/napi-test.c +16 -3
- data/vendor/liburing/test/no-mmap-inval.c +3 -1
- data/vendor/liburing/test/nop.c +44 -0
- data/vendor/liburing/test/ooo-file-unreg.c +1 -1
- data/vendor/liburing/test/open-close.c +40 -0
- data/vendor/liburing/test/openat2.c +37 -14
- data/vendor/liburing/test/poll-many.c +13 -7
- data/vendor/liburing/test/poll-mshot-update.c +17 -10
- data/vendor/liburing/test/poll-v-poll.c +6 -3
- data/vendor/liburing/test/pollfree.c +148 -0
- data/vendor/liburing/test/read-mshot-empty.c +158 -153
- data/vendor/liburing/test/read-mshot-stdin.c +121 -0
- data/vendor/liburing/test/read-mshot.c +282 -27
- data/vendor/liburing/test/read-write.c +78 -13
- data/vendor/liburing/test/recv-msgall-stream.c +3 -0
- data/vendor/liburing/test/recv-msgall.c +5 -0
- data/vendor/liburing/test/recvsend_bundle-inc.c +680 -0
- data/vendor/liburing/test/recvsend_bundle.c +94 -31
- data/vendor/liburing/test/reg-fd-only.c +15 -5
- data/vendor/liburing/test/reg-wait.c +251 -0
- data/vendor/liburing/test/regbuf-clone.c +645 -0
- data/vendor/liburing/test/regbuf-merge.c +7 -0
- data/vendor/liburing/test/register-restrictions.c +86 -85
- data/vendor/liburing/test/rename.c +59 -1
- data/vendor/liburing/test/resize-rings.c +643 -0
- data/vendor/liburing/test/ringbuf-read.c +5 -0
- data/vendor/liburing/test/ringbuf-status.c +5 -1
- data/vendor/liburing/test/rsrc_tags.c +1 -1
- data/vendor/liburing/test/runtests.sh +16 -1
- data/vendor/liburing/test/send-zerocopy.c +59 -0
- data/vendor/liburing/test/short-read.c +1 -0
- data/vendor/liburing/test/socket.c +43 -0
- data/vendor/liburing/test/splice.c +3 -1
- data/vendor/liburing/test/sq-poll-dup.c +1 -1
- data/vendor/liburing/test/sq-poll-share.c +2 -0
- data/vendor/liburing/test/sqpoll-disable-exit.c +8 -0
- data/vendor/liburing/test/sqpoll-exit-hang.c +1 -25
- data/vendor/liburing/test/sqpoll-sleep.c +40 -33
- data/vendor/liburing/test/sqwait.c +136 -0
- data/vendor/liburing/test/statx.c +89 -0
- data/vendor/liburing/test/stdout.c +2 -0
- data/vendor/liburing/test/submit-and-wait.c +1 -25
- data/vendor/liburing/test/submit-reuse.c +4 -26
- data/vendor/liburing/test/symlink.c +12 -1
- data/vendor/liburing/test/sync-cancel.c +56 -22
- data/vendor/liburing/test/thread-exit.c +5 -0
- data/vendor/liburing/test/timeout-new.c +1 -26
- data/vendor/liburing/test/timeout.c +25 -34
- data/vendor/liburing/test/unlink.c +94 -1
- data/vendor/liburing/test/uring_cmd_ublk.c +1252 -0
- data/vendor/liburing/test/waitid.c +62 -8
- data/vendor/liburing/test/wq-aff.c +35 -0
- data/vendor/liburing/test/xfail_prep_link_timeout_out_of_scope.c +46 -0
- data/vendor/liburing/test/xfail_register_buffers_out_of_scope.c +51 -0
- metadata +37 -6
- data/examples/event_loop.rb +0 -69
- data/examples/fibers.rb +0 -105
- data/examples/http_server_multishot.rb +0 -57
- data/examples/http_server_simpler.rb +0 -34
data/test/test_um.rb
CHANGED
@@ -3,13 +3,37 @@
|
|
3
3
|
require_relative 'helper'
|
4
4
|
require 'socket'
|
5
5
|
|
6
|
-
class
|
6
|
+
class UringMachineTest < Minitest::Test
|
7
|
+
def test_kernel_version
|
8
|
+
v = UringMachine.kernel_version
|
9
|
+
assert_kind_of Integer, v
|
10
|
+
assert_in_range 600..700, v
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class FiberTest < UMBaseTest
|
15
|
+
def test_spin
|
16
|
+
x = nil
|
17
|
+
f = machine.spin do
|
18
|
+
x = :foo
|
19
|
+
end
|
20
|
+
|
21
|
+
assert_kind_of Fiber, f
|
22
|
+
assert_nil x
|
23
|
+
|
24
|
+
machine.snooze
|
25
|
+
|
26
|
+
assert_equal :foo, x
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ScheduleTest < UMBaseTest
|
7
31
|
def test_schedule_and_yield
|
8
32
|
buf = []
|
9
|
-
|
33
|
+
main = Fiber.current
|
10
34
|
f = Fiber.new do |x|
|
11
35
|
buf << [21, x]
|
12
|
-
machine.schedule(
|
36
|
+
machine.schedule(main, 21)
|
13
37
|
buf << 22
|
14
38
|
x = machine.yield
|
15
39
|
buf << [23, x]
|
@@ -49,12 +73,11 @@ class SchedulingTest < UMBaseTest
|
|
49
73
|
assert_equal [e], buf
|
50
74
|
end
|
51
75
|
|
52
|
-
def
|
53
|
-
|
76
|
+
def test_schedule_exception2
|
77
|
+
main = Fiber.current
|
54
78
|
e = CustomError.new
|
55
79
|
f = Fiber.new do
|
56
|
-
machine.
|
57
|
-
assert_equal 2, machine.pending_count
|
80
|
+
machine.schedule(main, e)
|
58
81
|
machine.yield
|
59
82
|
end
|
60
83
|
|
@@ -62,17 +85,11 @@ class SchedulingTest < UMBaseTest
|
|
62
85
|
t0 = monotonic_clock
|
63
86
|
|
64
87
|
# the call to schedule means an op is checked out
|
65
|
-
assert_equal
|
88
|
+
assert_equal 0, machine.pending_count
|
66
89
|
begin
|
67
90
|
machine.sleep(1)
|
68
91
|
rescue Exception => e2
|
69
92
|
end
|
70
|
-
# the sleep op has been cancelled, but we still need to process the
|
71
|
-
# cancellation. Calling snooze should take care of that.
|
72
|
-
assert_equal 1, machine.pending_count
|
73
|
-
machine.snooze
|
74
|
-
|
75
|
-
# CQE should have been received, and the op checked in
|
76
93
|
assert_equal 0, machine.pending_count
|
77
94
|
t1 = monotonic_clock
|
78
95
|
|
@@ -96,13 +113,7 @@ class SchedulingTest < UMBaseTest
|
|
96
113
|
buf << 5
|
97
114
|
end
|
98
115
|
|
99
|
-
# at this point, the sleep cancelled CQE should not yet have been received.
|
100
|
-
# So we still have a pending operation. Snooze should have let the CQE be
|
101
|
-
# received.
|
102
|
-
assert_equal 1, machine.pending_count
|
103
|
-
machine.snooze
|
104
116
|
assert_equal 0, machine.pending_count
|
105
|
-
|
106
117
|
assert_equal [1, 2, 5], buf
|
107
118
|
assert_kind_of TOError, e
|
108
119
|
end
|
@@ -117,7 +128,7 @@ class SchedulingTest < UMBaseTest
|
|
117
128
|
end
|
118
129
|
|
119
130
|
assert_equal 1, machine.pending_count
|
120
|
-
machine.
|
131
|
+
machine.sleep(0.01) # wait for cancelled CQEs
|
121
132
|
assert_equal 0, machine.pending_count
|
122
133
|
|
123
134
|
assert_kind_of RuntimeError, e
|
@@ -130,7 +141,7 @@ class SchedulingTest < UMBaseTest
|
|
130
141
|
assert_equal 42, v
|
131
142
|
|
132
143
|
assert_equal 1, machine.pending_count
|
133
|
-
machine.
|
144
|
+
machine.sleep 0.01 # wait for cancelled CQE
|
134
145
|
assert_equal 0, machine.pending_count
|
135
146
|
end
|
136
147
|
|
@@ -152,6 +163,10 @@ class SchedulingTest < UMBaseTest
|
|
152
163
|
rescue => e
|
153
164
|
end
|
154
165
|
|
166
|
+
assert_equal 2, machine.pending_count
|
167
|
+
machine.sleep(0.01) # wait for cancelled CQEs
|
168
|
+
assert_equal 0, machine.pending_count
|
169
|
+
|
155
170
|
assert_kind_of TO2Error, e
|
156
171
|
assert_equal [3], buf
|
157
172
|
end
|
@@ -160,11 +175,41 @@ end
|
|
160
175
|
class SleepTest < UMBaseTest
|
161
176
|
def test_sleep
|
162
177
|
t0 = monotonic_clock
|
178
|
+
assert_equal 0, machine.pending_count
|
163
179
|
res = machine.sleep(0.1)
|
180
|
+
assert_equal 0, machine.pending_count
|
164
181
|
t1 = monotonic_clock
|
165
182
|
assert_in_range 0.09..0.13, t1 - t0
|
166
183
|
assert_equal 0.1, res
|
167
184
|
end
|
185
|
+
|
186
|
+
class C; end
|
187
|
+
|
188
|
+
def test_sleep_interrupted
|
189
|
+
t0 = monotonic_clock
|
190
|
+
ret = machine.timeout(0.03, C) do
|
191
|
+
machine.sleep 1
|
192
|
+
end
|
193
|
+
t1 = monotonic_clock
|
194
|
+
assert_in_range 0.02..0.04, t1 - t0
|
195
|
+
assert_kind_of C, ret
|
196
|
+
end
|
197
|
+
|
198
|
+
class D < RuntimeError; end
|
199
|
+
|
200
|
+
def test_sleep_with_timeout
|
201
|
+
t0 = monotonic_clock
|
202
|
+
ret = begin
|
203
|
+
machine.timeout(0.03, D) do
|
204
|
+
machine.sleep 1
|
205
|
+
end
|
206
|
+
rescue => e
|
207
|
+
e
|
208
|
+
end
|
209
|
+
t1 = monotonic_clock
|
210
|
+
assert_in_range 0.02..0.04, t1 - t0
|
211
|
+
assert_kind_of D, ret
|
212
|
+
end
|
168
213
|
end
|
169
214
|
|
170
215
|
class ReadTest < UMBaseTest
|
@@ -173,7 +218,9 @@ class ReadTest < UMBaseTest
|
|
173
218
|
w << 'foobar'
|
174
219
|
|
175
220
|
buf = +''
|
221
|
+
assert_equal 0, machine.pending_count
|
176
222
|
res = machine.read(r.fileno, buf, 3)
|
223
|
+
assert_equal 0, machine.pending_count
|
177
224
|
assert_equal 3, res
|
178
225
|
assert_equal 'foo', buf
|
179
226
|
|
@@ -195,6 +242,7 @@ class ReadTest < UMBaseTest
|
|
195
242
|
assert_raises(Errno::EBADF) do
|
196
243
|
machine.read(w.fileno, +'', 8192)
|
197
244
|
end
|
245
|
+
assert_equal 0, machine.pending_count
|
198
246
|
end
|
199
247
|
|
200
248
|
def test_read_with_buffer_offset
|
@@ -230,22 +278,24 @@ end
|
|
230
278
|
|
231
279
|
class ReadEachTest < UMBaseTest
|
232
280
|
def test_read_each
|
281
|
+
skip if UringMachine.kernel_version < 607
|
282
|
+
|
233
283
|
r, w = IO.pipe
|
234
284
|
bufs = []
|
235
|
-
|
236
285
|
bgid = machine.setup_buffer_ring(4096, 1024)
|
237
286
|
assert_equal 0, bgid
|
238
287
|
|
239
288
|
f = Fiber.new do
|
240
289
|
w << 'foo'
|
241
|
-
machine.
|
290
|
+
machine.sleep 0.02
|
242
291
|
w << 'bar'
|
243
|
-
machine.
|
292
|
+
machine.sleep 0.02
|
244
293
|
w << 'baz'
|
245
|
-
machine.
|
294
|
+
machine.sleep 0.02
|
246
295
|
w.close
|
247
296
|
machine.yield
|
248
297
|
end
|
298
|
+
|
249
299
|
machine.schedule(f, nil)
|
250
300
|
|
251
301
|
machine.read_each(r.fileno, bgid) do |buf|
|
@@ -258,8 +308,9 @@ class ReadEachTest < UMBaseTest
|
|
258
308
|
|
259
309
|
# send once and close write fd
|
260
310
|
def test_read_each_raising_1
|
261
|
-
|
311
|
+
skip if UringMachine.kernel_version < 607
|
262
312
|
|
313
|
+
r, w = IO.pipe
|
263
314
|
bgid = machine.setup_buffer_ring(4096, 1024)
|
264
315
|
assert_equal 0, bgid
|
265
316
|
|
@@ -281,8 +332,9 @@ class ReadEachTest < UMBaseTest
|
|
281
332
|
|
282
333
|
# send once and leave write fd open
|
283
334
|
def test_read_each_raising_2
|
284
|
-
|
335
|
+
skip if UringMachine.kernel_version < 607
|
285
336
|
|
337
|
+
r, w = IO.pipe
|
286
338
|
bgid = machine.setup_buffer_ring(4096, 1024)
|
287
339
|
assert_equal 0, bgid
|
288
340
|
|
@@ -299,17 +351,15 @@ class ReadEachTest < UMBaseTest
|
|
299
351
|
assert_kind_of RuntimeError, e
|
300
352
|
assert_equal 'hi', e.message
|
301
353
|
|
302
|
-
#
|
303
|
-
# the op, which is done asynchronously.
|
304
|
-
assert_equal 1, machine.pending_count
|
305
|
-
machine.snooze
|
354
|
+
machine.snooze # in case the final CQE has not yet arrived
|
306
355
|
assert_equal 0, machine.pending_count
|
307
356
|
end
|
308
357
|
|
309
358
|
# send twice
|
310
359
|
def test_read_each_raising_3
|
311
|
-
|
360
|
+
skip if UringMachine.kernel_version < 607
|
312
361
|
|
362
|
+
r, w = IO.pipe
|
313
363
|
bgid = machine.setup_buffer_ring(4096, 1024)
|
314
364
|
assert_equal 0, bgid
|
315
365
|
|
@@ -327,19 +377,55 @@ class ReadEachTest < UMBaseTest
|
|
327
377
|
assert_kind_of RuntimeError, e
|
328
378
|
assert_equal 'hi', e.message
|
329
379
|
|
330
|
-
#
|
331
|
-
# the op, which is done asynchronously.
|
332
|
-
assert_equal 1, machine.pending_count
|
333
|
-
machine.snooze
|
380
|
+
machine.snooze # in case the final CQE has not yet arrived
|
334
381
|
assert_equal 0, machine.pending_count
|
335
382
|
end
|
383
|
+
|
384
|
+
def test_read_each_break
|
385
|
+
skip if UringMachine.kernel_version < 607
|
386
|
+
|
387
|
+
r, w = IO.pipe
|
388
|
+
bgid = machine.setup_buffer_ring(4096, 1024)
|
389
|
+
|
390
|
+
t = Thread.new do
|
391
|
+
sleep 0.1
|
392
|
+
w << 'foo'
|
393
|
+
sleep 0.1
|
394
|
+
w.close
|
395
|
+
end
|
396
|
+
|
397
|
+
bufs = []
|
398
|
+
machine.read_each(r.fileno, bgid) do |b|
|
399
|
+
bufs << b
|
400
|
+
break
|
401
|
+
end
|
402
|
+
|
403
|
+
assert_equal ['foo'], bufs
|
404
|
+
machine.snooze # in case the final CQE has not yet arrived
|
405
|
+
assert_equal 0, machine.pending_count
|
406
|
+
ensure
|
407
|
+
t&.kill
|
408
|
+
end
|
409
|
+
|
410
|
+
def test_read_each_bad_file
|
411
|
+
skip if UringMachine.kernel_version < 607
|
412
|
+
|
413
|
+
_r, w = IO.pipe
|
414
|
+
bgid = machine.setup_buffer_ring(4096, 1024)
|
415
|
+
|
416
|
+
assert_raises(Errno::EBADF) do
|
417
|
+
machine.read_each(w.fileno, bgid)
|
418
|
+
end
|
419
|
+
end
|
336
420
|
end
|
337
421
|
|
338
422
|
class WriteTest < UMBaseTest
|
339
423
|
def test_write
|
340
424
|
r, w = IO.pipe
|
341
425
|
|
426
|
+
assert_equal 0, machine.pending_count
|
342
427
|
machine.write(w.fileno, 'foo')
|
428
|
+
assert_equal 0, machine.pending_count
|
343
429
|
assert_equal 'foo', r.readpartial(3)
|
344
430
|
|
345
431
|
machine.write(w.fileno, 'bar', 2)
|
@@ -349,16 +435,33 @@ class WriteTest < UMBaseTest
|
|
349
435
|
def test_write_bad_fd
|
350
436
|
r, _w = IO.pipe
|
351
437
|
|
438
|
+
assert_equal 0, machine.pending_count
|
352
439
|
assert_raises(Errno::EBADF) do
|
353
440
|
machine.write(r.fileno, 'foo')
|
354
441
|
end
|
442
|
+
assert_equal 0, machine.pending_count
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
class Closetest < UMBaseTest
|
447
|
+
def test_close
|
448
|
+
r, w = IO.pipe
|
449
|
+
machine.write(w.fileno, 'foo')
|
450
|
+
assert_equal 'foo', r.readpartial(3)
|
451
|
+
|
452
|
+
assert_equal 0, machine.pending_count
|
453
|
+
machine.close(w.fileno)
|
454
|
+
assert_equal 0, machine.pending_count
|
455
|
+
assert_equal '', r.read
|
456
|
+
|
457
|
+
assert_raises(Errno::EBADF) { machine.close(w.fileno) }
|
355
458
|
end
|
356
459
|
end
|
357
460
|
|
358
461
|
class AcceptTest < UMBaseTest
|
359
462
|
def setup
|
360
463
|
super
|
361
|
-
@port =
|
464
|
+
@port = assign_port
|
362
465
|
@server = TCPServer.open('127.0.0.1', @port)
|
363
466
|
end
|
364
467
|
|
@@ -370,7 +473,9 @@ class AcceptTest < UMBaseTest
|
|
370
473
|
def test_accept
|
371
474
|
conn = TCPSocket.new('127.0.0.1', @port)
|
372
475
|
|
476
|
+
assert_equal 0, machine.pending_count
|
373
477
|
fd = machine.accept(@server.fileno)
|
478
|
+
assert_equal 0, machine.pending_count
|
374
479
|
assert_kind_of Integer, fd
|
375
480
|
assert fd > 0
|
376
481
|
|
@@ -384,7 +489,7 @@ end
|
|
384
489
|
class AcceptEachTest < UMBaseTest
|
385
490
|
def setup
|
386
491
|
super
|
387
|
-
@port =
|
492
|
+
@port = assign_port
|
388
493
|
@server = TCPServer.open('127.0.0.1', @port)
|
389
494
|
end
|
390
495
|
|
@@ -394,21 +499,555 @@ class AcceptEachTest < UMBaseTest
|
|
394
499
|
end
|
395
500
|
|
396
501
|
def test_accept_each
|
397
|
-
conns =
|
502
|
+
conns = []
|
503
|
+
t = Thread.new do
|
504
|
+
sleep 0.05
|
505
|
+
3.times { conns << TCPSocket.new('127.0.0.1', @port) }
|
506
|
+
end
|
398
507
|
|
399
508
|
count = 0
|
400
509
|
machine.accept_each(@server.fileno) do |fd|
|
401
|
-
|
510
|
+
count += 1
|
402
511
|
break if count == 3
|
403
512
|
end
|
404
513
|
|
405
514
|
assert_equal 3, count
|
406
|
-
assert_equal 1, machine.pending_count
|
407
|
-
machine.snooze
|
408
515
|
assert_equal 0, machine.pending_count
|
516
|
+
ensure
|
517
|
+
t&.kill
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
class SocketTest < UMBaseTest
|
522
|
+
def test_socket
|
523
|
+
assert_equal 0, machine.pending_count
|
524
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0);
|
525
|
+
assert_equal 0, machine.pending_count
|
526
|
+
assert_kind_of Integer, fd
|
527
|
+
assert fd > 0
|
528
|
+
|
529
|
+
assert_raises(Errno::EDESTADDRREQ) { machine.write(fd, 'foo') }
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
class ConnectTest < UMBaseTest
|
534
|
+
def setup
|
535
|
+
super
|
536
|
+
@port = assign_port
|
537
|
+
@server = TCPServer.open('127.0.0.1', @port)
|
538
|
+
end
|
539
|
+
|
540
|
+
def teardown
|
541
|
+
@server&.close
|
542
|
+
super
|
543
|
+
end
|
544
|
+
|
545
|
+
def test_connect
|
546
|
+
t = Thread.new do
|
547
|
+
conn = @server.accept
|
548
|
+
conn.write('foobar')
|
549
|
+
sleep
|
550
|
+
end
|
551
|
+
|
552
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
553
|
+
assert_equal 0, machine.pending_count
|
554
|
+
res = machine.connect(fd, '127.0.0.1', @port)
|
555
|
+
assert_equal 0, machine.pending_count
|
556
|
+
assert_equal 0, res
|
557
|
+
|
558
|
+
buf = +''
|
559
|
+
res = machine.read(fd, buf, 42)
|
560
|
+
assert_equal 6, res
|
561
|
+
assert_equal 'foobar', buf
|
562
|
+
ensure
|
563
|
+
t&.kill
|
564
|
+
end
|
565
|
+
|
566
|
+
def test_connect_with_bad_addr
|
567
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0);
|
568
|
+
assert_equal 0, machine.pending_count
|
569
|
+
assert_raises(Errno::ENETUNREACH) { machine.connect(fd, 'a.b.c.d', @port) }
|
570
|
+
assert_equal 0, machine.pending_count
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
574
|
+
class SendTest < UMBaseTest
|
575
|
+
def setup
|
576
|
+
super
|
577
|
+
@port = assign_port
|
578
|
+
@server = TCPServer.open('127.0.0.1', @port)
|
579
|
+
end
|
580
|
+
|
581
|
+
def teardown
|
582
|
+
@server&.close
|
583
|
+
super
|
584
|
+
end
|
585
|
+
|
586
|
+
def test_send
|
587
|
+
t = Thread.new do
|
588
|
+
conn = @server.accept
|
589
|
+
str = conn.readpartial(42)
|
590
|
+
conn.write("You said: #{str}")
|
591
|
+
sleep
|
592
|
+
end
|
593
|
+
|
594
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
595
|
+
res = machine.connect(fd, '127.0.0.1', @port)
|
596
|
+
assert_equal 0, res
|
597
|
+
|
598
|
+
res = machine.send(fd, 'foobar', 6, 0)
|
599
|
+
assert_equal 6, res
|
600
|
+
|
601
|
+
buf = +''
|
602
|
+
res = machine.read(fd, buf, 42)
|
603
|
+
assert_equal 16, res
|
604
|
+
assert_equal 'You said: foobar', buf
|
605
|
+
ensure
|
606
|
+
t&.kill
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
class RecvTest < UMBaseTest
|
611
|
+
def setup
|
612
|
+
super
|
613
|
+
@port = assign_port
|
614
|
+
@server = TCPServer.open('127.0.0.1', @port)
|
615
|
+
end
|
616
|
+
|
617
|
+
def teardown
|
618
|
+
@server&.close
|
619
|
+
super
|
620
|
+
end
|
621
|
+
|
622
|
+
def test_recv
|
623
|
+
t = Thread.new do
|
624
|
+
conn = @server.accept
|
625
|
+
conn.write('foobar')
|
626
|
+
sleep
|
627
|
+
end
|
628
|
+
|
629
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
630
|
+
res = machine.connect(fd, '127.0.0.1', @port)
|
631
|
+
assert_equal 0, res
|
632
|
+
|
633
|
+
buf = +''
|
634
|
+
res = machine.recv(fd, buf, 42, 0)
|
635
|
+
assert_equal 6, res
|
636
|
+
assert_equal 'foobar', buf
|
637
|
+
ensure
|
638
|
+
t&.kill
|
639
|
+
end
|
640
|
+
end
|
641
|
+
|
642
|
+
class RecvEachTest < UMBaseTest
|
643
|
+
def setup
|
644
|
+
super
|
645
|
+
@port = assign_port
|
646
|
+
@server = TCPServer.open('127.0.0.1', @port)
|
647
|
+
end
|
648
|
+
|
649
|
+
def teardown
|
650
|
+
@server&.close
|
651
|
+
super
|
652
|
+
end
|
653
|
+
|
654
|
+
def test_recv_each
|
655
|
+
t = Thread.new do
|
656
|
+
conn = @server.accept
|
657
|
+
conn.write('abc')
|
658
|
+
sleep 0.01
|
659
|
+
conn.write('def')
|
660
|
+
sleep 0.01
|
661
|
+
conn.write('ghi')
|
662
|
+
sleep 0.01
|
663
|
+
conn.close
|
664
|
+
sleep
|
665
|
+
end
|
666
|
+
|
667
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
668
|
+
res = machine.connect(fd, '127.0.0.1', @port)
|
669
|
+
assert_equal 0, res
|
670
|
+
|
671
|
+
bgid = machine.setup_buffer_ring(4096, 1024)
|
672
|
+
assert_equal 0, bgid
|
673
|
+
|
674
|
+
bgid2 = machine.setup_buffer_ring(4096, 1024)
|
675
|
+
assert_equal 1, bgid2
|
676
|
+
|
677
|
+
bufs = []
|
678
|
+
|
679
|
+
machine.recv_each(fd, bgid, 0) do |buf|
|
680
|
+
bufs << buf
|
681
|
+
end
|
682
|
+
assert_equal ['abc', 'def', 'ghi'], bufs
|
683
|
+
ensure
|
684
|
+
t&.kill
|
685
|
+
end
|
686
|
+
end
|
687
|
+
|
688
|
+
class BindTest < UMBaseTest
|
689
|
+
def setup
|
690
|
+
super
|
691
|
+
@port = assign_port
|
692
|
+
end
|
693
|
+
|
694
|
+
def test_bind
|
695
|
+
assert_equal 0, machine.pending_count
|
696
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0)
|
697
|
+
res = machine.bind(fd, '127.0.0.1', @port)
|
698
|
+
assert_equal 0, res
|
699
|
+
assert_equal 0, machine.pending_count
|
700
|
+
|
701
|
+
peer = UDPSocket.new
|
702
|
+
peer.connect('127.0.0.1', @port)
|
703
|
+
peer.send 'foo', 0
|
704
|
+
|
705
|
+
buf = +''
|
706
|
+
res = machine.recv(fd, buf, 8192, 0)
|
707
|
+
assert_equal 3, res
|
708
|
+
assert_equal 'foo', buf
|
709
|
+
end
|
710
|
+
|
711
|
+
def test_bind_invalid_args
|
712
|
+
assert_equal 0, machine.pending_count
|
713
|
+
|
714
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0)
|
715
|
+
assert_raises(Errno::EACCES) { machine.bind(fd, 'foo.bar.baz', 3) }
|
716
|
+
assert_raises(Errno::EBADF) { machine.bind(-3, '127.0.01', 1234) }
|
717
|
+
|
718
|
+
assert_equal 0, machine.pending_count
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
class ListenTest < UMBaseTest
|
723
|
+
def setup
|
724
|
+
super
|
725
|
+
@port = assign_port
|
726
|
+
end
|
727
|
+
|
728
|
+
def test_listen
|
729
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
730
|
+
machine.bind(fd, '127.0.0.1', @port)
|
731
|
+
res = machine.listen(fd, 5)
|
732
|
+
assert_equal 0, res
|
733
|
+
assert_equal 0, machine.pending_count
|
734
|
+
|
735
|
+
conn = nil
|
736
|
+
t = Thread.new do
|
737
|
+
sleep 0.01
|
738
|
+
conn = TCPSocket.new('127.0.0.1', @port)
|
739
|
+
end
|
740
|
+
|
741
|
+
conn_fd = machine.accept(fd)
|
742
|
+
t.join
|
743
|
+
assert_kind_of TCPSocket, conn
|
744
|
+
|
745
|
+
machine.send(conn_fd, 'foo', 3, 0)
|
746
|
+
|
747
|
+
buf = conn.readpartial(42)
|
748
|
+
assert_equal 'foo', buf
|
749
|
+
ensure
|
750
|
+
t&.kill
|
751
|
+
end
|
752
|
+
end
|
753
|
+
|
754
|
+
class ConstTest < UMBaseTest
|
755
|
+
def test_constants
|
756
|
+
assert_equal UM::SOCK_STREAM, UM::SOCK_STREAM
|
757
|
+
end
|
758
|
+
end
|
759
|
+
|
760
|
+
class GetSetSockOptTest < UMBaseTest
|
761
|
+
def test_getsockopt_setsockopt
|
762
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
763
|
+
reuseaddr = machine.getsockopt(fd, UM::SOL_SOCKET, UM::SO_REUSEADDR)
|
764
|
+
assert_equal 0, reuseaddr
|
765
|
+
|
766
|
+
res = machine.setsockopt(fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
|
767
|
+
assert_equal 0, res
|
768
|
+
|
769
|
+
reuseaddr = machine.getsockopt(fd, UM::SOL_SOCKET, UM::SO_REUSEADDR)
|
770
|
+
assert_equal 1, reuseaddr
|
771
|
+
end
|
772
|
+
end
|
773
|
+
|
774
|
+
class SynchronizeTest < UMBaseTest
|
775
|
+
def test_synchronize_single
|
776
|
+
skip if !machine.respond_to?(:synchronize)
|
777
|
+
|
778
|
+
m = UM::Mutex.new
|
779
|
+
|
780
|
+
buf = []
|
781
|
+
machine.synchronize(m) do
|
782
|
+
buf << 1
|
783
|
+
end
|
784
|
+
machine.synchronize(m) do
|
785
|
+
buf << 2
|
786
|
+
end
|
787
|
+
|
788
|
+
assert_equal [1, 2], buf
|
789
|
+
assert_equal 0, machine.pending_count
|
790
|
+
end
|
791
|
+
|
792
|
+
def test_synchronize_pair
|
793
|
+
skip if !machine.respond_to?(:synchronize)
|
794
|
+
m = UM::Mutex.new
|
795
|
+
|
796
|
+
buf = []
|
797
|
+
|
798
|
+
f1 = Fiber.new do
|
799
|
+
machine.synchronize(m) do
|
800
|
+
buf << 11
|
801
|
+
machine.sleep(0.01)
|
802
|
+
buf << 12
|
803
|
+
end
|
804
|
+
buf << 13
|
805
|
+
machine.yield
|
806
|
+
end
|
807
|
+
|
808
|
+
f2 = Fiber.new do
|
809
|
+
machine.synchronize(m) do
|
810
|
+
buf << 21
|
811
|
+
machine.sleep(0.01)
|
812
|
+
buf << 22
|
813
|
+
end
|
814
|
+
buf << 23
|
815
|
+
machine.yield
|
816
|
+
end
|
817
|
+
|
818
|
+
machine.schedule(f1, nil)
|
819
|
+
machine.schedule(f2, nil)
|
820
|
+
|
821
|
+
machine.sleep(0.03)
|
822
|
+
assert_equal [11, 12, 13, 21, 22, 23], buf
|
823
|
+
assert_equal 0, machine.pending_count
|
824
|
+
end
|
825
|
+
end
|
826
|
+
|
827
|
+
class QueueTest < UMBaseTest
|
828
|
+
def test_push_pop_1
|
829
|
+
skip if !machine.respond_to?(:synchronize)
|
830
|
+
|
831
|
+
q = UM::Queue.new
|
832
|
+
assert_equal 0, q.count
|
833
|
+
machine.push(q, :foo)
|
834
|
+
machine.push(q, :bar)
|
835
|
+
assert_equal 2, q.count
|
836
|
+
|
837
|
+
assert_equal :bar, machine.pop(q)
|
838
|
+
assert_equal 1, q.count
|
839
|
+
assert_equal :foo, machine.pop(q)
|
840
|
+
assert_equal 0, q.count
|
841
|
+
end
|
842
|
+
|
843
|
+
def test_push_pop_2
|
844
|
+
skip if !machine.respond_to?(:synchronize)
|
845
|
+
|
846
|
+
q = UM::Queue.new
|
847
|
+
buf = []
|
409
848
|
|
410
|
-
|
411
|
-
|
412
|
-
|
849
|
+
f1 = Fiber.new do
|
850
|
+
buf << [1, machine.pop(q)]
|
851
|
+
machine.yield
|
852
|
+
end
|
853
|
+
|
854
|
+
machine.schedule(f1, nil)
|
855
|
+
|
856
|
+
f2 = Fiber.new do
|
857
|
+
buf << [2, machine.pop(q)]
|
858
|
+
machine.yield
|
859
|
+
end
|
860
|
+
|
861
|
+
machine.schedule(f2, nil)
|
862
|
+
|
863
|
+
machine.snooze
|
864
|
+
assert_equal [], buf
|
865
|
+
|
866
|
+
machine.push(q, :foo)
|
867
|
+
assert_equal 1, q.count
|
868
|
+
machine.sleep(0.02)
|
869
|
+
assert_equal [[1, :foo]], buf
|
870
|
+
|
871
|
+
machine.push(q, :bar)
|
872
|
+
assert_equal 1, q.count
|
873
|
+
|
874
|
+
machine.sleep(0.02)
|
875
|
+
assert_equal [[1, :foo], [2, :bar]], buf
|
876
|
+
assert_equal 0, q.count
|
877
|
+
end
|
878
|
+
|
879
|
+
def test_push_pop_3
|
880
|
+
skip if !machine.respond_to?(:synchronize)
|
881
|
+
|
882
|
+
q = UM::Queue.new
|
883
|
+
buf = []
|
884
|
+
|
885
|
+
machine.push(q, :foo)
|
886
|
+
machine.push(q, :bar)
|
887
|
+
assert_equal 2, q.count
|
888
|
+
|
889
|
+
f1 = Fiber.new do
|
890
|
+
buf << [1, machine.pop(q)]
|
891
|
+
machine.yield
|
892
|
+
end
|
893
|
+
machine.schedule(f1, nil)
|
894
|
+
|
895
|
+
f2 = Fiber.new do
|
896
|
+
buf << [2, machine.pop(q)]
|
897
|
+
machine.yield
|
898
|
+
end
|
899
|
+
machine.schedule(f2, nil)
|
900
|
+
|
901
|
+
3.times { machine.snooze }
|
902
|
+
|
903
|
+
assert_equal [[1, :bar], [2, :foo]], buf.sort
|
904
|
+
assert_equal 0, q.count
|
905
|
+
end
|
906
|
+
|
907
|
+
def test_push_pop_4
|
908
|
+
skip if !machine.respond_to?(:synchronize)
|
909
|
+
|
910
|
+
q = UM::Queue.new
|
911
|
+
buf = []
|
912
|
+
|
913
|
+
machine.push(q, :foo)
|
914
|
+
assert_equal 1, q.count
|
915
|
+
|
916
|
+
f1 = Fiber.new do
|
917
|
+
buf << [1, machine.pop(q)]
|
918
|
+
machine.yield
|
919
|
+
end
|
920
|
+
machine.schedule(f1, nil)
|
921
|
+
|
922
|
+
f2 = Fiber.new do
|
923
|
+
buf << [2, machine.pop(q)]
|
924
|
+
machine.yield
|
925
|
+
end
|
926
|
+
machine.schedule(f2, nil)
|
927
|
+
|
928
|
+
machine.sleep 0.01
|
929
|
+
|
930
|
+
assert_equal [[1, :foo]], buf
|
931
|
+
machine.push(q, :bar)
|
932
|
+
|
933
|
+
machine.sleep 0.01
|
934
|
+
assert_equal [[1, :foo], [2, :bar]], buf
|
935
|
+
end
|
936
|
+
|
937
|
+
def test_push_shift_1
|
938
|
+
skip if !machine.respond_to?(:synchronize)
|
939
|
+
|
940
|
+
q = UM::Queue.new
|
941
|
+
|
942
|
+
machine.push(q, :foo)
|
943
|
+
machine.push(q, :bar)
|
944
|
+
machine.push(q, :baz)
|
945
|
+
|
946
|
+
assert_equal :foo, machine.shift(q)
|
947
|
+
assert_equal :bar, machine.shift(q)
|
948
|
+
assert_equal :baz, machine.shift(q)
|
949
|
+
end
|
950
|
+
|
951
|
+
def test_shift_shift_1
|
952
|
+
skip if !machine.respond_to?(:synchronize)
|
953
|
+
|
954
|
+
q = UM::Queue.new
|
955
|
+
|
956
|
+
machine.unshift(q, :foo)
|
957
|
+
machine.unshift(q, :bar)
|
958
|
+
machine.unshift(q, :baz)
|
959
|
+
|
960
|
+
assert_equal :baz, machine.shift(q)
|
961
|
+
assert_equal :bar, machine.shift(q)
|
962
|
+
assert_equal :foo, machine.shift(q)
|
413
963
|
end
|
414
964
|
end
|
965
|
+
|
966
|
+
class OpenTest < UMBaseTest
|
967
|
+
PATH = '/tmp/um_open_test'
|
968
|
+
|
969
|
+
def setup
|
970
|
+
super
|
971
|
+
FileUtils.rm(PATH, force: true)
|
972
|
+
end
|
973
|
+
|
974
|
+
def test_open
|
975
|
+
fd = machine.open(PATH, UM::O_CREAT | UM::O_WRONLY)
|
976
|
+
assert_kind_of Integer, fd
|
977
|
+
assert File.file?(PATH)
|
978
|
+
|
979
|
+
machine.write(fd, 'foo')
|
980
|
+
machine.close(fd)
|
981
|
+
|
982
|
+
assert_equal 'foo', IO.read(PATH)
|
983
|
+
end
|
984
|
+
|
985
|
+
def test_open_with_block
|
986
|
+
res = machine.open(PATH, UM::O_CREAT | UM::O_WRONLY) do |fd|
|
987
|
+
machine.write(fd, 'bar')
|
988
|
+
fd
|
989
|
+
end
|
990
|
+
|
991
|
+
assert_kind_of Integer, res
|
992
|
+
assert_raises(Errno::EBADF) { machine.close(res) }
|
993
|
+
assert_equal 'bar', IO.read(PATH)
|
994
|
+
end
|
995
|
+
|
996
|
+
def test_open_bad_arg
|
997
|
+
assert_raises(Errno::ENOENT) { machine.open(PATH, UM::O_RDONLY) }
|
998
|
+
assert_raises(Errno::ENOENT) { machine.open(PATH, UM::O_RDONLY) {} }
|
999
|
+
end
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
class PipeTest < UMBaseTest
|
1003
|
+
def test_pipe
|
1004
|
+
rfd, wfd = UM.pipe
|
1005
|
+
ret = machine.write(wfd, 'foo')
|
1006
|
+
assert_equal 3, ret
|
1007
|
+
|
1008
|
+
ret = machine.close(wfd)
|
1009
|
+
assert_equal wfd, ret
|
1010
|
+
|
1011
|
+
buf = +''
|
1012
|
+
ret = machine.read(rfd, buf, 8192)
|
1013
|
+
|
1014
|
+
assert_equal 3, ret
|
1015
|
+
assert_equal 'foo', buf
|
1016
|
+
|
1017
|
+
ret = machine.close(rfd)
|
1018
|
+
assert_equal rfd, ret
|
1019
|
+
end
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
class WaitTest < UMBaseTest
|
1023
|
+
def test_waitpid
|
1024
|
+
skip if UM.kernel_version < 607
|
1025
|
+
|
1026
|
+
msg = 'hello from child'
|
1027
|
+
|
1028
|
+
rfd, wfd = UM.pipe
|
1029
|
+
pid = fork do
|
1030
|
+
m = UM.new
|
1031
|
+
m.write(wfd, msg)
|
1032
|
+
m.close(wfd)
|
1033
|
+
exit 42
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
ret = machine.waitpid(pid, UM::WEXITED)
|
1037
|
+
assert_kind_of Array, ret
|
1038
|
+
assert_equal [pid, 42], ret
|
1039
|
+
|
1040
|
+
buf = +''
|
1041
|
+
ret = machine.read(rfd, buf, 8192)
|
1042
|
+
assert_equal msg.bytesize, ret
|
1043
|
+
assert_equal msg, buf
|
1044
|
+
end
|
1045
|
+
|
1046
|
+
def test_waitpid_bad_pid
|
1047
|
+
skip if UM.kernel_version < 607
|
1048
|
+
|
1049
|
+
assert_raises(Errno::ECHILD) { machine.waitpid(1, UM::WEXITED) }
|
1050
|
+
end
|
1051
|
+
|
1052
|
+
end
|
1053
|
+
|