read_write: call rb_str_modify() before rb_str_resize()
[kgio.git] / test / lib_read_write.rb
blobd7f50c269f152b2439fd81b8c106e267af2f627b
1 # -*- encoding: binary -*-
2 require 'test/unit'
3 require 'io/nonblock'
4 require 'digest/sha1'
5 $-w = true
6 require 'kgio'
8 module LibReadWriteTest
9   RANDOM_BLOB = File.open("/dev/urandom") { |fp| fp.read(10 * 1024 * 1024) }
11   def teardown
12     assert_nothing_raised do
13       @rd.close if defined?(@rd) && ! @rd.closed?
14       @wr.close if defined?(@wr) && ! @wr.closed?
15     end
16   end
18   def test_write_empty
19     assert_nil @wr.kgio_write("")
20   end
22   def test_trywrite_empty
23     assert_nil @wr.kgio_trywrite("")
24   end
26   def test_read_zero
27     assert_equal "", @rd.kgio_read(0)
28     buf = "foo"
29     assert_equal buf.object_id, @rd.kgio_read(0, buf).object_id
30     assert_equal "", buf
31   end
33   def test_read_shared
34     a = "." * 0x1000
35     b = a.dup
36     @wr.syswrite "a"
37     assert_equal "a", @rd.kgio_read(0x1000, a)
38     assert_equal "a", a
39     assert_equal "." * 0x1000, b
40   end
42   def test_read_shared_2
43     a = "." * 0x1000
44     b = a.dup
45     @wr.syswrite "a"
46     assert_equal "a", @rd.kgio_read(0x1000, b)
47     assert_equal "a", b
48     assert_equal "." * 0x1000, a
49   end
51   def test_tryread_zero
52     assert_equal "", @rd.kgio_tryread(0)
53     buf = "foo"
54     assert_equal buf.object_id, @rd.kgio_tryread(0, buf).object_id
55     assert_equal "", buf
56   end
58   def test_tryread_shared
59     a = "." * 0x1000
60     b = a.dup
61     @wr.syswrite("a")
62     assert_equal "a", @rd.kgio_tryread(0x1000, b)
63     assert_equal "a", b
64     assert_equal "." * 0x1000, a
65   end
67   def test_tryread_shared_2
68     a = "." * 0x1000
69     b = a.dup
70     @wr.syswrite("a")
71     assert_equal "a", @rd.kgio_tryread(0x1000, a)
72     assert_equal "a", a
73     assert_equal "." * 0x1000, b
74   end
76   def test_read_eof
77     @wr.close
78     assert_nil @rd.kgio_read(5)
79   end
81   def test_read_bang_eof
82     @wr.close
83     begin
84       @rd.kgio_read!(5)
85       assert false, "should never get here (line:#{__LINE__})"
86     rescue EOFError => e
87       assert_equal [], e.backtrace
88     end
89   end
91   def test_tryread_eof
92     @wr.close
93     assert_nil @rd.kgio_tryread(5)
94   end
96   def test_write_closed
97     @rd.close
98     begin
99       loop { @wr.kgio_write "HI" }
100     rescue Errno::EPIPE, Errno::ECONNRESET => e
101       assert_equal [], e.backtrace
102       return
103     end
104     assert false, "should never get here (line:#{__LINE__})"
105   end
107   def test_trywrite_closed
108     @rd.close
109     begin
110       loop { @wr.kgio_trywrite "HI" }
111     rescue Errno::EPIPE, Errno::ECONNRESET => e
112       assert_equal [], e.backtrace
113       return
114     end
115     assert false, "should never get here (line:#{__LINE__})"
116   end
118   def test_trywrite_full
119     buf = "\302\251" * 1024 * 1024
120     buf2 = ""
121     dig = Digest::SHA1.new
122     t = Thread.new do
123       sleep 1
124       nr = 0
125       begin
126         dig.update(@rd.readpartial(4096, buf2))
127         nr += buf2.size
128       rescue EOFError
129         break
130       rescue => e
131       end while true
132       dig.hexdigest
133     end
134     50.times do
135       wr = buf
136       begin
137         rv = @wr.kgio_trywrite(wr)
138         case rv
139         when String
140           wr = rv
141         when :wait_readable
142           assert false, "should never get here line=#{__LINE__}"
143         when :wait_writable
144           IO.select(nil, [ @wr ])
145         else
146           wr = false
147         end
148       end while wr
149     end
150     @wr.close
151     t.join
152     assert_equal '8ff79d8115f9fe38d18be858c66aa08a1cc27a66', t.value
153   end
155   def test_write_conv
156     assert_equal nil, @wr.kgio_write(10)
157     assert_equal "10", @rd.kgio_read(2)
158   end
160   def test_trywrite_conv
161     assert_equal nil, @wr.kgio_trywrite(10)
162     assert_equal "10", @rd.kgio_tryread(2)
163   end
165   def test_tryread_empty
166     assert_equal :wait_readable, @rd.kgio_tryread(1)
167   end
169   def test_read_too_much
170     assert_equal nil, @wr.kgio_write("hi")
171     assert_equal "hi", @rd.kgio_read(4)
172   end
174   def test_tryread_too_much
175     assert_equal nil, @wr.kgio_trywrite("hi")
176     assert_equal "hi", @rd.kgio_tryread(4)
177   end
179   def test_read_short
180     assert_equal nil, @wr.kgio_write("hi")
181     assert_equal "h", @rd.kgio_read(1)
182     assert_equal "i", @rd.kgio_read(1)
183   end
185   def test_tryread_short
186     assert_equal nil, @wr.kgio_trywrite("hi")
187     assert_equal "h", @rd.kgio_tryread(1)
188     assert_equal "i", @rd.kgio_tryread(1)
189   end
191   def test_read_extra_buf
192     tmp = ""
193     tmp_object_id = tmp.object_id
194     assert_equal nil, @wr.kgio_write("hi")
195     rv = @rd.kgio_read(2, tmp)
196     assert_equal "hi", rv
197     assert_equal rv.object_id, tmp.object_id
198     assert_equal tmp_object_id, rv.object_id
199   end
201   def test_trywrite_return_wait_writable
202     tmp = []
203     tmp << @wr.kgio_trywrite("HI") until tmp[-1] == :wait_writable
204     assert :wait_writable === tmp[-1]
205     assert(!(:wait_readable === tmp[-1]))
206     assert_equal :wait_writable, tmp.pop
207     assert tmp.size > 0
208     penultimate = tmp.pop
209     assert(penultimate == "I" || penultimate == nil)
210     assert tmp.size > 0
211     tmp.each { |count| assert_equal nil, count }
212   end
214   def test_tryread_extra_buf_eagain_clears_buffer
215     tmp = "hello world"
216     rv = @rd.kgio_tryread(2, tmp)
217     assert_equal :wait_readable, rv
218     assert_equal "", tmp
219   end
221   def test_tryread_extra_buf_eof_clears_buffer
222     tmp = "hello world"
223     @wr.close
224     assert_nil @rd.kgio_tryread(2, tmp)
225     assert_equal "", tmp
226   end
228   def test_monster_trywrite
229     buf = RANDOM_BLOB.dup
230     rv = @wr.kgio_trywrite(buf)
231     assert_kind_of String, rv
232     assert rv.size < buf.size
233     @rd.nonblock = false
234     assert_equal(buf, @rd.read(buf.size - rv.size) + rv)
235   end
237   def test_monster_write
238     buf = RANDOM_BLOB.dup
239     thr = Thread.new { @wr.kgio_write(buf) }
240     @rd.nonblock = false
241     readed = @rd.read(buf.size)
242     thr.join
243     assert_nil thr.value
244     assert_equal buf, readed
245   end
247   def test_monster_write_wait_writable
248     @wr.instance_variable_set :@nr, 0
249     def @wr.kgio_wait_writable
250       @nr += 1
251       IO.select(nil, [self])
252     end
253     buf = "." * 1024 * 1024 * 10
254     thr = Thread.new { @wr.kgio_write(buf) }
255     readed = @rd.read(buf.size)
256     thr.join
257     assert_nil thr.value
258     assert_equal buf, readed
259     assert @wr.instance_variable_get(:@nr) > 0
260   end
262   def test_wait_readable_ruby_default
263     elapsed = 0
264     foo = nil
265     t0 = Time.now
266     thr = Thread.new { sleep 1; @wr.write "HELLO" }
267     assert_nothing_raised do
268       foo = @rd.kgio_read(5)
269       elapsed = Time.now - t0
270     end
271     assert elapsed >= 1.0, "elapsed: #{elapsed}"
272     assert_equal "HELLO", foo
273     thr.join
274     assert_equal 5, thr.value
275   end
277   def test_wait_writable_ruby_default
278     buf = "." * 512
279     nr = 0
280     begin
281       nr += @wr.write_nonblock(buf)
282     rescue Errno::EAGAIN
283       break
284     end while true
285     elapsed = 0
286     foo = nil
287     t0 = Time.now
288     thr = Thread.new { sleep 1; @rd.readpartial(nr) }
289     assert_nothing_raised do
290       foo = @wr.kgio_write("HELLO")
291       elapsed = Time.now - t0
292     end
293     assert_nil foo
294     if @wr.stat.pipe?
295       assert elapsed >= 1.0, "elapsed: #{elapsed}"
296     end
297     assert(String === foo || foo == nil)
298     assert_kind_of String, thr.value
299   end
301   def test_wait_readable_method
302     def @rd.kgio_wait_readable
303       defined?(@z) ? raise(RuntimeError, "Hello") : @z = "HI"
304     end
305     foo = nil
306     begin
307       foo = @rd.kgio_read(5)
308       assert false
309     rescue RuntimeError => e
310       assert_equal("Hello", e.message)
311     end
312     assert_equal "HI", @rd.instance_variable_get(:@z)
313     assert_nil foo
314   end
316   def test_tryread_wait_readable_method
317     def @rd.kgio_wait_readable
318       raise "Hello"
319     end
320     assert_equal :wait_readable, @rd.kgio_tryread(5)
321   end
323   def test_trywrite_wait_readable_method
324     def @wr.kgio_wait_writable
325       raise "Hello"
326     end
327     tmp = []
328     buf = "." * 1024
329     10000.times { tmp << @wr.kgio_trywrite(buf) }
330     assert_equal :wait_writable, tmp.pop
331   end
333   def test_wait_writable_method
334     def @wr.kgio_wait_writable
335       defined?(@z) ? raise(RuntimeError, "Hello") : @z = "HI"
336     end
337     n = []
338     begin
339       loop { n << @wr.kgio_write("HIHIHIHIHIHI") }
340       assert false
341     rescue RuntimeError => e
342       assert_equal("Hello", e.message)
343     end
344     assert n.size > 0
345     assert_equal "HI", @wr.instance_variable_get(:@z)
346   end