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
24 @rd, @wr = UNIXSocket.pair
29 @rd.close unless @rd.closed?
30 @wr.close unless @wr.closed?
33 def test_write_read_nonblock_str
34 assert_equal 3, @wr.write_nonblock('abc')
35 assert_equal 'abc', @rd.read_nonblock(3)
36 assert CALLED.empty? unless ORIGINAL_SOCKET
39 def test_write_read_nonblock_integer
40 assert_equal 3, @wr.write_nonblock(123)
41 assert_equal '123', @rd.read_nonblock(3)
42 assert CALLED.empty? unless ORIGINAL_SOCKET
45 def test_invalid_read_length
46 assert_raise(ArgumentError) { @rd.read(-1) }
47 assert_raise(ArgumentError) { @rd.read(-1, "") }
48 assert_raise(ArgumentError) { @rd.read_nonblock(-1) }
49 assert_raise(ArgumentError) { @rd.read_nonblock(-1, "") }
50 assert_raise(ArgumentError) { @rd.readpartial(-1) }
51 assert_raise(ArgumentError) { @rd.readpartial(-1, "") }
52 assert CALLED.empty? unless ORIGINAL_SOCKET
57 t = Thread.new { @rd.read 4096 }
58 assert_equal 4093, @wr.write(buf)
61 assert_equal 4, @wr.write('....')
63 assert_equal('.' * 4096, t.value)
64 assert_equal('.', @rd.read(1))
66 assert_nil @rd.read(1)
67 assert CALLED.empty? unless ORIGINAL_SOCKET
72 assert_equal '', @rd.read
74 str_object_id = str.object_id
75 assert_equal str_object_id, @rd.read(nil, str).object_id
76 assert CALLED.empty? unless ORIGINAL_SOCKET
79 def test_big_write_read_full_even
80 tmp = IO.read('/dev/urandom', 16427) * 32
81 tmp << '.' until ((tmp.bytesize % 16384) == 0)
85 exit!(nr == tmp.bytesize)
88 assert_equal tmp, @rd.read
89 _, status = Process.waitpid2(pid)
90 assert status.success?
91 assert CALLED.empty? unless ORIGINAL_SOCKET
94 def test_big_write_read_full_odd
95 n = @wr.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).unpack('i')[0]
96 tmp = IO.read('/dev/urandom', 16427) * 32
97 tmp << 'aasdfzf' until ((tmp.bytesize % 16384) != 0)
100 exit!(nr == tmp.bytesize)
103 assert_equal tmp, @rd.read
104 _, status = Process.waitpid2(pid)
105 assert status.success?
106 assert CALLED.empty? unless ORIGINAL_SOCKET
110 assert_equal '', @rd.read(0)
111 assert_equal '', @rd.readpartial(0)
112 assert_equal '', @rd.read_nonblock(0)
115 assert_equal buf.object_id, @rd.read(0, buf).object_id
118 assert_equal buf.object_id, @rd.readpartial(0, buf).object_id
121 assert_equal buf.object_id, @rd.read_nonblock(0, buf).object_id
125 def test_readpartial_signal
129 trap(:USR1) { w.syswrite "USR1" }
131 rv = @rd.readpartial(16384)
132 exit!(rv == "SIGNAL SAFE" && (ORIGINAL_SOCKET || CALLED.empty?))
135 assert_equal "READY", r.read(5)
136 assert_nothing_raised do
137 sleep 0.5 # ugh, still potentially racy :<
138 Process.kill(:USR1, pid)
140 assert_equal 'USR1', r.readpartial(4)
141 assert_equal 11, @wr.write("SIGNAL SAFE")
142 _, status = Process.waitpid2(pid)
143 assert status.success?
150 trap(:USR1) { w.syswrite "USR1" }
153 exit!(rv == "SIGNAL SAFE" && (ORIGINAL_SOCKET || CALLED.empty?))
156 assert_equal "READY", r.read(5)
157 assert_nothing_raised do
158 sleep 0.5 # ugh, still potentially racy :<
159 Process.kill(:USR1, pid)
161 assert_equal 'USR1', r.readpartial(4)
162 assert_equal 11, @wr.write("SIGNAL SAFE")
163 _, status = Process.waitpid2(pid)
164 assert status.success?
169 assert_raises(IOError) { @rd.read }
170 assert CALLED.empty? unless ORIGINAL_SOCKET
173 def test_closed_write
175 assert_raises(IOError) { @wr.write 'hello' }
176 assert_raises(IOError) { @wr.write_nonblock 'hello' }
177 assert CALLED.empty? unless ORIGINAL_SOCKET
180 def test_closed_writer_read
182 assert_raises(EOFError) { @rd.readpartial 5 }
183 assert_raises(EOFError) { @rd.read_nonblock 5 }
184 assert_nil @rd.read(5)
185 assert CALLED.empty? unless ORIGINAL_SOCKET
188 def test_closed_writer_read_with_buffer
191 assert_raises(EOFError) { @rd.readpartial 5, buf }
195 assert_raises(EOFError) { @rd.read_nonblock 5, buf }
199 assert_nil @rd.read(5, buf)
201 assert CALLED.empty? unless ORIGINAL_SOCKET
204 def test_closed_reader_write
206 assert_raises(Errno::EPIPE) { @wr.write 'hello' }
207 assert_raises(Errno::EPIPE) { @wr.write_nonblock 'hello' }
208 assert CALLED.empty? unless ORIGINAL_SOCKET
211 def test_readpartial_lock
213 t = Thread.new { @rd.readpartial(5, s) }
214 Thread.pass until s.size == 5
215 assert_raise(RuntimeError) { s.clear }
216 @wr.write "foobarbaz"
218 assert_equal("fooba", t.value)
219 assert CALLED.empty? unless ORIGINAL_SOCKET
224 t = Thread.new { @rd.read(5, s) }
225 Thread.pass until s.size == 5
226 assert_raise(RuntimeError) { s.clear }
227 @wr.write "foobarbaz"
229 assert_equal("fooba", t.value)
230 assert CALLED.empty? unless ORIGINAL_SOCKET
234 @wr.write "foobarbaz"
236 assert_equal("foobarbaz", @rd.read)
237 assert CALLED.empty? unless ORIGINAL_SOCKET
240 def test_read_on_nonblock_socket
244 t = Thread.new { @rd.read(6, s) }
245 Thread.pass until s.size == 6
248 assert_equal 'abcdef', t.value
249 assert ! @rd.nonblock? unless ORIGINAL_SOCKET
250 assert CALLED.empty? unless ORIGINAL_SOCKET
253 def test_write_nonblock_raises_eagain
255 assert_raises(Errno::EAGAIN) { loop { @wr.write_nonblock buf } }
258 def test_read_nonblock_raises_eagain
259 assert_raises(Errno::EAGAIN) { @rd.read_nonblock 1 }
260 assert CALLED.empty? unless ORIGINAL_SOCKET
263 def test_gets_fallback_to_super_readpartial_buffers
265 t = Thread.new { @rd.gets }
270 assert "hi\n", t.value
271 assert_equal "bye\n", @rd.readpartial(60)
272 assert_equal({ :readpartial => [ 60 ]}, CALLED)
275 def test_gets_fallback_to_super_read_buffers
277 t = Thread.new { @rd.gets }
282 assert "hi\n", t.value
283 assert_equal "bye\n", @rd.read(4)
284 assert_equal({ :read => [ 4 ]}, CALLED)
287 def test_gets_fallback_to_super_read_nonblock_buffers
289 t = Thread.new { @rd.gets }
294 assert "hi\n", t.value
295 assert_equal "bye\n", @rd.read_nonblock(40)
296 assert_equal({ :read_nonblock => [ 40 ]}, CALLED)
301 assert_nothing_raised { @wr.sync = false }
303 end unless ORIGINAL_SOCKET