diff options
author | tenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-08-26 22:41:44 +0000 |
---|---|---|
committer | tenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-08-26 22:41:44 +0000 |
commit | 988ca60565a5ba6661f7215026f008afebcf7aee (patch) | |
tree | bc196f4e6ce27e3ea505c18269a08f3910b99ba5 /test | |
parent | eadad2c9000f8cc1d5ef58d7d58569793f3db901 (diff) | |
download | ruby-988ca60565a5ba6661f7215026f008afebcf7aee.tar.gz |
* io.c (io_read_nonblock): support non-blocking reads without raising
exceptions. As in: `io.read_nonblock(size, exception: false)`
[ruby-core:38666] [Feature #5138]
* ext/openssl/ossl_ssl.c (ossl_ssl_read_internal): ditto
* ext/stringio/stringio.c (strio_sysread): ditto
* io.c (rb_io_write_nonblock): support non-blocking writes without
raising an exception.
* ext/openssl/ossl_ssl.c (ossl_ssl_write_internal): ditto
* test/openssl/test_pair.rb (class OpenSSL): tests
* test/ruby/test_io.rb (class TestIO): ditto
* test/socket/test_nonblock.rb (class TestSocketNonblock): ditto
* test/stringio/test_stringio.rb (class TestStringIO): ditto
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42695 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'test')
-rw-r--r-- | test/openssl/test_pair.rb | 63 | ||||
-rw-r--r-- | test/ruby/test_io.rb | 59 | ||||
-rw-r--r-- | test/socket/test_nonblock.rb | 14 | ||||
-rw-r--r-- | test/stringio/test_stringio.rb | 24 |
4 files changed, 152 insertions, 8 deletions
diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb index fa36725b58..e6b495f669 100644 --- a/test/openssl/test_pair.rb +++ b/test/openssl/test_pair.rb @@ -156,19 +156,46 @@ class OpenSSL::TestPair < Test::Unit::TestCase ret = nil assert_nothing_raised("[ruby-core:20298]") { ret = s2.read_nonblock(10) } assert_equal("def\n", ret) + s1.close + assert_raise(EOFError) { s2.read_nonblock(10) } } end + def test_read_nonblock_no_exception + ssl_pair {|s1, s2| + assert_equal :wait_readable, s2.read_nonblock(10, exception: false) + s1.write "abc\ndef\n" + IO.select([s2]) + assert_equal("ab", s2.read_nonblock(2, exception: false)) + assert_equal("c\n", s2.gets) + ret = nil + assert_nothing_raised("[ruby-core:20298]") { ret = s2.read_nonblock(10, exception: false) } + assert_equal("def\n", ret) + s1.close + assert_equal(nil, s2.read_nonblock(10, exception: false)) + } + end + + def write_nonblock(socket, meth, str) + ret = socket.send(meth, str) + ret.is_a?(Symbol) ? 0 : ret + end + + def write_nonblock_no_ex(socket, str) + ret = socket.write_nonblock str, exception: false + ret.is_a?(Symbol) ? 0 : ret + end + def test_write_nonblock ssl_pair {|s1, s2| n = 0 begin - n += s1.write_nonblock("a" * 100000) - n += s1.write_nonblock("b" * 100000) - n += s1.write_nonblock("c" * 100000) - n += s1.write_nonblock("d" * 100000) - n += s1.write_nonblock("e" * 100000) - n += s1.write_nonblock("f" * 100000) + n += write_nonblock s1, :write_nonblock, "a" * 100000 + n += write_nonblock s1, :write_nonblock, "b" * 100000 + n += write_nonblock s1, :write_nonblock, "c" * 100000 + n += write_nonblock s1, :write_nonblock, "d" * 100000 + n += write_nonblock s1, :write_nonblock, "e" * 100000 + n += write_nonblock s1, :write_nonblock, "f" * 100000 rescue IO::WaitWritable end s1.close @@ -176,6 +203,20 @@ class OpenSSL::TestPair < Test::Unit::TestCase } end + def test_write_nonblock_no_exceptions + ssl_pair {|s1, s2| + n = 0 + n += write_nonblock_no_ex s1, "a" * 100000 + n += write_nonblock_no_ex s1, "b" * 100000 + n += write_nonblock_no_ex s1, "c" * 100000 + n += write_nonblock_no_ex s1, "d" * 100000 + n += write_nonblock_no_ex s1, "e" * 100000 + n += write_nonblock_no_ex s1, "f" * 100000 + s1.close + assert_equal(n, s2.read.length) + } + end + def test_write_nonblock_with_buffered_data ssl_pair {|s1, s2| s1.write "foo" @@ -186,6 +227,16 @@ class OpenSSL::TestPair < Test::Unit::TestCase } end + def test_write_nonblock_with_buffered_data_no_exceptions + ssl_pair {|s1, s2| + s1.write "foo" + s1.write_nonblock("bar", exception: false) + s1.write "baz" + s1.close + assert_equal("foobarbaz", s2.read) + } + end + def test_connect_accept_nonblock host = "127.0.0.1" port = 0 diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index 5cda6c9e5a..4f002e8b3d 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -1205,6 +1205,16 @@ class TestIO < Test::Unit::TestCase } end + def test_write_nonblock_simple_no_exceptions + skip "IO#write_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM + pipe(proc do |w| + w.write_nonblock('1', exception: false) + w.close + end, proc do |r| + assert_equal("1", r.read) + end) + end + def test_read_nonblock_error return if !have_nonblock? skip "IO#read_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM @@ -1215,6 +1225,41 @@ class TestIO < Test::Unit::TestCase assert_kind_of(IO::WaitReadable, $!) end } + + with_pipe {|r, w| + begin + r.read_nonblock 4096, "" + rescue Errno::EWOULDBLOCK + assert_kind_of(IO::WaitReadable, $!) + end + } + end + + def test_read_nonblock_no_exceptions + return if !have_nonblock? + skip "IO#read_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM + with_pipe {|r, w| + assert_equal :wait_readable, r.read_nonblock(4096, exception: false) + w.puts "HI!" + assert_equal "HI!\n", r.read_nonblock(4096, exception: false) + w.close + assert_equal nil, r.read_nonblock(4096, exception: false) + } + end + + def test_read_nonblock_with_buffer_no_exceptions + return if !have_nonblock? + skip "IO#read_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM + with_pipe {|r, w| + assert_equal :wait_readable, r.read_nonblock(4096, "", exception: false) + w.puts "HI!" + buf = "buf" + value = r.read_nonblock(4096, buf, exception: false) + assert_equal value, "HI!\n" + assert buf.equal?(value) + w.close + assert_equal nil, r.read_nonblock(4096, "", exception: false) + } end def test_write_nonblock_error @@ -1231,6 +1276,20 @@ class TestIO < Test::Unit::TestCase } end + def test_write_nonblock_no_exceptions + return if !have_nonblock? + skip "IO#write_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM + with_pipe {|r, w| + loop { + ret = w.write_nonblock("a"*100000, exception: false) + if ret.is_a?(Symbol) + assert_equal :wait_writable, ret + break + end + } + } + end + def test_gets pipe(proc do |w| w.write "foobarbaz" diff --git a/test/socket/test_nonblock.rb b/test/socket/test_nonblock.rb index d494f91c41..e395a0ad31 100644 --- a/test/socket/test_nonblock.rb +++ b/test/socket/test_nonblock.rb @@ -190,6 +190,20 @@ class TestSocketNonblock < Test::Unit::TestCase s.close if s end + def test_read_nonblock_no_exception + c, s = tcp_pair + assert_equal :wait_readable, c.read_nonblock(100, exception: false) + assert_equal :wait_readable, s.read_nonblock(100, exception: false) + c.write("abc") + IO.select [s] + assert_equal("a", s.read_nonblock(1, exception: false)) + assert_equal("bc", s.read_nonblock(100, exception: false)) + assert_equal :wait_readable, s.read_nonblock(100, exception: false) + ensure + c.close if c + s.close if s + end + =begin def test_write_nonblock c, s = tcp_pair diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb index 0eceeba894..f29322b393 100644 --- a/test/stringio/test_stringio.rb +++ b/test/stringio/test_stringio.rb @@ -89,6 +89,14 @@ class TestStringIO < Test::Unit::TestCase f.close unless f.closed? end + def test_write_nonblock_no_exceptions + s = "" + f = StringIO.new(s, "w") + f.write_nonblock("foo", exception: false) + f.close + assert_equal("foo", s) + end + def test_write_nonblock s = "" f = StringIO.new(s, "w") @@ -437,7 +445,7 @@ class TestStringIO < Test::Unit::TestCase f = StringIO.new("\u3042\u3044") assert_raise(ArgumentError) { f.readpartial(-1) } assert_raise(ArgumentError) { f.readpartial(1, 2, 3) } - assert_equal("\u3042\u3044", f.readpartial) + assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(100)) f.rewind assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(f.size)) f.rewind @@ -450,7 +458,19 @@ class TestStringIO < Test::Unit::TestCase f = StringIO.new("\u3042\u3044") assert_raise(ArgumentError) { f.read_nonblock(-1) } assert_raise(ArgumentError) { f.read_nonblock(1, 2, 3) } - assert_equal("\u3042\u3044", f.read_nonblock) + assert_equal("\u3042\u3044".force_encoding("BINARY"), f.read_nonblock(100)) + assert_raise(EOFError) { f.read_nonblock(10) } + f.rewind + assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size)) + end + + def test_read_nonblock_no_exceptions + f = StringIO.new("\u3042\u3044") + assert_raise(ArgumentError) { f.read_nonblock(-1, exception: false) } + assert_raise(ArgumentError) { f.read_nonblock(1, 2, 3, exception: false) } + assert_raise(ArgumentError) { f.read_nonblock } + assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(100, exception: false)) + assert_equal(nil, f.read_nonblock(10, exception: false)) f.rewind assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size)) f.rewind |