mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
b1166a0469
rb_io_check_writable. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16128 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
548 lines
13 KiB
Ruby
548 lines
13 KiB
Ruby
require 'test/unit'
|
|
require 'tmpdir'
|
|
require 'io/nonblock'
|
|
require 'socket'
|
|
require 'stringio'
|
|
|
|
class TestIO < Test::Unit::TestCase
|
|
def test_gets_rs
|
|
# default_rs
|
|
r, w = IO.pipe
|
|
w.print "aaa\nbbb\n"
|
|
w.close
|
|
assert_equal "aaa\n", r.gets
|
|
assert_equal "bbb\n", r.gets
|
|
assert_nil r.gets
|
|
r.close
|
|
|
|
# nil
|
|
r, w = IO.pipe
|
|
w.print "a\n\nb\n\n"
|
|
w.close
|
|
assert_equal "a\n\nb\n\n", r.gets(nil)
|
|
assert_nil r.gets("")
|
|
r.close
|
|
|
|
# "\377"
|
|
r, w = IO.pipe('ascii-8bit')
|
|
w.print "\377xyz"
|
|
w.close
|
|
r.binmode
|
|
assert_equal("\377", r.gets("\377"), "[ruby-dev:24460]")
|
|
r.close
|
|
|
|
# ""
|
|
r, w = IO.pipe
|
|
w.print "a\n\nb\n\n"
|
|
w.close
|
|
assert_equal "a\n\n", r.gets(""), "[ruby-core:03771]"
|
|
assert_equal "b\n\n", r.gets("")
|
|
assert_nil r.gets("")
|
|
r.close
|
|
end
|
|
|
|
# This test cause SEGV.
|
|
def test_ungetc
|
|
r, w = IO.pipe
|
|
w.close
|
|
assert_raise(IOError, "[ruby-dev:31650]") { 20000.times { r.ungetc "a" } }
|
|
ensure
|
|
r.close
|
|
end
|
|
|
|
def test_each_byte
|
|
r, w = IO.pipe
|
|
w << "abc def"
|
|
w.close
|
|
r.each_byte {|byte| break if byte == 32 }
|
|
assert_equal("def", r.read, "[ruby-dev:31659]")
|
|
ensure
|
|
r.close
|
|
end
|
|
|
|
def test_rubydev33072
|
|
assert_raise(Errno::ENOENT, "[ruby-dev:33072]") do
|
|
File.read("empty", nil, nil, {})
|
|
end
|
|
end
|
|
|
|
def with_pipe
|
|
r, w = IO.pipe
|
|
begin
|
|
yield r, w
|
|
ensure
|
|
r.close unless r.closed?
|
|
w.close unless w.closed?
|
|
end
|
|
end
|
|
|
|
def with_read_pipe(content)
|
|
r, w = IO.pipe
|
|
w << content
|
|
w.close
|
|
begin
|
|
yield r
|
|
ensure
|
|
r.close
|
|
end
|
|
end
|
|
|
|
def mkcdtmpdir
|
|
Dir.mktmpdir {|d|
|
|
Dir.chdir(d) {
|
|
yield
|
|
}
|
|
}
|
|
end
|
|
|
|
def test_copy_stream
|
|
mkcdtmpdir {|d|
|
|
|
|
content = "foobar"
|
|
File.open("src", "w") {|f| f << content }
|
|
ret = IO.copy_stream("src", "dst")
|
|
assert_equal(content.bytesize, ret)
|
|
assert_equal(content, File.read("dst"))
|
|
|
|
# overwrite by smaller file.
|
|
content = "baz"
|
|
File.open("src", "w") {|f| f << content }
|
|
ret = IO.copy_stream("src", "dst")
|
|
assert_equal(content.bytesize, ret)
|
|
assert_equal(content, File.read("dst"))
|
|
|
|
ret = IO.copy_stream("src", "dst", 2)
|
|
assert_equal(2, ret)
|
|
assert_equal(content[0,2], File.read("dst"))
|
|
|
|
ret = IO.copy_stream("src", "dst", 0)
|
|
assert_equal(0, ret)
|
|
assert_equal("", File.read("dst"))
|
|
|
|
ret = IO.copy_stream("src", "dst", nil, 1)
|
|
assert_equal(content.bytesize-1, ret)
|
|
assert_equal(content[1..-1], File.read("dst"))
|
|
|
|
assert_raise(Errno::ENOENT) {
|
|
IO.copy_stream("nodir/foo", "dst")
|
|
}
|
|
|
|
assert_raise(Errno::ENOENT) {
|
|
IO.copy_stream("src", "nodir/bar")
|
|
}
|
|
|
|
with_pipe {|r, w|
|
|
ret = IO.copy_stream("src", w)
|
|
assert_equal(content.bytesize, ret)
|
|
w.close
|
|
assert_equal(content, r.read)
|
|
}
|
|
|
|
with_pipe {|r, w|
|
|
w.close
|
|
assert_raise(IOError) { IO.copy_stream("src", w) }
|
|
}
|
|
|
|
pipe_content = "abc"
|
|
with_read_pipe(pipe_content) {|r|
|
|
ret = IO.copy_stream(r, "dst")
|
|
assert_equal(pipe_content.bytesize, ret)
|
|
assert_equal(pipe_content, File.read("dst"))
|
|
}
|
|
|
|
with_read_pipe("abc") {|r1|
|
|
assert_equal("a", r1.getc)
|
|
with_pipe {|r2, w2|
|
|
w2.sync = false
|
|
w2 << "def"
|
|
ret = IO.copy_stream(r1, w2)
|
|
assert_equal(2, ret)
|
|
w2.close
|
|
assert_equal("defbc", r2.read)
|
|
}
|
|
}
|
|
|
|
with_read_pipe("abc") {|r1|
|
|
assert_equal("a", r1.getc)
|
|
with_pipe {|r2, w2|
|
|
w2.sync = false
|
|
w2 << "def"
|
|
ret = IO.copy_stream(r1, w2, 1)
|
|
assert_equal(1, ret)
|
|
w2.close
|
|
assert_equal("defb", r2.read)
|
|
}
|
|
}
|
|
|
|
with_read_pipe("abc") {|r1|
|
|
assert_equal("a", r1.getc)
|
|
with_pipe {|r2, w2|
|
|
ret = IO.copy_stream(r1, w2)
|
|
assert_equal(2, ret)
|
|
w2.close
|
|
assert_equal("bc", r2.read)
|
|
}
|
|
}
|
|
|
|
with_read_pipe("abc") {|r1|
|
|
assert_equal("a", r1.getc)
|
|
with_pipe {|r2, w2|
|
|
ret = IO.copy_stream(r1, w2, 1)
|
|
assert_equal(1, ret)
|
|
w2.close
|
|
assert_equal("b", r2.read)
|
|
}
|
|
}
|
|
|
|
with_read_pipe("abc") {|r1|
|
|
assert_equal("a", r1.getc)
|
|
with_pipe {|r2, w2|
|
|
ret = IO.copy_stream(r1, w2, 0)
|
|
assert_equal(0, ret)
|
|
w2.close
|
|
assert_equal("", r2.read)
|
|
}
|
|
}
|
|
|
|
with_pipe {|r1, w1|
|
|
w1 << "abc"
|
|
assert_equal("a", r1.getc)
|
|
with_pipe {|r2, w2|
|
|
w1 << "def"
|
|
w1.close
|
|
ret = IO.copy_stream(r1, w2)
|
|
assert_equal(5, ret)
|
|
w2.close
|
|
assert_equal("bcdef", r2.read)
|
|
}
|
|
}
|
|
|
|
with_pipe {|r, w|
|
|
ret = IO.copy_stream("src", w, 1, 1)
|
|
assert_equal(1, ret)
|
|
w.close
|
|
assert_equal(content[1,1], r.read)
|
|
}
|
|
|
|
with_read_pipe("abc") {|r1|
|
|
assert_equal("a", r1.getc)
|
|
with_pipe {|r2, w2|
|
|
w2.nonblock = true
|
|
s = w2.syswrite("a" * 100000)
|
|
t = Thread.new { sleep 0.1; r2.read }
|
|
ret = IO.copy_stream(r1, w2)
|
|
w2.close
|
|
assert_equal(2, ret)
|
|
assert_equal("a" * s + "bc", t.value)
|
|
}
|
|
}
|
|
|
|
bigcontent = "abc" * 123456
|
|
File.open("bigsrc", "w") {|f| f << bigcontent }
|
|
ret = IO.copy_stream("bigsrc", "bigdst")
|
|
assert_equal(bigcontent.bytesize, ret)
|
|
assert_equal(bigcontent, File.read("bigdst"))
|
|
|
|
File.unlink("bigdst")
|
|
ret = IO.copy_stream("bigsrc", "bigdst", nil, 100)
|
|
assert_equal(bigcontent.bytesize-100, ret)
|
|
assert_equal(bigcontent[100..-1], File.read("bigdst"))
|
|
|
|
File.unlink("bigdst")
|
|
ret = IO.copy_stream("bigsrc", "bigdst", 30000, 100)
|
|
assert_equal(30000, ret)
|
|
assert_equal(bigcontent[100, 30000], File.read("bigdst"))
|
|
|
|
File.open("bigsrc") {|f|
|
|
assert_equal(0, f.pos)
|
|
ret = IO.copy_stream(f, "bigdst", nil, 10)
|
|
assert_equal(bigcontent.bytesize-10, ret)
|
|
assert_equal(bigcontent[10..-1], File.read("bigdst"))
|
|
assert_equal(0, f.pos)
|
|
ret = IO.copy_stream(f, "bigdst", 40, 30)
|
|
assert_equal(40, ret)
|
|
assert_equal(bigcontent[30, 40], File.read("bigdst"))
|
|
assert_equal(0, f.pos)
|
|
}
|
|
|
|
with_pipe {|r, w|
|
|
w.close
|
|
assert_raise(IOError) { IO.copy_stream("src", w) }
|
|
}
|
|
|
|
megacontent = "abc" * 1234567
|
|
File.open("megasrc", "w") {|f| f << megacontent }
|
|
|
|
with_pipe {|r1, w1|
|
|
with_pipe {|r2, w2|
|
|
t1 = Thread.new { w1 << megacontent; w1.close }
|
|
t2 = Thread.new { r2.read }
|
|
r1.nonblock = true
|
|
w2.nonblock = true
|
|
ret = IO.copy_stream(r1, w2)
|
|
assert_equal(megacontent.bytesize, ret)
|
|
w2.close
|
|
t1.join
|
|
assert_equal(megacontent, t2.value)
|
|
}
|
|
}
|
|
|
|
with_pipe {|r1, w1|
|
|
with_pipe {|r2, w2|
|
|
t1 = Thread.new { w1 << megacontent; w1.close }
|
|
t2 = Thread.new { r2.read }
|
|
ret = IO.copy_stream(r1, w2)
|
|
assert_equal(megacontent.bytesize, ret)
|
|
w2.close
|
|
t1.join
|
|
assert_equal(megacontent, t2.value)
|
|
}
|
|
}
|
|
|
|
with_pipe {|r, w|
|
|
t = Thread.new { r.read }
|
|
ret = IO.copy_stream("megasrc", w)
|
|
assert_equal(megacontent.bytesize, ret)
|
|
w.close
|
|
assert_equal(megacontent, t.value)
|
|
}
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_rbuf
|
|
mkcdtmpdir {|d|
|
|
with_pipe {|r, w|
|
|
File.open("foo", "w") {|f| f << "abcd" }
|
|
File.open("foo") {|f|
|
|
f.read(1)
|
|
assert_equal(3, IO.copy_stream(f, w, 10, 1))
|
|
}
|
|
w.close
|
|
assert_equal("bcd", r.read)
|
|
}
|
|
}
|
|
end
|
|
|
|
def with_socketpair
|
|
s1, s2 = UNIXSocket.pair
|
|
begin
|
|
yield s1, s2
|
|
ensure
|
|
s1.close unless s1.closed?
|
|
s2.close unless s2.closed?
|
|
end
|
|
end
|
|
|
|
def test_copy_stream_socket
|
|
return unless defined? UNIXSocket
|
|
mkcdtmpdir {|d|
|
|
|
|
content = "foobar"
|
|
File.open("src", "w") {|f| f << content }
|
|
|
|
with_socketpair {|s1, s2|
|
|
ret = IO.copy_stream("src", s1)
|
|
assert_equal(content.bytesize, ret)
|
|
s1.close
|
|
assert_equal(content, s2.read)
|
|
}
|
|
|
|
bigcontent = "abc" * 123456
|
|
File.open("bigsrc", "w") {|f| f << bigcontent }
|
|
|
|
with_socketpair {|s1, s2|
|
|
t = Thread.new { s2.read }
|
|
ret = IO.copy_stream("bigsrc", s1)
|
|
assert_equal(bigcontent.bytesize, ret)
|
|
s1.close
|
|
result = t.value
|
|
assert_equal(bigcontent, result)
|
|
}
|
|
|
|
with_socketpair {|s1, s2|
|
|
t = Thread.new { s2.read }
|
|
ret = IO.copy_stream("bigsrc", s1, 10000)
|
|
assert_equal(10000, ret)
|
|
s1.close
|
|
result = t.value
|
|
assert_equal(bigcontent[0,10000], result)
|
|
}
|
|
|
|
File.open("bigsrc") {|f|
|
|
assert_equal(0, f.pos)
|
|
with_socketpair {|s1, s2|
|
|
t = Thread.new { s2.read }
|
|
ret = IO.copy_stream(f, s1, nil, 100)
|
|
assert_equal(bigcontent.bytesize-100, ret)
|
|
assert_equal(0, f.pos)
|
|
s1.close
|
|
result = t.value
|
|
assert_equal(bigcontent[100..-1], result)
|
|
}
|
|
}
|
|
|
|
File.open("bigsrc") {|f|
|
|
assert_equal(bigcontent[0,100], f.read(100))
|
|
assert_equal(100, f.pos)
|
|
with_socketpair {|s1, s2|
|
|
t = Thread.new { s2.read }
|
|
ret = IO.copy_stream(f, s1)
|
|
assert_equal(bigcontent.bytesize-100, ret)
|
|
assert_equal(bigcontent.length, f.pos)
|
|
s1.close
|
|
result = t.value
|
|
assert_equal(bigcontent[100..-1], result)
|
|
}
|
|
}
|
|
|
|
megacontent = "abc" * 1234567
|
|
File.open("megasrc", "w") {|f| f << megacontent }
|
|
|
|
with_socketpair {|s1, s2|
|
|
t = Thread.new { s2.read }
|
|
s1.nonblock = true
|
|
ret = IO.copy_stream("megasrc", s1)
|
|
assert_equal(megacontent.bytesize, ret)
|
|
s1.close
|
|
result = t.value
|
|
assert_equal(megacontent, result)
|
|
}
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_strio
|
|
src = StringIO.new("abcd")
|
|
dst = StringIO.new
|
|
ret = IO.copy_stream(src, dst)
|
|
assert_equal(4, ret)
|
|
assert_equal("abcd", dst.string)
|
|
assert_equal(4, src.pos)
|
|
end
|
|
|
|
def test_copy_stream_strio_len
|
|
src = StringIO.new("abcd")
|
|
dst = StringIO.new
|
|
ret = IO.copy_stream(src, dst, 3)
|
|
assert_equal(3, ret)
|
|
assert_equal("abc", dst.string)
|
|
assert_equal(3, src.pos)
|
|
end
|
|
|
|
def test_copy_stream_strio_off
|
|
src = StringIO.new("abcd")
|
|
with_pipe {|r, w|
|
|
assert_raise(ArgumentError) {
|
|
IO.copy_stream(src, w, 3, 1)
|
|
}
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_fname_to_strio
|
|
mkcdtmpdir {|d|
|
|
File.open("foo", "w") {|f| f << "abcd" }
|
|
src = "foo"
|
|
dst = StringIO.new
|
|
ret = IO.copy_stream(src, dst, 3)
|
|
assert_equal(3, ret)
|
|
assert_equal("abc", dst.string)
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_strio_to_fname
|
|
mkcdtmpdir {|d|
|
|
# StringIO to filename
|
|
src = StringIO.new("abcd")
|
|
ret = IO.copy_stream(src, "fooo", 3)
|
|
assert_equal(3, ret)
|
|
assert_equal("abc", File.read("fooo"))
|
|
assert_equal(3, src.pos)
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_io_to_strio
|
|
mkcdtmpdir {|d|
|
|
# IO to StringIO
|
|
File.open("bar", "w") {|f| f << "abcd" }
|
|
File.open("bar") {|src|
|
|
dst = StringIO.new
|
|
ret = IO.copy_stream(src, dst, 3)
|
|
assert_equal(3, ret)
|
|
assert_equal("abc", dst.string)
|
|
assert_equal(3, src.pos)
|
|
}
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_strio_to_io
|
|
mkcdtmpdir {|d|
|
|
# StringIO to IO
|
|
src = StringIO.new("abcd")
|
|
ret = File.open("baz", "w") {|dst|
|
|
IO.copy_stream(src, dst, 3)
|
|
}
|
|
assert_equal(3, ret)
|
|
assert_equal("abc", File.read("baz"))
|
|
assert_equal(3, src.pos)
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_strio_flush
|
|
with_pipe {|r, w|
|
|
w.sync = false
|
|
w.write "zz"
|
|
src = StringIO.new("abcd")
|
|
IO.copy_stream(src, w)
|
|
t = Thread.new {
|
|
w.close
|
|
}
|
|
assert_equal("zzabcd", r.read)
|
|
t.join
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_strio_rbuf
|
|
with_pipe {|r, w|
|
|
w << "abcd"
|
|
w.close
|
|
assert_equal("a", r.read(1))
|
|
sio = StringIO.new
|
|
IO.copy_stream(r, sio)
|
|
assert_equal("bcd", sio.string)
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_src_wbuf
|
|
mkcdtmpdir {|d|
|
|
with_pipe {|r, w|
|
|
File.open("foe", "w+") {|f|
|
|
f.write "abcd\n"
|
|
f.rewind
|
|
f.write "xy"
|
|
IO.copy_stream(f, w)
|
|
}
|
|
assert_equal("xycd\n", File.read("foe"))
|
|
w.close
|
|
assert_equal("cd\n", r.read)
|
|
r.close
|
|
}
|
|
}
|
|
end
|
|
|
|
def test_copy_stream_dst_rbuf
|
|
mkcdtmpdir {|d|
|
|
with_pipe {|r, w|
|
|
w << "xyz"
|
|
w.close
|
|
File.open("fom", "w+") {|f|
|
|
f.write "abcd\n"
|
|
f.rewind
|
|
assert_equal("abc", f.read(3))
|
|
f.ungetc "c"
|
|
IO.copy_stream(r, f)
|
|
}
|
|
assert_equal("abxyz", File.read("fom"))
|
|
}
|
|
}
|
|
end
|
|
|
|
end
|