test_poll: avoid potentially thread-unsafe test
[kgio.git] / test / test_poll.rb
blob13f5f2a99c1d4d0b6232165fc9e396627459a90a
1 require 'test/unit'
2 $-w = true
3 require 'kgio'
5 class TestPoll < Test::Unit::TestCase
6   def teardown
7     [ @rd, @wr ].each { |io| io.close unless io.closed? }
8   end
10   def setup
11     @rd, @wr = IO.pipe
12   end
14   def test_constants
15     assert_kind_of Integer, Kgio::POLLIN
16     assert_kind_of Integer, Kgio::POLLOUT
17     assert_kind_of Integer, Kgio::POLLPRI
18     assert_kind_of Integer, Kgio::POLLHUP
19     assert_kind_of Integer, Kgio::POLLERR
20     assert_kind_of Integer, Kgio::POLLNVAL
21   end
23   def test_poll_symbol
24     set = { @rd => :wait_readable, @wr => :wait_writable }
25     res = Kgio.poll(set)
26     assert_equal({@wr => Kgio::POLLOUT}, res)
27     assert_equal set.object_id, res.object_id
28   end
30   def test_poll_integer
31     set = { @wr => Kgio::POLLOUT|Kgio::POLLHUP }
32     res = Kgio.poll(set)
33     assert_equal({@wr => Kgio::POLLOUT}, res)
34     assert_equal set.object_id, res.object_id
35   end
37   def test_poll_timeout
38     t0 = Time.now
39     res = Kgio.poll({}, 10)
40     diff = Time.now - t0
41     assert diff >= 0.010, "diff=#{diff}"
42     assert_nil res
43   end
45   def test_poll_close
46     foo = nil
47     thr = Thread.new { sleep 0.100; @wr.close }
48     t0 = Time.now
49     res = Kgio.poll({@rd => Kgio::POLLIN})
50     diff = Time.now - t0
51     thr.join
52     assert_equal([ @rd ], res.keys)
53     assert diff >= 0.010, "diff=#{diff}"
54   end
56   def test_signal_close
57     orig = trap(:USR1) { @rd.close }
58     res = nil
59     thr = Thread.new { sleep 0.100; Process.kill(:USR1, $$) }
60     t0 = Time.now
61     assert_raises(IOError) do
62       result = Kgio.poll({@rd => Kgio::POLLIN})
63       result.each_key { |io| io.read_nonblock(1) }
64     end
65     diff = Time.now - t0
66     thr.join
67     assert diff >= 0.010, "diff=#{diff}"
68     ensure
69       trap(:USR1, orig)
70   end
72   def test_poll_EINTR
73     ok = false
74     orig = trap(:USR1) { ok = true }
75     thr = Thread.new do
76       sleep 0.100
77       Process.kill(:USR1, $$)
78     end
79     t0 = Time.now
80     res = Kgio.poll({@rd => Kgio::POLLIN}, 1000)
81     diff = Time.now - t0
82     thr.join
83     assert_nil res
84     assert diff >= 1.0, "diff=#{diff}"
85     assert ok
86     ensure
87       trap(:USR1, orig)
88   end
90   def test_poll_EINTR_changed
91     ok = false
92     pollset = { @rd => Kgio::POLLIN }
93     orig = trap(:USR1) do
94       pollset[@wr] = Kgio::POLLOUT
95       ok = true
96     end
97     thr = Thread.new do
98       sleep 0.100
99       Process.kill(:USR1, $$)
100     end
101     t0 = Time.now
102     res = Kgio.poll(pollset, 1000)
103     diff = Time.now - t0
104     thr.join
105     assert_equal({@wr => Kgio::POLLOUT}, res)
106     assert diff < 1.0, "diff=#{diff}"
107     assert ok
108     ensure
109       trap(:USR1, orig)
110   end
112   def test_poll_signal_torture
113     usr1 = 0
114     empty = 0
115     nr = 100
116     set = { @rd => Kgio::POLLIN }
117     trap(:USR1) { usr1 += 1 }
118     pid = fork do
119       trap(:USR1, "DEFAULT")
120       sleep 0.1
121       ppid = Process.ppid
122       nr.times { Process.kill(:USR1, ppid); sleep 0.05 }
123       @wr.syswrite('.')
124       exit!(0)
125     end
127     empty += 1 until Kgio.poll(set.dup, 100)
128     _, status = Process.waitpid2(pid)
129     assert status.success?, status.inspect
130     assert usr1 > 0, "usr1: #{usr1}"
131   ensure
132     trap(:USR1, "DEFAULT")
133   end unless RUBY_PLATFORM =~ /kfreebsd-gnu/
134 end if Kgio.respond_to?(:poll)