7 %w(read read_nonblock readpartial).each do |m|
19 ORIGINAL_SOCKET = ENV['ORIGINAL_SOCKET'].to_i != 0
20 require(ORIGINAL_SOCKET ? 'socket' : 'socket_dontwait')
22 class TestSocketDontwait < Test::Unit::TestCase
23 BS = ENV['bs'] ? ENV['bs'].to_i : 16384
24 COUNT = ENV['count'] ? ENV['count'].to_i : 100000
27 @rd, @wr = UNIXSocket.pair
32 @rd.close unless @rd.closed?
33 @wr.close unless @wr.closed?
36 def test_write_read_nonblock_str
37 assert_equal 3, @wr.write_nonblock('abc')
38 assert_equal 'abc', @rd.read_nonblock(3)
39 assert CALLED.empty? unless ORIGINAL_SOCKET
42 def test_write_read_nonblock_integer
43 assert_equal 3, @wr.write_nonblock(123)
44 assert_equal '123', @rd.read_nonblock(3)
45 assert CALLED.empty? unless ORIGINAL_SOCKET
48 def test_invalid_read_length
49 assert_raise(ArgumentError) { @rd.read(-1) }
50 assert_raise(ArgumentError) { @rd.read(-1, "") }
51 assert_raise(ArgumentError) { @rd.read_nonblock(-1) }
52 assert_raise(ArgumentError) { @rd.read_nonblock(-1, "") }
53 assert_raise(ArgumentError) { @rd.readpartial(-1) }
54 assert_raise(ArgumentError) { @rd.readpartial(-1, "") }
55 assert CALLED.empty? unless ORIGINAL_SOCKET
60 t = Thread.new { @rd.read 4096 }
61 assert_equal 4093, @wr.write(buf)
64 assert_equal 4, @wr.write('....')
66 assert_equal('.' * 4096, t.value)
67 assert_equal('.', @rd.read(1))
69 assert_nil @rd.read(1)
70 assert CALLED.empty? unless ORIGINAL_SOCKET
75 assert_equal '', @rd.read
77 str_object_id = str.object_id
78 assert_equal str_object_id, @rd.read(nil, str).object_id
79 assert CALLED.empty? unless ORIGINAL_SOCKET
82 def test_big_write_read_full_even
83 tmp = IO.read('/dev/urandom', 16427) * 32
84 tmp << '.' until ((tmp.bytesize % 16384) == 0)
88 exit!(nr == tmp.bytesize)
91 assert_equal tmp, @rd.read
92 _, status = Process.waitpid2(pid)
93 assert status.success?
94 assert CALLED.empty? unless ORIGINAL_SOCKET
97 def test_big_write_read_full_odd
98 n = @wr.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).unpack('i')[0]
99 tmp = IO.read('/dev/urandom', 16427) * 32
100 tmp << 'aasdfzf' until ((tmp.bytesize % 16384) != 0)
103 exit!(nr == tmp.bytesize)
106 assert_equal tmp, @rd.read
107 _, status = Process.waitpid2(pid)
108 assert status.success?
109 assert CALLED.empty? unless ORIGINAL_SOCKET
113 assert_equal '', @rd.read(0)
114 assert_equal '', @rd.readpartial(0)
115 assert_equal '', @rd.read_nonblock(0)
118 assert_equal buf.object_id, @rd.read(0, buf).object_id
121 assert_equal buf.object_id, @rd.readpartial(0, buf).object_id
124 assert_equal buf.object_id, @rd.read_nonblock(0, buf).object_id
128 def test_readpartial_signal
132 trap(:USR1) { w.syswrite "USR1" }
134 rv = @rd.readpartial(16384)
135 exit!(rv == "SIGNAL SAFE" && (ORIGINAL_SOCKET || CALLED.empty?))
138 assert_equal "READY", r.read(5)
139 assert_nothing_raised do
140 sleep 0.5 # ugh, still potentially racy :<
141 Process.kill(:USR1, pid)
143 assert_equal 'USR1', r.readpartial(4)
144 assert_equal 11, @wr.write("SIGNAL SAFE")
145 _, status = Process.waitpid2(pid)
146 assert status.success?
153 trap(:USR1) { w.syswrite "USR1" }
156 exit!(rv == "SIGNAL SAFE" && (ORIGINAL_SOCKET || CALLED.empty?))
159 assert_equal "READY", r.read(5)
160 assert_nothing_raised do
161 sleep 0.5 # ugh, still potentially racy :<
162 Process.kill(:USR1, pid)
164 assert_equal 'USR1', r.readpartial(4)
165 assert_equal 11, @wr.write("SIGNAL SAFE")
166 _, status = Process.waitpid2(pid)
167 assert status.success?
172 assert_raises(IOError) { @rd.read }
173 assert CALLED.empty? unless ORIGINAL_SOCKET
176 def test_closed_write
178 assert_raises(IOError) { @wr.write 'hello' }
179 assert_raises(IOError) { @wr.write_nonblock 'hello' }
180 assert CALLED.empty? unless ORIGINAL_SOCKET
183 def test_closed_writer_read
185 assert_raises(EOFError) { @rd.readpartial 5 }
186 assert_raises(EOFError) { @rd.read_nonblock 5 }
187 assert_nil @rd.read(5)
188 assert CALLED.empty? unless ORIGINAL_SOCKET
191 def test_closed_writer_read_with_buffer
194 assert_raises(EOFError) { @rd.readpartial 5, buf }
198 assert_raises(EOFError) { @rd.read_nonblock 5, buf }
202 assert_nil @rd.read(5, buf)
204 assert CALLED.empty? unless ORIGINAL_SOCKET
207 def test_closed_reader_write
209 assert_raises(Errno::EPIPE) { @wr.write 'hello' }
210 assert_raises(Errno::EPIPE) { @wr.write_nonblock 'hello' }
211 assert CALLED.empty? unless ORIGINAL_SOCKET
214 def test_readpartial_lock
216 t = Thread.new { @rd.readpartial(5, s) }
217 Thread.pass until s.size == 5
218 assert_raise(RuntimeError) { s.clear }
219 @wr.write "foobarbaz"
221 assert_equal("fooba", t.value)
222 assert CALLED.empty? unless ORIGINAL_SOCKET
227 t = Thread.new { @rd.read(5, s) }
228 Thread.pass until s.size == 5
229 assert_raise(RuntimeError) { s.clear }
230 @wr.write "foobarbaz"
232 assert_equal("fooba", t.value)
233 assert CALLED.empty? unless ORIGINAL_SOCKET
237 @wr.write "foobarbaz"
239 assert_equal("foobarbaz", @rd.read)
240 assert CALLED.empty? unless ORIGINAL_SOCKET
243 def test_read_on_nonblock_socket
247 t = Thread.new { @rd.read(6, s) }
248 Thread.pass until s.size == 6
251 assert_equal 'abcdef', t.value
252 assert ! @rd.nonblock? unless ORIGINAL_SOCKET
253 assert CALLED.empty? unless ORIGINAL_SOCKET
256 def test_write_nonblock_raises_eagain
258 assert_raises(Errno::EAGAIN) { loop { @wr.write_nonblock buf } }
261 def test_read_nonblock_raises_eagain
262 assert_raises(Errno::EAGAIN) { @rd.read_nonblock 1 }
263 assert CALLED.empty? unless ORIGINAL_SOCKET
268 assert_nothing_raised { @wr.sync = false }
270 end unless ORIGINAL_SOCKET
276 while io.read(bs, rbuf)
292 def test_read_write_loop_fork
300 _, status = Process.waitpid2(pid)
301 assert status.success?