uringmachine 0.4 → 0.5.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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +2 -1
- data/CHANGELOG.md +16 -0
- data/README.md +44 -1
- data/TODO.md +12 -3
- data/examples/bm_snooze.rb +89 -0
- data/examples/bm_sqlite.rb +89 -0
- data/examples/bm_write.rb +56 -0
- data/examples/dns_client.rb +12 -0
- data/examples/http_server.rb +42 -43
- data/examples/pg.rb +85 -0
- data/examples/server_client.rb +64 -0
- data/examples/snooze.rb +44 -0
- data/examples/stream.rb +85 -0
- data/examples/write_dev_null.rb +16 -0
- data/ext/um/extconf.rb +81 -14
- data/ext/um/um.c +468 -414
- data/ext/um/um.h +149 -40
- data/ext/um/um_async_op.c +40 -0
- data/ext/um/um_async_op_class.c +136 -0
- data/ext/um/um_buffer.c +49 -0
- data/ext/um/um_class.c +176 -44
- data/ext/um/um_const.c +174 -9
- data/ext/um/um_ext.c +8 -0
- data/ext/um/um_mutex_class.c +47 -0
- data/ext/um/um_op.c +89 -111
- data/ext/um/um_queue_class.c +58 -0
- data/ext/um/um_ssl.c +850 -0
- data/ext/um/um_ssl.h +22 -0
- data/ext/um/um_ssl_class.c +138 -0
- data/ext/um/um_sync.c +273 -0
- data/ext/um/um_utils.c +1 -1
- data/lib/uringmachine/dns_resolver.rb +84 -0
- data/lib/uringmachine/ssl/context_builder.rb +96 -0
- data/lib/uringmachine/ssl.rb +394 -0
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +27 -3
- data/supressions/ruby.supp +71 -0
- data/test/helper.rb +6 -0
- data/test/test_async_op.rb +119 -0
- data/test/test_ssl.rb +155 -0
- data/test/test_um.rb +464 -47
- data/uringmachine.gemspec +3 -2
- data/vendor/liburing/.gitignore +5 -0
- data/vendor/liburing/CHANGELOG +1 -0
- data/vendor/liburing/configure +32 -0
- data/vendor/liburing/examples/Makefile +1 -0
- data/vendor/liburing/examples/reg-wait.c +159 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/include/liburing/io_uring.h +48 -2
- data/vendor/liburing/src/include/liburing.h +28 -2
- data/vendor/liburing/src/int_flags.h +10 -3
- data/vendor/liburing/src/liburing-ffi.map +13 -2
- data/vendor/liburing/src/liburing.map +9 -0
- data/vendor/liburing/src/queue.c +25 -16
- data/vendor/liburing/src/register.c +73 -4
- data/vendor/liburing/src/setup.c +46 -18
- data/vendor/liburing/src/setup.h +6 -0
- data/vendor/liburing/test/Makefile +7 -0
- data/vendor/liburing/test/cmd-discard.c +427 -0
- data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
- data/vendor/liburing/test/file-exit-unreg.c +48 -0
- data/vendor/liburing/test/io_uring_passthrough.c +2 -0
- data/vendor/liburing/test/io_uring_register.c +13 -2
- data/vendor/liburing/test/napi-test.c +1 -1
- data/vendor/liburing/test/no-mmap-inval.c +1 -1
- data/vendor/liburing/test/read-mshot-empty.c +2 -0
- data/vendor/liburing/test/read-mshot-stdin.c +121 -0
- data/vendor/liburing/test/read-mshot.c +6 -0
- data/vendor/liburing/test/recvsend_bundle.c +2 -2
- data/vendor/liburing/test/reg-fd-only.c +1 -1
- data/vendor/liburing/test/reg-wait.c +251 -0
- data/vendor/liburing/test/regbuf-clone.c +458 -0
- data/vendor/liburing/test/resize-rings.c +643 -0
- data/vendor/liburing/test/rsrc_tags.c +1 -1
- data/vendor/liburing/test/sqpoll-sleep.c +39 -8
- data/vendor/liburing/test/sqwait.c +136 -0
- data/vendor/liburing/test/sync-cancel.c +8 -1
- data/vendor/liburing/test/timeout.c +13 -8
- metadata +52 -8
- 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
|
@@ -167,6 +182,34 @@ class SleepTest < UMBaseTest
|
|
167
182
|
assert_in_range 0.09..0.13, t1 - t0
|
168
183
|
assert_equal 0.1, res
|
169
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
|
170
213
|
end
|
171
214
|
|
172
215
|
class ReadTest < UMBaseTest
|
@@ -199,6 +242,7 @@ class ReadTest < UMBaseTest
|
|
199
242
|
assert_raises(Errno::EBADF) do
|
200
243
|
machine.read(w.fileno, +'', 8192)
|
201
244
|
end
|
245
|
+
assert_equal 0, machine.pending_count
|
202
246
|
end
|
203
247
|
|
204
248
|
def test_read_with_buffer_offset
|
@@ -234,22 +278,24 @@ end
|
|
234
278
|
|
235
279
|
class ReadEachTest < UMBaseTest
|
236
280
|
def test_read_each
|
281
|
+
skip if UringMachine.kernel_version < 607
|
282
|
+
|
237
283
|
r, w = IO.pipe
|
238
284
|
bufs = []
|
239
|
-
|
240
285
|
bgid = machine.setup_buffer_ring(4096, 1024)
|
241
286
|
assert_equal 0, bgid
|
242
287
|
|
243
288
|
f = Fiber.new do
|
244
289
|
w << 'foo'
|
245
|
-
machine.
|
290
|
+
machine.sleep 0.02
|
246
291
|
w << 'bar'
|
247
|
-
machine.
|
292
|
+
machine.sleep 0.02
|
248
293
|
w << 'baz'
|
249
|
-
machine.
|
294
|
+
machine.sleep 0.02
|
250
295
|
w.close
|
251
296
|
machine.yield
|
252
297
|
end
|
298
|
+
|
253
299
|
machine.schedule(f, nil)
|
254
300
|
|
255
301
|
machine.read_each(r.fileno, bgid) do |buf|
|
@@ -262,8 +308,9 @@ class ReadEachTest < UMBaseTest
|
|
262
308
|
|
263
309
|
# send once and close write fd
|
264
310
|
def test_read_each_raising_1
|
265
|
-
|
311
|
+
skip if UringMachine.kernel_version < 607
|
266
312
|
|
313
|
+
r, w = IO.pipe
|
267
314
|
bgid = machine.setup_buffer_ring(4096, 1024)
|
268
315
|
assert_equal 0, bgid
|
269
316
|
|
@@ -285,8 +332,9 @@ class ReadEachTest < UMBaseTest
|
|
285
332
|
|
286
333
|
# send once and leave write fd open
|
287
334
|
def test_read_each_raising_2
|
288
|
-
|
335
|
+
skip if UringMachine.kernel_version < 607
|
289
336
|
|
337
|
+
r, w = IO.pipe
|
290
338
|
bgid = machine.setup_buffer_ring(4096, 1024)
|
291
339
|
assert_equal 0, bgid
|
292
340
|
|
@@ -303,17 +351,15 @@ class ReadEachTest < UMBaseTest
|
|
303
351
|
assert_kind_of RuntimeError, e
|
304
352
|
assert_equal 'hi', e.message
|
305
353
|
|
306
|
-
#
|
307
|
-
# the op, which is done asynchronously.
|
308
|
-
assert_equal 1, machine.pending_count
|
309
|
-
machine.snooze
|
354
|
+
machine.snooze # in case the final CQE has not yet arrived
|
310
355
|
assert_equal 0, machine.pending_count
|
311
356
|
end
|
312
357
|
|
313
358
|
# send twice
|
314
359
|
def test_read_each_raising_3
|
315
|
-
|
360
|
+
skip if UringMachine.kernel_version < 607
|
316
361
|
|
362
|
+
r, w = IO.pipe
|
317
363
|
bgid = machine.setup_buffer_ring(4096, 1024)
|
318
364
|
assert_equal 0, bgid
|
319
365
|
|
@@ -331,12 +377,46 @@ class ReadEachTest < UMBaseTest
|
|
331
377
|
assert_kind_of RuntimeError, e
|
332
378
|
assert_equal 'hi', e.message
|
333
379
|
|
334
|
-
#
|
335
|
-
# the op, which is done asynchronously.
|
336
|
-
assert_equal 1, machine.pending_count
|
337
|
-
machine.snooze
|
380
|
+
machine.snooze # in case the final CQE has not yet arrived
|
338
381
|
assert_equal 0, machine.pending_count
|
339
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
|
340
420
|
end
|
341
421
|
|
342
422
|
class WriteTest < UMBaseTest
|
@@ -421,7 +501,7 @@ class AcceptEachTest < UMBaseTest
|
|
421
501
|
def test_accept_each
|
422
502
|
conns = []
|
423
503
|
t = Thread.new do
|
424
|
-
sleep 0.
|
504
|
+
sleep 0.05
|
425
505
|
3.times { conns << TCPSocket.new('127.0.0.1', @port) }
|
426
506
|
end
|
427
507
|
|
@@ -432,8 +512,6 @@ class AcceptEachTest < UMBaseTest
|
|
432
512
|
end
|
433
513
|
|
434
514
|
assert_equal 3, count
|
435
|
-
assert_equal 1, machine.pending_count
|
436
|
-
machine.snooze
|
437
515
|
assert_equal 0, machine.pending_count
|
438
516
|
ensure
|
439
517
|
t&.kill
|
@@ -471,7 +549,7 @@ class ConnectTest < UMBaseTest
|
|
471
549
|
sleep
|
472
550
|
end
|
473
551
|
|
474
|
-
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
552
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
475
553
|
assert_equal 0, machine.pending_count
|
476
554
|
res = machine.connect(fd, '127.0.0.1', @port)
|
477
555
|
assert_equal 0, machine.pending_count
|
@@ -513,7 +591,7 @@ class SendTest < UMBaseTest
|
|
513
591
|
sleep
|
514
592
|
end
|
515
593
|
|
516
|
-
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
594
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
517
595
|
res = machine.connect(fd, '127.0.0.1', @port)
|
518
596
|
assert_equal 0, res
|
519
597
|
|
@@ -548,7 +626,7 @@ class RecvTest < UMBaseTest
|
|
548
626
|
sleep
|
549
627
|
end
|
550
628
|
|
551
|
-
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
629
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
552
630
|
res = machine.connect(fd, '127.0.0.1', @port)
|
553
631
|
assert_equal 0, res
|
554
632
|
|
@@ -561,6 +639,52 @@ class RecvTest < UMBaseTest
|
|
561
639
|
end
|
562
640
|
end
|
563
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
|
+
|
564
688
|
class BindTest < UMBaseTest
|
565
689
|
def setup
|
566
690
|
super
|
@@ -569,7 +693,7 @@ class BindTest < UMBaseTest
|
|
569
693
|
|
570
694
|
def test_bind
|
571
695
|
assert_equal 0, machine.pending_count
|
572
|
-
fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0)
|
696
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0)
|
573
697
|
res = machine.bind(fd, '127.0.0.1', @port)
|
574
698
|
assert_equal 0, res
|
575
699
|
assert_equal 0, machine.pending_count
|
@@ -587,7 +711,7 @@ class BindTest < UMBaseTest
|
|
587
711
|
def test_bind_invalid_args
|
588
712
|
assert_equal 0, machine.pending_count
|
589
713
|
|
590
|
-
fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0)
|
714
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_DGRAM, 0, 0)
|
591
715
|
assert_raises(Errno::EACCES) { machine.bind(fd, 'foo.bar.baz', 3) }
|
592
716
|
assert_raises(Errno::EBADF) { machine.bind(-3, '127.0.01', 1234) }
|
593
717
|
|
@@ -602,7 +726,7 @@ class ListenTest < UMBaseTest
|
|
602
726
|
end
|
603
727
|
|
604
728
|
def test_listen
|
605
|
-
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
729
|
+
fd = machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
|
606
730
|
machine.bind(fd, '127.0.0.1', @port)
|
607
731
|
res = machine.listen(fd, 5)
|
608
732
|
assert_equal 0, res
|
@@ -631,4 +755,297 @@ class ConstTest < UMBaseTest
|
|
631
755
|
def test_constants
|
632
756
|
assert_equal UM::SOCK_STREAM, UM::SOCK_STREAM
|
633
757
|
end
|
634
|
-
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 = []
|
848
|
+
|
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)
|
963
|
+
end
|
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
|
+
end
|
data/uringmachine.gemspec
CHANGED
@@ -20,8 +20,9 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
s.required_ruby_version = '>= 3.3'
|
22
22
|
|
23
|
-
s.add_development_dependency 'rake-compiler', '1.2.
|
23
|
+
s.add_development_dependency 'rake-compiler', '1.2.8'
|
24
24
|
s.add_development_dependency 'minitest', '5.25.1'
|
25
25
|
s.add_development_dependency 'http_parser.rb', '0.8.0'
|
26
|
-
s.add_development_dependency 'benchmark-ips', '2.
|
26
|
+
s.add_development_dependency 'benchmark-ips', '2.14.0'
|
27
|
+
s.add_development_dependency 'localhost', '1.3.1'
|
27
28
|
end
|
data/vendor/liburing/.gitignore
CHANGED
@@ -27,11 +27,16 @@
|
|
27
27
|
/examples/send-zerocopy
|
28
28
|
/examples/rsrc-update-bench
|
29
29
|
/examples/kdigest
|
30
|
+
/examples/reg-wait
|
30
31
|
|
31
32
|
/test/*.t
|
32
33
|
/test/*.dmesg
|
33
34
|
/test/output/
|
34
35
|
|
36
|
+
# Clang's compilation database file and directory.
|
37
|
+
/.cache
|
38
|
+
/compile_commands.json
|
39
|
+
|
35
40
|
config-host.h
|
36
41
|
config-host.mak
|
37
42
|
config.log
|