uringmachine 0.1 → 0.3

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.
data/test/test_iou.rb DELETED
@@ -1,876 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'helper'
4
- require 'socket'
5
-
6
- class IOURingTest < IOURingBaseTest
7
- def test_close
8
- ring2 = IOU::Ring.new
9
- refute ring2.closed?
10
-
11
- ring2.close
12
- assert ring2.closed?
13
- end
14
-
15
- def test_pending_ops
16
- assert_equal({}, ring.pending_ops)
17
-
18
- id = ring.prep_timeout(interval: 1)
19
- spec = ring.pending_ops[id].spec
20
- assert_equal id, spec[:id]
21
- assert_equal :timeout, spec[:op]
22
- assert_equal 1, spec[:interval]
23
-
24
- ring.prep_cancel(id)
25
- ring.submit
26
- ring.process_completions(true)
27
-
28
- assert_nil ring.pending_ops[id]
29
- end
30
- end
31
-
32
- class PrepTimeoutTest < IOURingBaseTest
33
- def test_prep_timeout
34
- interval = 0.03
35
-
36
- t0 = monotonic_clock
37
- id = ring.prep_timeout(interval: interval)
38
- assert_equal 1, id
39
-
40
- ring.submit
41
- c = ring.wait_for_completion
42
- elapsed = monotonic_clock - t0
43
- assert_in_range interval..(interval + 0.02), elapsed
44
-
45
- assert_kind_of Hash, c
46
- assert_equal id, c[:id]
47
- assert_equal :timeout, c[:op]
48
- assert_equal interval, c[:interval]
49
- assert_equal (-Errno::ETIME::Errno), c[:result]
50
- end
51
-
52
- def test_prep_timeout_invalid_args
53
- assert_raises(ArgumentError) { ring.prep_timeout() }
54
- assert_raises(ArgumentError) { ring.prep_timeout(foo: 1) }
55
- assert_raises(ArgumentError) { ring.prep_timeout(1) }
56
- end
57
- end
58
-
59
- class PrepCancelTest < IOURingBaseTest
60
- def test_prep_cancel
61
- interval = 15
62
- timeout_id = ring.prep_timeout(interval: interval)
63
- assert_equal 1, timeout_id
64
-
65
- cancel_id = ring.prep_cancel(timeout_id)
66
- assert_equal 2, cancel_id
67
-
68
- ring.submit
69
- c = ring.wait_for_completion
70
- assert_equal cancel_id, c[:id]
71
- assert_equal 0, c[:result]
72
-
73
- c = ring.wait_for_completion
74
- assert_equal timeout_id, c[:id]
75
- assert_equal :timeout, c[:op]
76
- assert_equal interval, c[:interval]
77
- assert_equal (-Errno::ECANCELED::Errno), c[:result]
78
- end
79
-
80
- def test_prep_cancel_kw
81
- interval = 15
82
- timeout_id = ring.prep_timeout(interval: interval)
83
- assert_equal 1, timeout_id
84
-
85
- cancel_id = ring.prep_cancel(id: timeout_id)
86
- assert_equal 2, cancel_id
87
-
88
- ring.submit
89
- c = ring.wait_for_completion
90
- assert_equal cancel_id, c[:id]
91
- assert_equal 0, c[:result]
92
-
93
- c = ring.wait_for_completion
94
- assert_equal timeout_id, c[:id]
95
- assert_equal :timeout, c[:op]
96
- assert_equal interval, c[:interval]
97
- assert_equal (-Errno::ECANCELED::Errno), c[:result]
98
- end
99
-
100
- def test_prep_cancel_invalid_args
101
- assert_raises(ArgumentError) { ring.prep_cancel() }
102
- assert_raises(ArgumentError) { ring.prep_cancel('foo') }
103
- assert_raises(ArgumentError) { ring.prep_cancel({}) }
104
- assert_raises(TypeError) { ring.prep_cancel(id: 'bar') }
105
- end
106
-
107
- def test_prep_cancel_invalid_id
108
- cancel_id = ring.prep_cancel(id: 42)
109
- assert_equal 1, cancel_id
110
-
111
- ring.submit
112
- c = ring.wait_for_completion
113
- assert_equal cancel_id, c[:id]
114
- assert_equal (-Errno::ENOENT::Errno), c[:result]
115
- end
116
- end
117
-
118
- class PrepTimeoutMultishotTest < IOURingBaseTest
119
- def test_prep_timeout_multishot
120
- interval = 0.03
121
- count = 0
122
- cancelled = false
123
-
124
- t0 = monotonic_clock
125
- id = ring.prep_timeout(interval: interval, multishot: true) do |c|
126
- case c[:result]
127
- when (-Errno::ETIME::Errno)
128
- count += 1
129
- when (-Errno::ECANCELED::Errno)
130
- cancelled = true
131
- end
132
- end
133
- ring.submit
134
-
135
- ring.process_completions(true)
136
- elapsed = monotonic_clock - t0
137
- assert_in_range interval..(interval + 0.02), elapsed
138
- assert_equal 1, count
139
-
140
- t0 = monotonic_clock
141
- ring.process_completions(true)
142
- elapsed = monotonic_clock - t0
143
- assert_in_range (interval - 0.01)..(interval + 0.02), elapsed
144
- assert_equal 2, count
145
-
146
- t0 = monotonic_clock
147
- ring.process_completions(true)
148
- elapsed = monotonic_clock - t0
149
- assert_in_range (interval - 0.01)..(interval + 0.02), elapsed
150
- assert_equal 3, count
151
-
152
- ring.prep_cancel(id)
153
- ring.submit
154
- ring.process_completions(true)
155
- assert_equal true, cancelled
156
- assert_equal 3, count
157
- assert_nil ring.pending_ops[id]
158
- end
159
- end
160
-
161
- class PrepWriteTest < IOURingBaseTest
162
- def test_prep_write
163
- r, w = IO.pipe
164
- s = 'foobar'
165
-
166
- id = ring.prep_write(fd: w.fileno, buffer: s)
167
- assert_equal 1, id
168
-
169
- ring.submit
170
- c = ring.wait_for_completion
171
-
172
- assert_kind_of Hash, c
173
- assert_equal id, c[:id]
174
- assert_equal :write, c[:op]
175
- assert_equal w.fileno, c[:fd]
176
- assert_equal s.bytesize, c[:result]
177
-
178
- w.close
179
- assert_equal s, r.read
180
- end
181
-
182
- def test_prep_write_with_len
183
- r, w = IO.pipe
184
- s = 'foobar'
185
-
186
- id = ring.prep_write(fd: w.fileno, buffer: s, len: 3)
187
- assert_equal 1, id
188
-
189
- ring.submit
190
- c = ring.wait_for_completion
191
-
192
- assert_kind_of Hash, c
193
- assert_equal id, c[:id]
194
- assert_equal :write, c[:op]
195
- assert_equal w.fileno, c[:fd]
196
- assert_equal 3, c[:result]
197
-
198
- w.close
199
- assert_equal s[0..2], r.read
200
- end
201
-
202
- def test_prep_write_invalid_args
203
- assert_raises(ArgumentError) { ring.prep_write() }
204
- assert_raises(ArgumentError) { ring.prep_write(foo: 1) }
205
- assert_raises(ArgumentError) { ring.prep_write(fd: 'bar') }
206
- assert_raises(ArgumentError) { ring.prep_write({}) }
207
- end
208
-
209
- def test_prep_write_invalid_fd
210
- r, _w = IO.pipe
211
- s = 'foobar'
212
-
213
- id = ring.prep_write(fd: r.fileno, buffer: s)
214
- assert_equal 1, id
215
-
216
- ring.submit
217
- c = ring.wait_for_completion
218
-
219
- assert_kind_of Hash, c
220
- assert_equal id, c[:id]
221
- assert_equal :write, c[:op]
222
- assert_equal r.fileno, c[:fd]
223
- assert_equal (-Errno::EBADF::Errno), c[:result]
224
- end
225
- end
226
-
227
- class PrepNopTest < IOURingBaseTest
228
- def test_prep_nop
229
- id = ring.prep_nop
230
- assert_equal 1, id
231
-
232
- ring.submit
233
- c = ring.wait_for_completion
234
-
235
- assert_kind_of Hash, c
236
- assert_equal id, c[:id]
237
- assert_nil c[:op]
238
- assert_equal 0, c[:result]
239
- end
240
-
241
- def test_nop_as_signal
242
- s1 = Queue.new
243
- s2 = Queue.new
244
- s3 = Queue.new
245
- s4 = Queue.new
246
-
247
- signaller = Thread.new do
248
- s1.pop
249
- id = ring.prep_nop
250
- ring.submit
251
- s2 << id
252
- end
253
-
254
- waiter = Thread.new do
255
- s3.pop
256
- s4 << ring.wait_for_completion
257
- end
258
-
259
- s3 << 'go'
260
- s1 << 'go'
261
- id = s2.pop
262
- c = s4.pop
263
-
264
- assert_kind_of Hash, c
265
- assert_equal id, c[:id]
266
- assert_nil c[:op]
267
- assert_equal 0, c[:result]
268
- ensure
269
- signaller&.kill rescue nil
270
- waiter&.kill rescue nil
271
- end
272
- end
273
-
274
- class ProcessCompletionsTest < IOURingBaseTest
275
- def test_process_completions_no_wait
276
- ret = ring.process_completions
277
- assert_equal 0, ret
278
-
279
- (1..3).each do |i|
280
- id = ring.prep_nop
281
- assert_equal i, id
282
- end
283
-
284
- ring.submit
285
- sleep 0.001
286
-
287
- ret = ring.process_completions
288
- assert_equal 3, ret
289
- end
290
-
291
- def test_process_completions_wait
292
- (1..3).each do |i|
293
- id = ring.prep_nop
294
- assert_equal i, id
295
- end
296
-
297
- ring.submit
298
- ret = ring.process_completions(true)
299
- assert_equal 3, ret
300
- end
301
-
302
- def test_process_completions_with_block
303
- r, w = IO.pipe
304
-
305
- ring.prep_write(fd: w.fileno, buffer: 'foo')
306
- ring.prep_write(fd: w.fileno, buffer: 'bar')
307
- ring.prep_write(fd: w.fileno, buffer: 'baz')
308
- ring.submit
309
- sleep 0.01
310
-
311
- completions = []
312
-
313
- ret = ring.process_completions do |c|
314
- completions << c
315
- end
316
-
317
- assert_equal 3, ret
318
- assert_equal 3, completions.size
319
- assert_equal [1, 2, 3], completions.map { _1[:id] }
320
- assert_equal [:write], completions.map { _1[:op] }.uniq
321
- assert_equal 9, completions.inject(0) { |t, c| t + c[:result] }
322
-
323
- w.close
324
- assert_equal 'foobarbaz', r.read
325
- end
326
-
327
- def test_process_completions_op_with_block
328
- cc = []
329
-
330
- ring.prep_timeout(interval: 0.01) { cc << 1 }
331
- ring.prep_timeout(interval: 0.02) { cc << 2 }
332
- ring.submit
333
-
334
- ret = ring.process_completions
335
- assert_equal 0, ret
336
- assert_equal [], cc
337
-
338
- sleep 0.02
339
- ret = ring.process_completions(true)
340
-
341
- assert_equal 2, ret
342
- assert_equal [1, 2], cc
343
- end
344
-
345
- def test_process_completions_op_with_block_no_submit
346
- cc = []
347
-
348
- ring.prep_timeout(interval: 0.01) { cc << 1 }
349
- ring.prep_timeout(interval: 0.02) { cc << 2 }
350
-
351
- ret = ring.process_completions
352
- assert_equal 0, ret
353
- assert_equal [], cc
354
-
355
- sleep 0.02
356
- ret = ring.process_completions(true)
357
- assert_equal 2, ret
358
- assert_equal [1, 2], cc
359
- end
360
- end
361
-
362
- class PrepReadTest < IOURingBaseTest
363
- def test_prep_read
364
- r, w = IO.pipe
365
- s = 'foobar'
366
-
367
- id = ring.prep_read(fd: r.fileno, buffer: +'', len: 8192)
368
- assert_equal 1, id
369
- ring.submit
370
-
371
- w << s
372
-
373
- c = ring.wait_for_completion
374
-
375
- assert_kind_of Hash, c
376
- assert_equal id, c[:id]
377
- assert_equal :read, c[:op]
378
- assert_equal r.fileno, c[:fd]
379
- assert_equal s.bytesize, c[:result]
380
- assert_equal s, c[:buffer]
381
- end
382
-
383
- def test_prep_read_empty
384
- r, w = IO.pipe
385
-
386
- id = ring.prep_read(fd: r.fileno, buffer: +'', len: 8192)
387
- assert_equal 1, id
388
- ring.submit
389
-
390
- w.close
391
-
392
- c = ring.wait_for_completion
393
-
394
- assert_kind_of Hash, c
395
- assert_equal id, c[:id]
396
- assert_equal :read, c[:op]
397
- assert_equal r.fileno, c[:fd]
398
- assert_equal 0, c[:result]
399
- assert_equal '', c[:buffer]
400
- end
401
-
402
- def test_prep_read_invalid_args
403
- assert_raises(ArgumentError) { ring.prep_read() }
404
- assert_raises(ArgumentError) { ring.prep_read(foo: 1) }
405
- assert_raises(ArgumentError) { ring.prep_read(fd: 'bar', buffer: +'') }
406
- assert_raises(ArgumentError) { ring.prep_read({}) }
407
- end
408
-
409
- def test_prep_read_bad_fd
410
- _r, w = IO.pipe
411
-
412
- id = ring.prep_read(fd: w.fileno, buffer: +'', len: 8192)
413
- assert_equal 1, id
414
-
415
- ring.submit
416
- c = ring.wait_for_completion
417
-
418
- assert_kind_of Hash, c
419
- assert_equal id, c[:id]
420
- assert_equal :read, c[:op]
421
- assert_equal w.fileno, c[:fd]
422
- assert_equal (-Errno::EBADF::Errno), c[:result]
423
- end
424
-
425
- def test_prep_read_with_block
426
- r, w = IO.pipe
427
- w << 'foobar'
428
-
429
- cc = nil
430
- id = ring.prep_read(fd: r.fileno, buffer: +'', len: 3) do |c|
431
- cc = c
432
- end
433
-
434
- ring.submit
435
- ring.process_completions
436
-
437
- assert_kind_of Hash, cc
438
- assert_equal id, cc[:id]
439
- assert_equal :read, cc[:op]
440
- assert_equal r.fileno, cc[:fd]
441
- assert_equal 3, cc[:result]
442
- assert_equal 'foo', cc[:buffer]
443
-
444
- id = ring.prep_read(fd: r.fileno, buffer: +'', len: 5) do |c|
445
- cc = c
446
- end
447
- assert_equal 'foo', cc[:buffer]
448
-
449
- ring.submit
450
- ring.process_completions
451
-
452
- assert_kind_of Hash, cc
453
- assert_equal id, cc[:id]
454
- assert_equal :read, cc[:op]
455
- assert_equal r.fileno, cc[:fd]
456
- assert_equal 3, cc[:result]
457
- assert_equal 'bar', cc[:buffer]
458
- end
459
-
460
- def test_prep_read_with_buffer_offset
461
- buffer = +'foo'
462
-
463
- r, w = IO.pipe
464
- w << 'bar'
465
-
466
- id = ring.prep_read(fd: r.fileno, buffer: buffer, len: 100, buffer_offset: buffer.bytesize)
467
- ring.submit
468
- cc = ring.wait_for_completion
469
-
470
- assert_kind_of Hash, cc
471
- assert_equal id, cc[:id]
472
- assert_equal :read, cc[:op]
473
- assert_equal r.fileno, cc[:fd]
474
- assert_equal 3, cc[:result]
475
- assert_equal 'foobar', buffer
476
- end
477
-
478
- def test_prep_read_with_negative_buffer_offset
479
- buffer = +'foo'
480
-
481
- r, w = IO.pipe
482
- w << 'bar'
483
-
484
- id = ring.prep_read(fd: r.fileno, buffer: buffer, len: 100, buffer_offset: -1)
485
- ring.submit
486
- cc = ring.wait_for_completion
487
-
488
- assert_kind_of Hash, cc
489
- assert_equal id, cc[:id]
490
- assert_equal :read, cc[:op]
491
- assert_equal r.fileno, cc[:fd]
492
- assert_equal 3, cc[:result]
493
- assert_equal 'foobar', buffer
494
-
495
-
496
-
497
- buffer = +'foogrr'
498
-
499
- r, w = IO.pipe
500
- w << 'bar'
501
-
502
- id = ring.prep_read(fd: r.fileno, buffer: buffer, len: 100, buffer_offset: -4)
503
- ring.submit
504
- cc = ring.wait_for_completion
505
-
506
- assert_kind_of Hash, cc
507
- assert_equal id, cc[:id]
508
- assert_equal :read, cc[:op]
509
- assert_equal r.fileno, cc[:fd]
510
- assert_equal 3, cc[:result]
511
- assert_equal 'foobar', buffer
512
- end
513
- end
514
-
515
- class PrepCloseTest < IOURingBaseTest
516
- def test_prep_close
517
- _r, w = IO.pipe
518
- fd = w.fileno
519
-
520
- id = ring.prep_close(fd: fd)
521
- assert_equal 1, id
522
- ring.submit
523
-
524
- c = ring.wait_for_completion
525
- assert_kind_of Hash, c
526
- assert_equal id, c[:id]
527
- assert_equal :close, c[:op]
528
- assert_equal fd, c[:fd]
529
- assert_equal 0, c[:result]
530
-
531
- assert_raises(Errno::EBADF) { w << 'fail' }
532
-
533
- id = ring.prep_close(fd: fd)
534
- assert_equal 2, id
535
- ring.submit
536
-
537
- c = ring.wait_for_completion
538
- assert_kind_of Hash, c
539
- assert_equal id, c[:id]
540
- assert_equal :close, c[:op]
541
- assert_equal fd, c[:fd]
542
- assert_equal (-Errno::EBADF::Errno), c[:result]
543
-
544
- end
545
-
546
- def test_prep_close_invalid_args
547
- assert_raises(ArgumentError) { ring.prep_close() }
548
- assert_raises(ArgumentError) { ring.prep_close({}) }
549
- assert_raises(ArgumentError) { ring.prep_close(foo: 1) }
550
- assert_raises(TypeError) { ring.prep_close(fd: 'bar') }
551
- end
552
-
553
- def test_prep_close_invalid_fd
554
- id = ring.prep_close(fd: 9999)
555
- assert_equal 1, id
556
-
557
- ring.submit
558
- c = ring.wait_for_completion
559
-
560
- assert_kind_of Hash, c
561
- assert_equal id, c[:id]
562
- assert_equal :close, c[:op]
563
- assert_equal 9999, c[:fd]
564
- assert_equal (-Errno::EBADF::Errno), c[:result]
565
- end
566
- end
567
-
568
- class PrepAcceptTest < IOURingBaseTest
569
- def setup
570
- super
571
- @port = 9000 + rand(1000)
572
- @server = TCPServer.open('127.0.0.1', @port)
573
- end
574
-
575
- def teardown
576
- @server.close
577
- super
578
- end
579
-
580
- def test_prep_accept
581
- id = ring.prep_accept(fd: @server.fileno)
582
- ring.submit
583
-
584
- t = Thread.new do
585
- TCPSocket.new('127.0.0.1', @port)
586
- end
587
-
588
- c = ring.wait_for_completion
589
- assert_equal id, c[:id]
590
- assert_equal :accept, c[:op]
591
- fd = c[:result]
592
- assert fd > 0
593
- ensure
594
- t&.kill rescue nil
595
- end
596
-
597
- def test_prep_accept_invalid_args
598
- assert_raises(ArgumentError) { ring.prep_accept() }
599
- assert_raises(ArgumentError) { ring.prep_accept(foo: 1) }
600
- assert_raises(TypeError) { ring.prep_accept(fd: 'bar') }
601
- assert_raises(ArgumentError) { ring.prep_accept({}) }
602
- end
603
-
604
- def test_prep_accept_bad_fd
605
- id = ring.prep_accept(fd: STDIN.fileno)
606
- assert_equal 1, id
607
-
608
- ring.submit
609
- c = ring.wait_for_completion
610
-
611
- assert_kind_of Hash, c
612
- assert_equal id, c[:id]
613
- assert_equal :accept, c[:op]
614
- assert_equal STDIN.fileno, c[:fd]
615
- assert_equal (-Errno::ENOTSOCK::Errno), c[:result]
616
- end
617
-
618
- def test_prep_accept_multishot
619
- id = ring.prep_accept(fd: @server.fileno, multishot: true)
620
- ring.submit
621
-
622
- tt = []
623
-
624
- connect = -> {
625
- tt << Thread.new do
626
- TCPSocket.new('127.0.0.1', @port)
627
- end
628
- }
629
-
630
- fds = []
631
-
632
- 3.times do |i|
633
- connect.call
634
- c = ring.wait_for_completion
635
- assert_equal id, c[:id]
636
- assert_equal :accept, c[:op]
637
- fd = c[:result]
638
- assert fd > 0
639
- assert ring.pending_ops[id]
640
-
641
- fds << fd
642
- end
643
-
644
- assert_equal 3, fds.uniq.size
645
-
646
- ring.prep_cancel(id)
647
- ring.process_completions
648
-
649
- assert_nil ring.pending_ops[id]
650
- ensure
651
- tt.each { |t| t&.kill rescue nil }
652
- end
653
- end
654
-
655
- class EmitTest < IOURingBaseTest
656
- def test_emit
657
- o = { foo: 'bar' }
658
- id = ring.emit(o)
659
- assert_equal 1, id
660
-
661
- c = ring.wait_for_completion
662
- assert_equal o, c
663
- assert_equal id, c[:id]
664
- assert_equal :emit, c[:op]
665
- assert_equal 0, c[:result]
666
- end
667
- end
668
-
669
- class ProcessCompletionsLoopTest < IOURingBaseTest
670
- def test_loop_stop
671
- ring.emit(signal: :stop)
672
-
673
- cc = []
674
- ring.process_completions_loop do |c|
675
- p c
676
- cc << c
677
- end
678
-
679
- assert_equal [], cc
680
- end
681
-
682
- def test_loop
683
- ring.emit(value: 1)
684
- ring.emit(value: 2)
685
- ring.emit(value: 3)
686
- ring.emit(signal: :stop)
687
- ring.emit(value: 4)
688
-
689
- cc = []
690
- ring.process_completions_loop do |c|
691
- cc << c
692
- end
693
- assert_equal (1..3).to_a, cc.map { _1[:value] }
694
-
695
- c = ring.wait_for_completion
696
- assert_equal 4, c[:value]
697
- end
698
- end
699
-
700
- class PrepReadMultishotTest < IOURingBaseTest
701
- def test_prep_read_multishot_invalid_args
702
- assert_raises(ArgumentError) { ring.prep_read(multishot: true, buffer_group: 1) }
703
- assert_raises(ArgumentError) { ring.prep_read(multishot: true, foo: 1) }
704
- assert_raises(ArgumentError) { ring.prep_read(multishot: true, fd: 'bar', buffer: +'') }
705
- assert_raises(ArgumentError) { ring.prep_read(multishot: true) }
706
- end
707
-
708
- def test_prep_read_multishot
709
- r, w = IO.pipe
710
-
711
- bgid = ring.setup_buffer_ring(size: 4096, count: 1024)
712
- assert_equal 0, bgid
713
-
714
- id = ring.prep_read(fd: r.fileno, multishot: true, buffer_group: bgid)
715
- assert_equal 1, id
716
- ring.submit
717
-
718
- w << 'foo'
719
- c = ring.wait_for_completion
720
-
721
- # make sure the OS supports this op (the liburing docs are not clear)
722
- skip if c[:result] == (-Errno::EINVAL::Errno)
723
-
724
- assert_kind_of Hash, c
725
- assert_equal id, c[:id]
726
- assert_equal :read, c[:op]
727
- assert_equal r.fileno, c[:fd]
728
- assert_equal 3, c[:result]
729
- assert_equal 'foo', c[:buffer]
730
- assert_equal Encoding::ASCII_8BIT, c[:buffer].encoding
731
- refute_nil ring.pending_ops[id]
732
-
733
- w << 'bar'
734
- c = ring.wait_for_completion
735
- assert_kind_of Hash, c
736
- assert_equal id, c[:id]
737
- assert_equal :read, c[:op]
738
- assert_equal r.fileno, c[:fd]
739
- assert_equal 3, c[:result]
740
- assert_equal 'bar', c[:buffer]
741
- refute_nil ring.pending_ops[id]
742
-
743
- w.close
744
- c = ring.wait_for_completion
745
- assert_kind_of Hash, c
746
- assert_equal id, c[:id]
747
- assert_equal :read, c[:op]
748
- assert_equal r.fileno, c[:fd]
749
- assert_equal 0, c[:result]
750
- assert_nil ring.pending_ops[id]
751
- end
752
-
753
- def test_prep_read_multishot_utf8
754
- r, w = IO.pipe
755
-
756
- bgid = ring.setup_buffer_ring(size: 4096, count: 1024)
757
- assert_equal 0, bgid
758
-
759
- id = ring.prep_read(fd: r.fileno, multishot: true, utf8: true, buffer_group: bgid)
760
- assert_equal 1, id
761
- ring.submit
762
-
763
- w << 'foo'
764
- c = ring.wait_for_completion
765
-
766
- # make sure the OS supports this op (the liburing docs are not clear)
767
- skip if c[:result] == (-Errno::EINVAL::Errno)
768
-
769
- assert_kind_of Hash, c
770
- assert_equal id, c[:id]
771
- assert_equal :read, c[:op]
772
- assert_equal r.fileno, c[:fd]
773
- assert_equal 3, c[:result]
774
- assert_equal 'foo', c[:buffer]
775
- assert_equal Encoding::UTF_8, c[:buffer].encoding
776
- refute_nil ring.pending_ops[id]
777
-
778
- w << 'bar'
779
- c = ring.wait_for_completion
780
- assert_kind_of Hash, c
781
- assert_equal id, c[:id]
782
- assert_equal :read, c[:op]
783
- assert_equal r.fileno, c[:fd]
784
- assert_equal 3, c[:result]
785
- assert_equal 'bar', c[:buffer]
786
- refute_nil ring.pending_ops[id]
787
-
788
- w.close
789
- c = ring.wait_for_completion
790
- assert_kind_of Hash, c
791
- assert_equal id, c[:id]
792
- assert_equal :read, c[:op]
793
- assert_equal r.fileno, c[:fd]
794
- assert_equal 0, c[:result]
795
- assert_nil ring.pending_ops[id]
796
- end
797
- end
798
-
799
- class OpCtxTest < IOURingBaseTest
800
- def test_ctx_spec
801
- id = ring.emit(foo: :bar)
802
- assert_equal({ foo: :bar, id: 1, op: :emit }, ring.pending_ops[id].spec)
803
- end
804
-
805
- def test_ctx_type
806
- id = ring.emit(v: 1)
807
- assert_equal 1, id
808
- assert_equal :emit, ring.pending_ops[id].spec[:op]
809
-
810
- id = ring.prep_timeout(interval: 1)
811
- assert_equal 2, id
812
- assert_equal :timeout, ring.pending_ops[id].spec[:op]
813
-
814
- id = ring.prep_read(fd: STDIN.fileno, buffer: +'', len: 42)
815
- assert_equal 3, id
816
- assert_equal :read, ring.pending_ops[id].spec[:op]
817
-
818
- id = ring.prep_write(fd: STDOUT.fileno, buffer: '')
819
- assert_equal 4, id
820
- assert_equal :write, ring.pending_ops[id].spec[:op]
821
-
822
- id = ring.prep_accept(fd: STDIN.fileno)
823
- assert_equal 5, id
824
- assert_equal :accept, ring.pending_ops[id].spec[:op]
825
-
826
- id = ring.prep_close(fd: STDIN.fileno)
827
- assert_equal 6, id
828
- assert_equal :close, ring.pending_ops[id].spec[:op]
829
- end
830
- end
831
-
832
- class LinkTest < IOURingBaseTest
833
- def test_linked_submissions
834
- r, w = IO.pipe
835
- id1 = ring.prep_write(fd: w.fileno, buffer: 'foo', link: true)
836
- id2 = ring.prep_write(fd: w.fileno, buffer: 'bar')
837
-
838
- ret = ring.submit
839
- assert_equal 2, ret
840
-
841
- ret = ring.process_completions(true)
842
- assert_equal 2, ret
843
-
844
- w.close
845
- assert_equal 'foobar', r.read
846
- end
847
- end
848
-
849
- class RactorTest < Minitest::Test
850
- def test_ractor
851
- # Ractor is still experimental in Ruby 3.x.x
852
- old_warning_status = Warning[:experimental]
853
- Warning[:experimental] = false
854
-
855
- r, w = IO.pipe
856
-
857
- w << 'foobar'
858
-
859
- ractor = Ractor.new(r.fileno) do |fd|
860
- ring = IOU::Ring.new
861
- id = ring.prep_read(fd: fd, buffer: +'', len: 42)
862
- ring.submit
863
- c = ring.wait_for_completion
864
- [id, c]
865
- end
866
-
867
- id, c = ractor.take
868
- assert_equal 1, id
869
- assert_kind_of Hash, c
870
- assert_equal :read, c[:op]
871
- assert_equal 'foobar', c[:buffer]
872
-
873
- ensure
874
- Warning[:experimental] = old_warning_status
875
- end
876
- end