1 # -*- encoding: binary -*-
10 class Test_IO_Splice < Test::Unit::TestCase
16 tmp = Tempfile.new('ruby_io_splice')
18 assert_nothing_raised {
23 nr = IO.splice(tmp.fileno, nil, wr.fileno, nil, size, 0)
25 assert_equal str, rd.sysread(size)
32 tmp = Tempfile.new('ruby_io_splice')
34 assert_nothing_raised {
39 nr = IO.splice(tmp, nil, wr, nil, size, 0)
41 assert_equal str, rd.sysread(size)
44 def test_splice_io_noflags
48 tmp = Tempfile.new('ruby_io_splice')
50 assert_nothing_raised {
55 nr = IO.splice(tmp, nil, wr, nil, size)
57 assert_equal str, rd.sysread(size)
60 def test_trysplice_io_noflags
64 tmp = Tempfile.new('ruby_io_splice')
66 assert_nothing_raised {
71 nr = IO.trysplice(tmp, nil, wr, nil, size)
73 assert_equal str, rd.sysread(size)
76 def test_splice_io_ish
80 tmp = Tempfile.new('ruby_io_splice')
86 assert_nothing_raised {
91 nr = IO.splice(io_ish, nil, wr, nil, size, 0)
93 assert_equal str, rd.sysread(size)
96 def test_splice_in_offset
101 tmp = Tempfile.new('ruby_io_splice')
103 assert_nothing_raised {
108 nr = IO.splice(tmp.fileno, off, wr.fileno, nil, len, 0)
110 assert_equal 'de', rd.sysread(len)
113 def test_splice_out_offset
116 tmp = Tempfile.new('ruby_io_splice')
118 assert_nothing_raised { wr.syswrite(str) }
119 nr = IO.splice(rd.fileno, nil, tmp.fileno, 3, str.size, 0)
121 assert_nothing_raised { tmp.sysseek(0) }
122 assert_equal "\0\0\0abcde", tmp.sysread(9)
125 def test_splice_nonblock
127 tmp = Tempfile.new('ruby_io_splice')
129 assert_raises(Errno::EAGAIN) {
130 IO.splice(rd.fileno, nil, tmp.fileno, 0, 5, IO::Splice::F_NONBLOCK)
134 def test_trysplice_nonblock
136 tmp = Tempfile.new('ruby_io_splice')
137 assert_equal :EAGAIN,
138 IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
141 def test_trysplice_nonblock_noargs
143 tmp = Tempfile.new('ruby_io_splice')
144 assert_equal :EAGAIN, IO.trysplice(rd, nil, tmp, 0, 5)
145 assert_equal :EAGAIN, IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_MORE)
150 tmp = Tempfile.new('ruby_io_splice')
154 nr = IO.splice(rd.fileno, nil, tmp.fileno, 0, 5, IO::Splice::F_NONBLOCK)
156 assert_raises(EOFError) {
157 IO.splice(rd.fileno, nil, tmp.fileno, 0, 5, IO::Splice::F_NONBLOCK)
161 def test_trysplice_eof
163 tmp = Tempfile.new('ruby_io_splice')
167 nr = IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
169 assert_nil IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
172 def test_splice_nonblock_socket
173 server = TCPServer.new('127.0.0.1', 0)
174 port = server.addr[1]
176 rs = TCPSocket.new('127.0.0.1', port)
178 assert_raises(Errno::EAGAIN) { IO.splice(rs, nil, wp, nil, 1024, 0) }
189 assert_nothing_raised { wra.syswrite(str) }
190 nr = IO.tee(rda.fileno, wrb.fileno, size, 0)
192 assert_equal str, rdb.sysread(5)
193 assert_equal str, rda.sysread(5)
202 assert_nothing_raised { wra.syswrite(str) }
203 nr = IO.trytee(rda, wrb, size, 0)
205 assert_equal str, rdb.sysread(5)
206 assert_equal str, rda.sysread(5)
213 assert_raises(EOFError) { IO.tee(rda.fileno, wrb.fileno, 4096, 0) }
220 assert_nil IO.trytee(rda, wrb, 4096)
223 def test_tee_nonblock
226 assert_raises(Errno::EAGAIN) {
227 IO.tee(rda.fileno, wrb.fileno, 4096, IO::Splice::F_NONBLOCK)
231 def test_trytee_nonblock
234 assert_equal :EAGAIN, IO.trytee(rda, wrb, 4096)
243 assert_nothing_raised { wra.syswrite(str) }
244 nr = IO.tee(rda, wrb, size, 0)
246 assert_equal str, rdb.sysread(5)
247 assert_equal str, rda.sysread(5)
250 def test_vmsplice_array
251 data = %w(hello world how are you today)
253 n = IO.vmsplice(w.fileno, data, 0)
254 assert_equal data.join('').size, n
255 assert_equal data.join(''), r.readpartial(16384)
258 def test_vmsplice_noflags
259 data = %w(hello world how are you today)
261 n = IO.vmsplice(w, data)
262 assert_equal data.join('').size, n
263 assert_equal data.join(''), r.readpartial(16384)
266 def test_vmsplice_string
268 assert_equal 5, IO.vmsplice(w, 'hello', 0)
269 assert_equal 'hello', r.read(5)
272 def test_vmsplice_array_io
273 data = %w(hello world how are you today)
275 n = IO.vmsplice(w, data, 0)
276 assert_equal data.join('').size, n
277 assert_equal data.join(''), r.readpartial(16384)
280 def test_vmsplice_nonblock
281 data = %w(hello world how are you today)
283 w.syswrite('.' * IO::Splice::PIPE_CAPA)
284 assert_raises(Errno::EAGAIN) {
285 IO.vmsplice(w.fileno, data, IO::Splice::F_NONBLOCK)
289 def test_vmsplice_in_full
292 # bs * count should be > PIPE_BUF
293 [ [ 512, 512 ], [ 131073, 3 ], [ 4098, 64 ] ].each do |(bs,count)|
295 buf = File.open('/dev/urandom', 'rb') { |fp| fp.sysread(bs) }
297 vec = (1..count).map { buf }
303 tmp << rd.readpartial(8192)
307 ok = (vec.join(empty) == tmp.join(empty))
310 assert_nothing_raised { rd.close }
311 assert_equal(bs * count, IO.vmsplice(wr.fileno, vec, 0))
312 assert_nothing_raised { wr.close }
313 _, status = Process.waitpid2(pid)
314 assert status.success?
318 def test_vmsplice_nil
319 data = %w(hello world how are you today)
320 assert_raises(TypeError) { IO.vmsplice(nil, data, 0) }
324 assert IO::Splice::PIPE_BUF > 0
325 %w(move nonblock more gift).each { |x|
326 assert Integer === IO::Splice.const_get("F_#{x.upcase}")
328 assert IO::Splice::PIPE_CAPA >= IO::Splice::PIPE_BUF
331 def test_splice_copy_stream_file_to_file_small
332 a, b = Tempfile.new('a'), Tempfile.new('b')
333 a.syswrite 'hello world'
335 IO::Splice.copy_stream(a, b)
337 assert_equal 'hello world', b.read
340 def test_splice_copy_stream_file_to_file_big
341 buf = ('ab' * IO::Splice::PIPE_CAPA) + 'hi'
342 a, b = Tempfile.new('a'), Tempfile.new('b')
345 IO::Splice.copy_stream(a, b)
347 assert_equal buf, b.read
350 def test_splice_copy_stream_file_to_file_big_partial
351 nr = IO::Splice::PIPE_CAPA
352 buf = ('ab' * nr) + 'hi'
353 a, b = Tempfile.new('a'), Tempfile.new('b')
356 assert_equal nr, IO::Splice.copy_stream(a, b, nr)
358 assert_equal('ab' * (nr/2), b.read)
361 def test_splice_copy_stream_file_to_file_len
362 a, b = Tempfile.new('a'), Tempfile.new('b')
363 a.syswrite 'hello world'
365 IO::Splice.copy_stream(a, b, 5)
367 assert_equal 'hello', b.read
370 def test_splice_copy_stream_pipe_to_file_len
371 a = Tempfile.new('a')
373 w.syswrite 'hello world'
374 IO::Splice.copy_stream(r, a, 5)
376 assert_equal 'hello', a.read
379 def test_splice_copy_stream_paths
380 a = Tempfile.new('a')
381 b = Tempfile.new('a')
382 a.syswrite('hello world')
383 IO::Splice.copy_stream(a.path, b.path, 5)
384 assert_equal 'hello', b.read
387 def test_splice_copy_stream_src_offset
388 a = Tempfile.new('a')
389 b = Tempfile.new('a')
390 a.syswrite('hello world')
391 IO::Splice.copy_stream(a.path, b.path, 5, 6)
392 assert_equal 'world', b.read
395 def test_copy_stream_nonblock_src
396 server = TCPServer.new('127.0.0.1', 0)
397 port = server.addr[1]
399 rs = TCPSocket.new('127.0.0.1', port)
402 assert_raises(Timeout::Error) do
403 timeout(0.05) { nr += IO::Splice.copy_stream(rs, wp, 5) }
410 def test_copy_stream_nonblock_dst
411 server = TCPServer.new('127.0.0.1', 0)
412 port = server.addr[1]
414 rs = TCPSocket.new('127.0.0.1', port)
416 client = server.accept
417 buf = ' ' * IO::Splice::PIPE_CAPA
419 assert_raises(Timeout::Error) do
422 wp.write_nonblock(buf)
426 nr += IO::Splice.copy_stream(rp, rs, IO::Splice::PIPE_CAPA)
430 assert_equal nr, client.read(nr).size
435 def test_copy_stream_eof
437 w.syswrite 'hello world'
439 a = Tempfile.new('a')
440 assert_equal 11, IO::Splice.copy_stream(r, a)
442 assert_equal 'hello world', a.read
447 assert_kind_of Integer, r.pipe_size
448 assert(r.pipe_size >= 512)
449 assert_nothing_raised { w.pipe_size = 8192 }
450 assert_equal 8192, r.pipe_size
453 assert_raises(Errno::EBUSY) { r.pipe_size = 4096 }
455 pipe_max_size = File.read("/proc/sys/fs/pipe-max-size").to_i
456 assert_nothing_raised { r.pipe_size = pipe_max_size }
457 assert_raises(Errno::EPERM) { r.pipe_size = pipe_max_size * 2 }
458 end if IO.method_defined?(:pipe_size)