remove copy_stream tests and references
[ruby_io_splice.git] / test / test_io_splice.rb
blobba66a6155aea55632e1ca69be7cf77fac828f431
1 # -*- encoding: binary -*-
2 require 'test/unit'
3 require 'tempfile'
4 require 'socket'
5 require 'io/nonblock'
6 require 'timeout'
7 $-w = true
8 require 'io/splice'
10 class Test_IO_Splice < Test::Unit::TestCase
12   def self.mri?
13     (defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby") || !defined?(RUBY_ENGINE)
14   end
16   def test_splice
17     str = 'abcde'
18     size = 5
19     rd, wr = IO.pipe
20     tmp = Tempfile.new('ruby_io_splice')
22     assert_nothing_raised {
23       tmp.syswrite(str)
24       tmp.sysseek(0)
25     }
27     nr = IO.splice(tmp.fileno, nil, wr.fileno, nil, size, 0)
28     assert_equal size, nr
29     assert_equal str, rd.sysread(size)
30   end
32   def test_splice_io
33     str = 'abcde'
34     size = 5
35     rd, wr = IO.pipe
36     tmp = Tempfile.new('ruby_io_splice')
38     assert_nothing_raised {
39       tmp.syswrite(str)
40       tmp.sysseek(0)
41     }
43     nr = IO.splice(tmp, nil, wr, nil, size, 0)
44     assert_equal size, nr
45     assert_equal str, rd.sysread(size)
46   end
48   def test_splice_io_noflags
49     str = 'abcde'
50     size = 5
51     rd, wr = IO.pipe
52     tmp = Tempfile.new('ruby_io_splice')
54     assert_nothing_raised {
55       tmp.syswrite(str)
56       tmp.sysseek(0)
57     }
59     nr = IO.splice(tmp, nil, wr, nil, size)
60     assert_equal size, nr
61     assert_equal str, rd.sysread(size)
62   end
64   def test_trysplice_io_noflags
65     str = 'abcde'
66     size = 5
67     rd, wr = IO.pipe
68     tmp = Tempfile.new('ruby_io_splice')
70     assert_nothing_raised {
71       tmp.syswrite(str)
72       tmp.sysseek(0)
73     }
75     nr = IO.trysplice(tmp, nil, wr, nil, size)
76     assert_equal size, nr
77     assert_equal str, rd.sysread(size)
78   end
80   def test_splice_io_ish
81     str = 'abcde'
82     size = 5
83     rd, wr = IO.pipe
84     tmp = Tempfile.new('ruby_io_splice')
85     io_ish = [ tmp ]
86     def io_ish.to_io
87       first.to_io
88     end
90     assert_nothing_raised {
91       tmp.syswrite(str)
92       tmp.sysseek(0)
93     }
95     nr = IO.splice(io_ish, nil, wr, nil, size, 0)
96     assert_equal size, nr
97     assert_equal str, rd.sysread(size)
98   end
100   def test_splice_in_offset
101     str = 'abcde'
102     off = 3
103     len = 2
104     rd, wr = IO.pipe
105     tmp = Tempfile.new('ruby_io_splice')
107     assert_nothing_raised {
108       tmp.syswrite(str)
109       tmp.sysseek(0)
110     }
112     nr = IO.splice(tmp.fileno, off, wr.fileno, nil, len, 0)
113     assert_equal len, nr
114     assert_equal 'de', rd.sysread(len)
115   end
117   def test_splice_out_offset
118     str = 'abcde'
119     rd, wr = IO.pipe
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)
124     assert_equal 5, nr
125     assert_nothing_raised { tmp.sysseek(0) }
126     assert_equal "\0\0\0abcde", tmp.sysread(9)
127   end
129   def test_splice_nonblock
130     rd, wr = IO.pipe
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)
135     }
136   end
138   def test_trysplice_nonblock
139     rd, wr = IO.pipe
140     tmp = Tempfile.new('ruby_io_splice')
141     assert_equal :EAGAIN,
142            IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
143   end
145   def test_trysplice_nonblock_noargs
146     rd, wr = IO.pipe
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)
150   end
152   def test_splice_eof
153     rd, wr = IO.pipe
154     tmp = Tempfile.new('ruby_io_splice')
155     wr.syswrite 'abc'
156     wr.close
158     nr = IO.splice(rd.fileno, nil, tmp.fileno, 0, 5, IO::Splice::F_NONBLOCK)
159     assert_equal 3, nr
160     assert_raises(EOFError) {
161       IO.splice(rd.fileno, nil, tmp.fileno, 0, 5, IO::Splice::F_NONBLOCK)
162     }
163   end
165   def test_trysplice_eof
166     rd, wr = IO.pipe
167     tmp = Tempfile.new('ruby_io_splice')
168     wr.syswrite 'abc'
169     wr.close
171     nr = IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
172     assert_equal 3, nr
173     assert_nil IO.trysplice(rd, nil, tmp, 0, 5, IO::Splice::F_NONBLOCK)
174   end
176   def test_splice_nonblock_socket
177     server = TCPServer.new('127.0.0.1', 0)
178     port = server.addr[1]
179     rp, wp = IO.pipe
180     rs = TCPSocket.new('127.0.0.1', port)
181     rs.nonblock = true
182     assert_raises(Errno::EAGAIN) { IO.splice(rs, nil, wp, nil, 1024, 0) }
183     rs.close
184     server.close
185   end
187   def test_tee
188     str = 'abcde'
189     size = 5
190     rda, wra = IO.pipe
191     rdb, wrb = IO.pipe
193     assert_nothing_raised { wra.syswrite(str) }
194     nr = IO.tee(rda.fileno, wrb.fileno, size, 0)
195     assert_equal 5, nr
196     assert_equal str, rdb.sysread(5)
197     assert_equal str, rda.sysread(5)
198   end
200   def test_trytee
201     str = 'abcde'
202     size = 5
203     rda, wra = IO.pipe
204     rdb, wrb = IO.pipe
206     assert_nothing_raised { wra.syswrite(str) }
207     nr = IO.trytee(rda, wrb, size, 0)
208     assert_equal 5, nr
209     assert_equal str, rdb.sysread(5)
210     assert_equal str, rda.sysread(5)
211   end
213   def test_tee_eof
214     rda, wra = IO.pipe
215     rdb, wrb = IO.pipe
216     wra.close
217     assert_raises(EOFError) { IO.tee(rda.fileno, wrb.fileno, 4096, 0) }
218   end
220   def test_trytee_eof
221     rda, wra = IO.pipe
222     rdb, wrb = IO.pipe
223     wra.close
224     assert_nil IO.trytee(rda, wrb, 4096)
225   end
227   def test_tee_nonblock
228     rda, wra = IO.pipe
229     rdb, wrb = IO.pipe
230     assert_raises(Errno::EAGAIN) {
231       IO.tee(rda.fileno, wrb.fileno, 4096, IO::Splice::F_NONBLOCK)
232     }
233   end
235   def test_trytee_nonblock
236     rda, wra = IO.pipe
237     rdb, wrb = IO.pipe
238     assert_equal :EAGAIN, IO.trytee(rda, wrb, 4096)
239   end
241   def test_tee_io
242     str = 'abcde'
243     size = 5
244     rda, wra = IO.pipe
245     rdb, wrb = IO.pipe
247     assert_nothing_raised { wra.syswrite(str) }
248     nr = IO.tee(rda, wrb, size, 0)
249     assert_equal 5, nr
250     assert_equal str, rdb.sysread(5)
251     assert_equal str, rda.sysread(5)
252   end
254   def test_vmsplice_array
255     data = %w(hello world how are you today)
256     r, w = IO.pipe
257     n = IO.vmsplice(w.fileno, data, 0)
258     assert_equal data.join('').size, n
259     assert_equal data.join(''), r.readpartial(16384)
260   end
262   def test_vmsplice_noflags
263     data = %w(hello world how are you today)
264     r, w = IO.pipe
265     n = IO.vmsplice(w, data)
266     assert_equal data.join('').size, n
267     assert_equal data.join(''), r.readpartial(16384)
268   end
270   def test_vmsplice_string
271     r, w = IO.pipe
272     assert_equal 5, IO.vmsplice(w, 'hello', 0)
273     assert_equal 'hello', r.read(5)
274   end
276   def test_vmsplice_array_io
277     data = %w(hello world how are you today)
278     r, w = IO.pipe
279     n = IO.vmsplice(w, data, 0)
280     assert_equal data.join('').size, n
281     assert_equal data.join(''), r.readpartial(16384)
282   end
284   def test_vmsplice_nonblock
285     data = %w(hello world how are you today)
286     r, w = IO.pipe
287     w.syswrite('.' * IO::Splice::PIPE_CAPA)
288     assert_raises(Errno::EAGAIN) {
289       IO.vmsplice(w.fileno, data, IO::Splice::F_NONBLOCK)
290     }
291   end
293   def test_vmsplice_in_full
294     empty = ""
296     # bs * count should be > PIPE_BUF
297     [ [ 512, 512 ], [ 131073, 3 ], [ 4098, 64 ] ].each do |(bs,count)|
298       rd, wr = IO.pipe
299       buf = File.open('/dev/urandom', 'rb') { |fp| fp.sysread(bs) }
301       vec = (1..count).map { buf }
302       pid = fork do
303         wr.close
304         tmp = []
305         begin
306           sleep 0.005
307           tmp << rd.readpartial(8192)
308         rescue EOFError
309           break
310         end while true
311         ok = (vec.join(empty) == tmp.join(empty))
312         exit! ok
313       end
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?
319     end
320   end
322   def test_vmsplice_nil
323     data = %w(hello world how are you today)
324     assert_raises(TypeError) { IO.vmsplice(nil, data, 0) }
325   end
327   def test_constants
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}")
331     }
332     assert IO::Splice::PIPE_CAPA >= IO::Splice::PIPE_BUF
333   end
335   def test_pipe_size
336     r, w = IO.pipe
337     assert_kind_of Integer, r.pipe_size
338     assert(r.pipe_size >= 512)
339     assert_nothing_raised { w.pipe_size = 8192 }
340     assert_equal 8192, r.pipe_size
342     w.write('*' * 4097)
343     assert_raises(Errno::EBUSY) { r.pipe_size = 4096 }
345     pipe_max_size = File.read("/proc/sys/fs/pipe-max-size").to_i
346     assert_nothing_raised { r.pipe_size = pipe_max_size }
347     assert_raises(Errno::EPERM) { r.pipe_size = pipe_max_size * 2 }
348   end if IO.method_defined?(:pipe_size)