uringmachine 0.25.0 → 0.27.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.
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
@@ -572,6 +585,8 @@ class ReadTest < UMBaseTest
572
585
  assert_raises(UM::Error) {
573
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
@@ -1260,7 +1344,7 @@ class AcceptEachTest < UMBaseTest
1260
1344
  def test_accept_each_closed
1261
1345
  count = 0
1262
1346
  done = nil
1263
- f = @machine.spin do
1347
+ @machine.spin do
1264
1348
  machine.accept_each(@server.fileno) do |fd|
1265
1349
  count += 1
1266
1350
  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,11 +1806,165 @@ 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
+ @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
+ @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
+ 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
1669
1882
  end
1670
1883
 
1884
+ class SendRecvFdTest < UMBaseTest
1885
+ def setup
1886
+ @s1_fd, @s2_fd = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
1887
+ super
1888
+ end
1889
+
1890
+ def teardown
1891
+ [@s1_fd, @s2_fd].each { machine.close(it) rescue nil }
1892
+ super
1893
+ end
1894
+
1895
+ class TOError < StandardError; end
1896
+
1897
+ def test_send_recv_fd
1898
+ r_fd, w_fd = UM.pipe
1899
+
1900
+ res = machine.send_fd(@s1_fd, w_fd)
1901
+ assert_equal w_fd, res
1902
+
1903
+ fd = machine.recv_fd(@s2_fd)
1904
+ assert_kind_of Integer, fd
1905
+ refute_equal w_fd, fd
1906
+
1907
+ machine.close(w_fd)
1908
+ machine.write(fd, 'foobar')
1909
+ machine.close(fd)
1910
+
1911
+ buf = +''
1912
+ res = machine.read(r_fd, buf, 12)
1913
+ assert_equal 6, res
1914
+ assert_equal 'foobar', buf
1915
+ end
1916
+
1917
+ def test_send_recv_fd_fork
1918
+ pid = fork do
1919
+ m = UM.new
1920
+ fd = m.recv_fd(@s2_fd)
1921
+ m.write(fd, 'Hello!')
1922
+ ensure
1923
+ m.close(fd) rescue nil
1924
+ end
1925
+
1926
+ r_fd, w_fd = UM.pipe
1927
+
1928
+ res = machine.send_fd(@s1_fd, w_fd)
1929
+ assert_equal w_fd, res
1930
+ Process.wait(pid)
1931
+ pid = nil
1932
+ machine.close(w_fd)
1933
+
1934
+ buf = +''
1935
+ len = machine.timeout(1, TOError) { machine.read(r_fd, buf, 12) }
1936
+ assert_equal 6, len
1937
+ assert_equal 'Hello!', buf
1938
+ ensure
1939
+ if pid
1940
+ Process.kill('KILL', pid) rescue nil
1941
+ Process.wait(pid) rescue nil
1942
+ end
1943
+ machine.close(r_fd) rescue nil
1944
+ machine.close(w_fd) rescue nil
1945
+ end
1946
+
1947
+ def test_send_fd_bad_sock_fd
1948
+ _r_fd, w_fd = UM.pipe
1949
+ assert_raises(Errno::ENOTSOCK) { machine.send_fd(0, w_fd) }
1950
+ end
1951
+
1952
+ def test_send_fd_bad_fd
1953
+ assert_raises(TypeError) { machine.send_fd(@s1_fd, nil) }
1954
+ assert_raises(Errno::EBADF) { machine.send_fd(@s1_fd, 1111) }
1955
+ end
1956
+
1957
+ def test_recv_fd_bad_msg
1958
+ buf = "\0" * 1000
1959
+ machine.write(@s1_fd, buf)
1960
+
1961
+ assert_raises(Errno::EINVAL) {
1962
+ res = machine.recv_fd(@s2_fd)
1963
+ p res: res
1964
+ }
1965
+ end
1966
+ end
1967
+
1671
1968
  class BindTest < UMBaseTest
1672
1969
  def setup
1673
1970
  super
@@ -1699,6 +1996,7 @@ class BindTest < UMBaseTest
1699
1996
  assert_raises(Errno::EBADF) { machine.bind(-3, '127.0.01', 1234) }
1700
1997
 
1701
1998
  assert_equal 0, machine.metrics[:ops_pending]
1999
+ assert_equal 256, machine.metrics[:ops_free]
1702
2000
  end
1703
2001
  end
1704
2002
 
@@ -1768,6 +2066,28 @@ class SynchronizeTest < UMBaseTest
1768
2066
 
1769
2067
  assert_equal [1, 2], buf
1770
2068
  assert_equal 0, machine.metrics[:ops_pending]
2069
+ assert_equal 0, machine.metrics[:ops_free]
2070
+ end
2071
+
2072
+ class MyError < StandardError; end
2073
+
2074
+ def test_synchronize_exception
2075
+ m = UM::Mutex.new
2076
+
2077
+ buf = []
2078
+ assert_raises(MyError) {
2079
+ machine.synchronize(m) do
2080
+ raise MyError
2081
+ buf << 1
2082
+ end
2083
+ }
2084
+ machine.synchronize(m) do
2085
+ buf << 2
2086
+ end
2087
+
2088
+ assert_equal [2], buf
2089
+ assert_equal 0, machine.metrics[:ops_pending]
2090
+ assert_equal 0, machine.metrics[:ops_free]
1771
2091
  end
1772
2092
 
1773
2093
  def test_synchronize_pair
@@ -1800,6 +2120,7 @@ class SynchronizeTest < UMBaseTest
1800
2120
  machine.sleep(0.03)
1801
2121
  assert_equal [11, 12, 13, 21, 22, 23], buf
1802
2122
  assert_equal 0, machine.metrics[:ops_pending]
2123
+ assert_equal 256, machine.metrics[:ops_free]
1803
2124
  end
1804
2125
 
1805
2126
  def test_synchronize_multi
@@ -1819,6 +2140,8 @@ class SynchronizeTest < UMBaseTest
1819
2140
 
1820
2141
  machine.join(*fibers)
1821
2142
  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
2143
+ assert_equal 0, machine.metrics[:ops_pending]
2144
+ assert_equal 256, machine.metrics[:ops_free]
1822
2145
  end
1823
2146
  end
1824
2147
 
@@ -1932,7 +2255,7 @@ class QueueTest < UMBaseTest
1932
2255
  assert_equal :baz, machine.shift(q)
1933
2256
  end
1934
2257
 
1935
- def test_shift_shift_1
2258
+ def test_shift_unshift_1
1936
2259
  q = UM::Queue.new
1937
2260
 
1938
2261
  machine.unshift(q, :foo)
@@ -2176,6 +2499,8 @@ class PollTest < UMBaseTest
2176
2499
 
2177
2500
  def test_poll_bad_fd
2178
2501
  assert_raises(Errno::EBADF) { machine.poll(9876, POLLIN) }
2502
+ assert_equal 0, machine.metrics[:ops_pending]
2503
+ assert_equal 256, machine.metrics[:ops_free]
2179
2504
  end
2180
2505
  end
2181
2506
 
@@ -2219,6 +2544,8 @@ class SelectTest < UMBaseTest
2219
2544
 
2220
2545
  machine.close(rfd1)
2221
2546
  machine.close(rfd2)
2547
+ assert_equal 0, machine.metrics[:ops_pending]
2548
+ assert_equal 256, machine.metrics[:ops_free]
2222
2549
  end
2223
2550
 
2224
2551
  def test_select_single
@@ -2246,15 +2573,27 @@ class SelectTest < UMBaseTest
2246
2573
 
2247
2574
  machine.close(rfd1)
2248
2575
  machine.close(wfd1)
2576
+ assert_equal 0, machine.metrics[:ops_pending]
2577
+ assert_equal 256, machine.metrics[:ops_free]
2249
2578
  end
2250
2579
 
2251
2580
  def test_select_empty
2252
2581
  ret = machine.select([], [], [])
2253
2582
  assert_equal [[], [], []], ret
2583
+ assert_equal 0, machine.metrics[:ops_pending]
2584
+ assert_equal 0, machine.metrics[:ops_free]
2254
2585
  end
2255
2586
 
2256
2587
  def test_select_bad_fd
2257
2588
  assert_raises(Errno::EBADF) { machine.select([9876, 9877], [], []) }
2589
+
2590
+ # we get one CQE with EBADF, the other one is cancelled and discarded
2591
+ assert_equal 0, machine.metrics[:ops_pending]
2592
+ assert_equal 255, machine.metrics[:ops_free]
2593
+
2594
+ # a second CQE with -ECANCELED, released
2595
+ machine.snooze
2596
+ assert_equal 256, machine.metrics[:ops_free]
2258
2597
  end
2259
2598
  end
2260
2599
 
@@ -2272,6 +2611,8 @@ class WaitidTest < UMBaseTest
2272
2611
  pid, status = machine.waitid(UM::P_PID, child_pid, UM::WEXITED)
2273
2612
  assert_equal child_pid, pid
2274
2613
  assert_equal 42, status
2614
+ assert_equal 0, machine.metrics[:ops_pending]
2615
+ assert_equal 256, machine.metrics[:ops_free]
2275
2616
  ensure
2276
2617
  Process.wait(child_pid) rescue nil
2277
2618
  end
@@ -2280,18 +2621,27 @@ class WaitidTest < UMBaseTest
2280
2621
  assert_raises(Errno::ECHILD) {
2281
2622
  machine.waitid(UM::P_PID, Process.pid + 1, UM::WEXITED)
2282
2623
  }
2624
+
2625
+ assert_equal 0, machine.metrics[:ops_pending]
2626
+ assert_equal 256, machine.metrics[:ops_free]
2283
2627
  end
2284
2628
 
2285
2629
  def test_waitid_invalid_idtype
2286
2630
  assert_raises(Errno::EINVAL) {
2287
2631
  machine.waitid(1234, 0, UM::WEXITED)
2288
2632
  }
2633
+
2634
+ assert_equal 0, machine.metrics[:ops_pending]
2635
+ assert_equal 256, machine.metrics[:ops_free]
2289
2636
  end
2290
2637
 
2291
2638
  def test_waitid_invalid_options
2292
2639
  assert_raises(Errno::EINVAL) {
2293
2640
  machine.waitid(P_ALL, 0, 1234)
2294
2641
  }
2642
+
2643
+ assert_equal 0, machine.metrics[:ops_pending]
2644
+ assert_equal 256, machine.metrics[:ops_free]
2295
2645
  end
2296
2646
 
2297
2647
  def test_waitid_P_ALL
@@ -2307,6 +2657,8 @@ class WaitidTest < UMBaseTest
2307
2657
  pid, status = machine.waitid(UM::P_ALL, 0, UM::WEXITED)
2308
2658
  assert_equal child_pid, pid
2309
2659
  assert_equal 42, status
2660
+ assert_equal 0, machine.metrics[:ops_pending]
2661
+ assert_equal 256, machine.metrics[:ops_free]
2310
2662
  ensure
2311
2663
  Process.wait(child_pid) rescue nil
2312
2664
  end
@@ -2324,6 +2676,8 @@ class WaitidTest < UMBaseTest
2324
2676
  pid, status = machine.waitid(UM::P_PGID, Process.getpgrp, UM::WEXITED)
2325
2677
  assert_equal child_pid, pid
2326
2678
  assert_equal 42, status
2679
+ assert_equal 0, machine.metrics[:ops_pending]
2680
+ assert_equal 256, machine.metrics[:ops_free]
2327
2681
  ensure
2328
2682
  Process.wait(child_pid) rescue nil
2329
2683
  end
@@ -2447,6 +2801,9 @@ class StatxTest < UMBaseTest
2447
2801
  assert_equal rstat.atime.to_i, ustat2[:atime].to_i
2448
2802
  assert_equal rstat.ctime.to_i, ustat2[:ctime].to_i
2449
2803
  assert_equal rstat.mtime.to_i, ustat2[:mtime].to_i
2804
+
2805
+ assert_equal 0, machine.metrics[:ops_pending]
2806
+ assert_equal 256, machine.metrics[:ops_free]
2450
2807
  ensure
2451
2808
  io.close
2452
2809
  end
@@ -2458,12 +2815,19 @@ class StatxTest < UMBaseTest
2458
2815
 
2459
2816
  assert_equal rstat.size, ustat[:size]
2460
2817
  assert_equal rstat.mtime.to_i, ustat[:mtime].to_i
2818
+ assert_equal 0, machine.metrics[:ops_pending]
2819
+ assert_equal 256, machine.metrics[:ops_free]
2461
2820
  ensure
2462
2821
  @machine.close_async(fd)
2463
2822
  end
2464
2823
 
2465
2824
  def test_statx_bad_path
2466
- assert_raises(Errno::ENOENT) { machine.statx(UM::AT_FDCWD, 'foobar', 0, UM::STATX_ALL) }
2825
+ assert_raises(Errno::ENOENT) {
2826
+ machine.statx(UM::AT_FDCWD, 'foobar', 0, UM::STATX_ALL)
2827
+ }
2828
+
2829
+ assert_equal 0, machine.metrics[:ops_pending]
2830
+ assert_equal 256, machine.metrics[:ops_free]
2467
2831
  end
2468
2832
  end
2469
2833
 
@@ -2556,23 +2920,6 @@ class SendBundleTest < UMBaseTest
2556
2920
  end
2557
2921
  end
2558
2922
 
2559
- class NonBlockTest < UMBaseTest
2560
- def test_io_nonblock?
2561
- assert_equal false, UM.io_nonblock?(STDIN)
2562
- end
2563
-
2564
- def test_io_set_nonblock
2565
- r, _w = IO.pipe
2566
- assert_equal true, UM.io_nonblock?(r)
2567
-
2568
- UM.io_set_nonblock(r, false)
2569
- assert_equal false, UM.io_nonblock?(r)
2570
-
2571
- UM.io_set_nonblock(r, true)
2572
- assert_equal true, UM.io_nonblock?(r)
2573
- end
2574
- end
2575
-
2576
2923
  class MetricsTest < UMBaseTest
2577
2924
  def test_metrics_empty
2578
2925
  assert_equal({
@@ -2672,7 +3019,7 @@ class MetricsTest < UMBaseTest
2672
3019
  f = machine.spin { machine.sleep(0.001) }
2673
3020
  assert_equal [0, 0, 1, 255, 0], ops_metrics
2674
3021
  machine.snooze
2675
- assert_equal [1, 0, 0, 256, 0], ops_metrics
3022
+ assert_equal [1, 0, 0, 255, 0], ops_metrics
2676
3023
  machine.join(f)
2677
3024
  assert_equal [0, 0, 0, 256, 0], ops_metrics
2678
3025
 
@@ -2879,3 +3226,39 @@ class FileWatchTest < UMBaseTest
2879
3226
  machine.join(f)
2880
3227
  end
2881
3228
  end
3229
+
3230
+ class SetChildSubreaperTest < Minitest::Test
3231
+ def test_pr_set_child_subreaper
3232
+ r, w = IO.pipe
3233
+ UM.pr_set_child_subreaper(true)
3234
+
3235
+ child_pid = fork {
3236
+ r2, w2 = IO.pipe
3237
+ pid = fork {
3238
+ r.close
3239
+ w.close
3240
+ w2.close
3241
+ r2.read
3242
+ r2.close
3243
+ sleep(0.01)
3244
+ }
3245
+ w << pid
3246
+ w.close
3247
+ r2.close
3248
+ w2 << 'done'
3249
+ w2.close
3250
+ }
3251
+ Process.wait(child_pid)
3252
+
3253
+ w.close
3254
+ msg = r.read
3255
+ r.close
3256
+
3257
+ refute msg.empty?
3258
+ grand_child_pid = msg.to_i
3259
+ refute_equal 0, grand_child_pid
3260
+
3261
+ res = Process.wait(grand_child_pid)
3262
+ assert_equal grand_child_pid, res
3263
+ end
3264
+ end