1 # -*- encoding: binary -*-
10 class Test_IO_Splice < Test::Unit::TestCase
13 (defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby") || !defined?(RUBY_ENGINE)
20 tmp = Tempfile.new('ruby_io_splice')
22 assert_nothing_raised {
27 nr = IO.splice(tmp.fileno, nil, wr.fileno, nil, size, 0)
29 assert_equal str, rd.sysread(size)
36 tmp = Tempfile.new('ruby_io_splice')
38 assert_nothing_raised {
43 nr = IO.splice(tmp, nil, wr, nil, size, 0)
45 assert_equal str, rd.sysread(size)
48 def test_splice_io_noflags
52 tmp = Tempfile.new('ruby_io_splice')
54 assert_nothing_raised {
59 nr = IO.splice(tmp, nil, wr, nil, size)
61 assert_equal str, rd.sysread(size)
64 def test_trysplice_io_noflags
68 tmp = Tempfile.new('ruby_io_splice')
70 assert_nothing_raised {
75 nr = IO.trysplice(tmp, nil, wr, nil, size)
77 assert_equal str, rd.sysread(size)
80 def test_splice_io_ish
84 tmp = Tempfile.new('ruby_io_splice')
90 assert_nothing_raised {
95 nr = IO.splice(io_ish, nil, wr, nil, size, 0)
97 assert_equal str, rd.sysread(size)
100 def test_splice_in_offset
105 tmp = Tempfile.new('ruby_io_splice')
107 assert_nothing_raised {
112 nr = IO.splice(tmp.fileno, off, wr.fileno, nil, len, 0)
114 assert_equal 'de', rd.sysread(len)
117 def test_splice_out_offset
120 tmp = Tempfile.new('ruby_io_splice')
122 assert_nothing_raised { wr.syswrite(str) }
123 nr = IO.splice(rd.fileno, nil, tmp.fileno, 3, str.size, 0)
125 assert_nothing_raised { tmp.sysseek(0) }
126 assert_equal "\0\0\0abcde", tmp.sysread(9)
129 def test_splice_nonblock
131 tmp = Tempfile.new('ruby_io_splice')
133 assert_raises(Errno::EAGAIN) {
134 IO.splice(rd.fileno, nil, tmp.fileno, 0, 5, IO::Splice::F_NONBLOCK)
138 def test_trysplice_nonblock
140 tmp = Tempfile.new('ruby_io_splice')
141 assert_equal :EAGAIN,
142 IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
145 def test_trysplice_nonblock_noargs
147 tmp = Tempfile.new('ruby_io_splice')
148 assert_equal :EAGAIN, IO.trysplice(rd, nil, tmp, 0, 5)
149 assert_equal :EAGAIN, IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_MORE)
154 tmp = Tempfile.new('ruby_io_splice')
158 nr = IO.splice(rd.fileno, nil, tmp.fileno, 0, 5, IO::Splice::F_NONBLOCK)
160 assert_raises(EOFError) {
161 IO.splice(rd.fileno, nil, tmp.fileno, 0, 5, IO::Splice::F_NONBLOCK)
165 def test_trysplice_eof
167 tmp = Tempfile.new('ruby_io_splice')
171 nr = IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
173 assert_nil IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
176 def test_splice_nonblock_socket
177 server = TCPServer.new('127.0.0.1', 0)
178 port = server.addr[1]
180 rs = TCPSocket.new('127.0.0.1', port)
182 assert_raises(Errno::EAGAIN) { IO.splice(rs, nil, wp, nil, 1024, 0) }
193 assert_nothing_raised { wra.syswrite(str) }
194 nr = IO.tee(rda.fileno, wrb.fileno, size, 0)
196 assert_equal str, rdb.sysread(5)
197 assert_equal str, rda.sysread(5)
206 assert_nothing_raised { wra.syswrite(str) }
207 nr = IO.trytee(rda, wrb, size, 0)
209 assert_equal str, rdb.sysread(5)
210 assert_equal str, rda.sysread(5)
217 assert_raises(EOFError) { IO.tee(rda.fileno, wrb.fileno, 4096, 0) }
224 assert_nil IO.trytee(rda, wrb, 4096)
227 def test_tee_nonblock
230 assert_raises(Errno::EAGAIN) {
231 IO.tee(rda.fileno, wrb.fileno, 4096, IO::Splice::F_NONBLOCK)
235 def test_trytee_nonblock
238 assert_equal :EAGAIN, IO.trytee(rda, wrb, 4096)
247 assert_nothing_raised { wra.syswrite(str) }
248 nr = IO.tee(rda, wrb, size, 0)
250 assert_equal str, rdb.sysread(5)
251 assert_equal str, rda.sysread(5)
254 def test_vmsplice_array
255 data = %w(hello world how are you today)
257 n = IO.vmsplice(w.fileno, data, 0)
258 assert_equal data.join('').size, n
259 assert_equal data.join(''), r.readpartial(16384)
262 def test_vmsplice_noflags
263 data = %w(hello world how are you today)
265 n = IO.vmsplice(w, data)
266 assert_equal data.join('').size, n
267 assert_equal data.join(''), r.readpartial(16384)
270 def test_vmsplice_string
272 assert_equal 5, IO.vmsplice(w, 'hello', 0)
273 assert_equal 'hello', r.read(5)
276 def test_vmsplice_array_io
277 data = %w(hello world how are you today)
279 n = IO.vmsplice(w, data, 0)
280 assert_equal data.join('').size, n
281 assert_equal data.join(''), r.readpartial(16384)
284 def test_vmsplice_nonblock
285 data = %w(hello world how are you today)
287 w.syswrite('.' * IO::Splice::PIPE_CAPA)
288 assert_raises(Errno::EAGAIN) {
289 IO.vmsplice(w.fileno, data, IO::Splice::F_NONBLOCK)
293 def test_vmsplice_in_full
296 # bs * count should be > PIPE_BUF
297 [ [ 512, 512 ], [ 131073, 3 ], [ 4098, 64 ] ].each do |(bs,count)|
299 buf = File.open('/dev/urandom', 'rb') { |fp| fp.sysread(bs) }
301 vec = (1..count).map { buf }
307 tmp << rd.readpartial(8192)
311 ok = (vec.join(empty) == tmp.join(empty))
314 assert_nothing_raised { rd.close }
315 assert_equal(bs * count, IO.vmsplice(wr.fileno, vec, 0))
316 assert_nothing_raised { wr.close }
317 _, status = Process.waitpid2(pid)
318 assert status.success?
322 def test_vmsplice_nil
323 data = %w(hello world how are you today)
324 assert_raises(TypeError) { IO.vmsplice(nil, data, 0) }
328 assert IO::Splice::PIPE_BUF > 0
329 %w(move nonblock more gift).each { |x|
330 assert Integer === IO::Splice.const_get("F_#{x.upcase}")
332 assert IO::Splice::PIPE_CAPA >= IO::Splice::PIPE_BUF
335 def test_splice_copy_stream_file_to_file_small
336 a, b = Tempfile.new('a'), Tempfile.new('b')
337 a.syswrite 'hello world'
339 IO::Splice.copy_stream(a, b)
341 assert_equal 'hello world', b.read
344 def test_splice_copy_stream_file_to_file_big
345 buf = ('ab' * IO::Splice::PIPE_CAPA) + 'hi'
346 a, b = Tempfile.new('a'), Tempfile.new('b')
349 IO::Splice.copy_stream(a, b)
351 assert_equal buf, b.read
354 def test_splice_copy_stream_file_to_file_big_partial
355 nr = IO::Splice::PIPE_CAPA
356 buf = ('ab' * nr) + 'hi'
357 a, b = Tempfile.new('a'), Tempfile.new('b')
360 assert_equal nr, IO::Splice.copy_stream(a, b, nr)
362 assert_equal('ab' * (nr/2), b.read)
365 def test_splice_copy_stream_file_to_file_len
366 a, b = Tempfile.new('a'), Tempfile.new('b')
367 a.syswrite 'hello world'
369 IO::Splice.copy_stream(a, b, 5)
371 assert_equal 'hello', b.read
374 def test_splice_copy_stream_pipe_to_file_len
375 a = Tempfile.new('a')
377 w.syswrite 'hello world'
378 IO::Splice.copy_stream(r, a, 5)
380 assert_equal 'hello', a.read
383 def test_splice_copy_stream_paths
384 a = Tempfile.new('a')
385 b = Tempfile.new('a')
386 a.syswrite('hello world')
387 IO::Splice.copy_stream(a.path, b.path, 5)
388 assert_equal 'hello', b.read
391 def test_splice_copy_stream_src_offset
392 a = Tempfile.new('a')
393 b = Tempfile.new('a')
394 a.syswrite('hello world')
395 IO::Splice.copy_stream(a.path, b.path, 5, 6)
396 assert_equal 'world', b.read
399 def test_splice_copy_stream_src_offset_unchanged
400 a = Tempfile.new('a')
401 b = Tempfile.new('a')
402 a.syswrite('hello world')
403 assert_equal 0, a.sysseek(0, IO::SEEK_SET)
404 IO::Splice.copy_stream(a, b.path, 5, 6)
405 assert_equal 'world', b.read
406 assert_equal 0, a.sysseek(0, IO::SEEK_CUR)
409 def test_copy_stream_nonblock_src
410 server = TCPServer.new('127.0.0.1', 0)
411 port = server.addr[1]
413 rs = TCPSocket.new('127.0.0.1', port)
416 assert_raises(Timeout::Error) do
417 timeout(0.05) { nr += IO::Splice.copy_stream(rs, wp, 5) }
424 def test_copy_stream_nonblock_dst
425 server = TCPServer.new('127.0.0.1', 0)
426 port = server.addr[1]
428 rs = TCPSocket.new('127.0.0.1', port)
430 client = server.accept
431 buf = ' ' * IO::Splice::PIPE_CAPA
433 assert_raises(Timeout::Error) do
436 wp.write_nonblock(buf)
440 nr += IO::Splice.copy_stream(rp, rs, IO::Splice::PIPE_CAPA)
444 assert_equal nr, client.read(nr).size
449 def test_copy_stream_eof
451 w.syswrite 'hello world'
453 a = Tempfile.new('a')
454 assert_equal 11, IO::Splice.copy_stream(r, a)
456 assert_equal 'hello world', a.read
461 assert_kind_of Integer, r.pipe_size
462 assert(r.pipe_size >= 512)
463 assert_nothing_raised { w.pipe_size = 8192 }
464 assert_equal 8192, r.pipe_size
467 assert_raises(Errno::EBUSY) { r.pipe_size = 4096 }
469 pipe_max_size = File.read("/proc/sys/fs/pipe-max-size").to_i
470 assert_nothing_raised { r.pipe_size = pipe_max_size }
471 assert_raises(Errno::EPERM) { r.pipe_size = pipe_max_size * 2 }
472 end if IO.method_defined?(:pipe_size)