Index: test/ruby/test_io_m17n.rb =================================================================== --- test/ruby/test_io_m17n.rb (revision 29519) +++ test/ruby/test_io_m17n.rb (working copy) @@ -19,6 +19,18 @@ } end + def pipe(*args, wp, rp) + r, w = IO.pipe(*args) + rt = Thread.new { rp.call(r) } + wt = Thread.new { wp.call(w) } + flunk("timeout") unless rt.join(10) && wt.join(10) + ensure + r.close unless !r || r.closed? + w.close unless !w || r.closed? + (rt.kill; rt.join) if rt + (wt.kill; wt.join) if wt + end + def with_pipe(*args) r, w = IO.pipe(*args) begin @@ -220,54 +232,68 @@ end def test_s_pipe_invalid - with_pipe("utf-8", "euc-jp", :invalid=>:replace) {|r, w| - w << "\x80" - w.close - assert_equal("?", r.read) - } + pipe("utf-8", "euc-jp", { :invalid=>:replace }, + proc do |w| + w << "\x80" + w.close + end, + proc do |r| + assert_equal("?", r.read) + end) end def test_s_pipe_undef - with_pipe("utf-8:euc-jp", :undef=>:replace) {|r, w| - w << "\ufffd" - w.close - assert_equal("?", r.read) - } + pipe("utf-8:euc-jp", { :undef=>:replace }, + proc do |w| + w << "\ufffd" + w.close + end, + proc do |r| + assert_equal("?", r.read) + end) end def test_s_pipe_undef_replace_string - with_pipe("utf-8:euc-jp", :undef=>:replace, :replace=>"X") {|r, w| - w << "\ufffd" - w.close - assert_equal("X", r.read) - } + pipe("utf-8:euc-jp", { :undef=>:replace, :replace=>"X" }, + proc do |w| + w << "\ufffd" + w.close + end, + proc do |r| + assert_equal("X", r.read) + end) end def test_dup - with_pipe("utf-8:euc-jp") {|r, w| - w << "\u3042" - w.close - r2 = r.dup - begin - assert_equal("\xA4\xA2".force_encoding("euc-jp"), r2.read) - ensure - r2.close - end - - } + pipe("utf-8:euc-jp", + proc do |w| + w << "\u3042" + w.close + end, + proc do |r| + r2 = r.dup + begin + assert_equal("\xA4\xA2".force_encoding("euc-jp"), r2.read) + ensure + r2.close + end + end) end def test_dup_undef - with_pipe("utf-8:euc-jp", :undef=>:replace) {|r, w| - w << "\uFFFD" - w.close - r2 = r.dup - begin - assert_equal("?", r2.read) - ensure - r2.close - end - } + pipe("utf-8:euc-jp", { :undef=>:replace }, + proc do |w| + w << "\uFFFD" + w.close + end, + proc do |r| + r2 = r.dup + begin + assert_equal("?", r2.read) + ensure + r2.close + end + end) end def test_stdin @@ -331,47 +357,53 @@ end def test_pipe_terminator_conversion - with_pipe("euc-jp:utf-8") {|r, w| - w.write "before \xa2\xa2 after" - rs = "\xA2\xA2".encode("utf-8", "euc-jp") - w.close - timeout(1) { - assert_equal("before \xa2\xa2".encode("utf-8", "euc-jp"), - r.gets(rs)) - } - } + rs = "\xA2\xA2".encode("utf-8", "euc-jp") + pipe("euc-jp:utf-8", + proc do |w| + w.write "before \xa2\xa2 after" + w.close + end, + proc do |r| + timeout(1) { + assert_equal("before \xa2\xa2".encode("utf-8", "euc-jp"), + r.gets(rs)) + } + end) end def test_pipe_conversion - with_pipe("euc-jp:utf-8") {|r, w| - w.write "\xa1\xa1" - assert_equal("\xa1\xa1".encode("utf-8", "euc-jp"), r.getc) - } + pipe("euc-jp:utf-8", + proc do |w| + w.write "\xa1\xa1" + end, + proc do |r| + assert_equal("\xa1\xa1".encode("utf-8", "euc-jp"), r.getc) + end) end def test_pipe_convert_partial_read - with_pipe("euc-jp:utf-8") {|r, w| - begin - t = Thread.new { - w.write "\xa1" - sleep 0.1 - w.write "\xa1" - } - assert_equal("\xa1\xa1".encode("utf-8", "euc-jp"), r.getc) - ensure - t.join if t - end - } + pipe("euc-jp:utf-8", + proc do |w| + w.write "\xa1" + sleep 0.1 + w.write "\xa1" + end, + proc do |r| + assert_equal("\xa1\xa1".encode("utf-8", "euc-jp"), r.getc) + end) end def test_getc_invalid - with_pipe("euc-jp:utf-8") {|r, w| - w << "\xa1xyz" - w.close - err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc } - assert_equal("\xA1".force_encoding("ascii-8bit"), err.error_bytes) - assert_equal("xyz", r.read(10)) - } + pipe("euc-jp:utf-8", + proc do |w| + w << "\xa1xyz" + w.close + end, + proc do |r| + err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc } + assert_equal("\xA1".force_encoding("ascii-8bit"), err.error_bytes) + assert_equal("xyz", r.read(10)) + end) end def test_getc_stateful_conversion @@ -597,37 +629,47 @@ utf8 = "\u6666" eucjp = "\xb3\xa2".force_encoding("EUC-JP") - with_pipe {|r,w| + pipe(proc do |w| + w << utf8 + w.close + end, proc do |r| assert_equal(Encoding.default_external, r.external_encoding) assert_equal(nil, r.internal_encoding) - w << utf8 - w.close s = r.read assert_equal(Encoding.default_external, s.encoding) assert_str_equal(utf8.dup.force_encoding(Encoding.default_external), s) - } + end) - with_pipe("EUC-JP") {|r,w| - assert_equal(Encoding::EUC_JP, r.external_encoding) - assert_equal(nil, r.internal_encoding) - w << eucjp - w.close - assert_equal(eucjp, r.read) - } + pipe("EUC-JP", + proc do |w| + w << eucjp + w.close + end, + proc do |r| + assert_equal(Encoding::EUC_JP, r.external_encoding) + assert_equal(nil, r.internal_encoding) + assert_equal(eucjp, r.read) + end) - with_pipe("UTF-8") {|r,w| - w << "a" * 1023 + "\u3042" + "a" * 1022 - w.close - assert_equal(true, r.read.valid_encoding?) - } + pipe("UTF-8", + proc do |w| + w << "a" * 1023 + "\u3042" + "a" * 1022 + w.close + end, + proc do |r| + assert_equal(true, r.read.valid_encoding?) + end) - with_pipe("UTF-8:EUC-JP") {|r,w| - assert_equal(Encoding::UTF_8, r.external_encoding) - assert_equal(Encoding::EUC_JP, r.internal_encoding) - w << utf8 - w.close - assert_equal(eucjp, r.read) - } + pipe("UTF-8:EUC-JP", + proc do |w| + w << utf8 + w.close + end, + proc do |r| + assert_equal(Encoding::UTF_8, r.external_encoding) + assert_equal(Encoding::EUC_JP, r.internal_encoding) + assert_equal(eucjp, r.read) + end) e = assert_raise(ArgumentError) {with_pipe("UTF-8", "UTF-8".encode("UTF-32BE")) {}} assert_match(/invalid name encoding/, e.message) @@ -635,147 +677,174 @@ assert_match(/invalid name encoding/, e.message) ENCS.each {|enc| - with_pipe(enc) {|r, w| - w << "\xc2\xa1" - w.close - s = r.getc - assert_equal(enc, s.encoding) - } + pipe(enc, + proc do |w| + w << "\xc2\xa1" + w.close + end, + proc do |r| + s = r.getc + assert_equal(enc, s.encoding) + end) } ENCS.each {|enc| next if enc == Encoding::ASCII_8BIT next if enc == Encoding::UTF_8 - with_pipe("#{enc}:UTF-8") {|r, w| - w << "\xc2\xa1" - w.close - s = r.read - assert_equal(Encoding::UTF_8, s.encoding) - assert_equal(s.encode("UTF-8"), s) - } + pipe("#{enc}:UTF-8", + proc do |w| + w << "\xc2\xa1" + w.close + end, + proc do |r| + s = r.read + assert_equal(Encoding::UTF_8, s.encoding) + assert_equal(s.encode("UTF-8"), s) + end) } end def test_marshal - with_pipe("EUC-JP") {|r, w| - data = 56225 - Marshal.dump(data, w) - w.close - result = nil - assert_nothing_raised("[ruby-dev:33264]") { result = Marshal.load(r) } - assert_equal(data, result) - } + data = 56225 + pipe("EUC-JP", + proc do |w| + Marshal.dump(data, w) + w.close + end, + proc do |r| + result = nil + assert_nothing_raised("[ruby-dev:33264]") { result = Marshal.load(r) } + assert_equal(data, result) + end) end def test_gets_nil - with_pipe("UTF-8:EUC-JP") {|r, w| - w << "\u{3042}" - w.close - result = r.gets(nil) - assert_equal("\u{3042}".encode("euc-jp"), result) - } + pipe("UTF-8:EUC-JP", + proc do |w| + w << "\u{3042}" + w.close + end, + proc do |r| + result = r.gets(nil) + assert_equal("\u{3042}".encode("euc-jp"), result) + end) end def test_gets_limit - with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close - assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.gets(1)) - } - with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close - assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.gets(2)) - } - with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close - assert_equal("\xa4\xa2\xa4\xa4".force_encoding("euc-jp"), r.gets(3)) - } - with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close - assert_equal("\xa4\xa2\xa4\xa4".force_encoding("euc-jp"), r.gets(4)) - } - with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close - assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6".force_encoding("euc-jp"), r.gets(5)) - } - with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close - assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6".force_encoding("euc-jp"), r.gets(6)) - } - with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close - assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6\n".force_encoding("euc-jp"), r.gets(7)) - } - with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close - assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6\n".force_encoding("euc-jp"), r.gets(8)) - } - with_pipe("euc-jp") {|r, w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close - assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6\n".force_encoding("euc-jp"), r.gets(9)) - } + pipe("euc-jp", + proc {|w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close }, + proc {|r| assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.gets(1)) }) + pipe("euc-jp", + proc {|w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close }, + proc {|r| assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.gets(2)) }) + pipe("euc-jp", + proc {|w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close }, + proc {|r| assert_equal("\xa4\xa2\xa4\xa4".force_encoding("euc-jp"), r.gets(3)) }) + pipe("euc-jp", + proc {|w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close }, + proc {|r| assert_equal("\xa4\xa2\xa4\xa4".force_encoding("euc-jp"), r.gets(4)) }) + pipe("euc-jp", + proc {|w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close }, + proc {|r| assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6".force_encoding("euc-jp"), r.gets(5)) }) + pipe("euc-jp", + proc {|w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close }, + proc {|r| assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6".force_encoding("euc-jp"), r.gets(6)) }) + pipe("euc-jp", + proc {|w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close }, + proc {|r| assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6\n".force_encoding("euc-jp"), r.gets(7)) }) + pipe("euc-jp", + proc {|w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close }, + proc {|r| assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6\n".force_encoding("euc-jp"), r.gets(8)) }) + pipe("euc-jp", + proc {|w| w << "\xa4\xa2\xa4\xa4\xa4\xa6\n\xa4\xa8\xa4\xaa"; w.close }, + proc {|r| assert_equal("\xa4\xa2\xa4\xa4\xa4\xa6\n".force_encoding("euc-jp"), r.gets(9)) }) end def test_gets_invalid - with_pipe("utf-8:euc-jp") {|r, w| - before = "\u{3042}\u{3044}" - invalid = "\x80".force_encoding("utf-8") - after = "\u{3046}\u{3048}" - w << before + invalid + after - w.close - err = assert_raise(Encoding::InvalidByteSequenceError) { r.gets } - assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes) - assert_equal(after.encode("euc-jp"), r.gets) - } + before = "\u{3042}\u{3044}" + invalid = "\x80".force_encoding("utf-8") + after = "\u{3046}\u{3048}" + pipe("utf-8:euc-jp", + proc do |w| + w << before + invalid + after + w.close + end, + proc do |r| + err = assert_raise(Encoding::InvalidByteSequenceError) { r.gets } + assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes) + assert_equal(after.encode("euc-jp"), r.gets) + end) end def test_getc_invalid2 - with_pipe("utf-8:euc-jp") {|r, w| - before1 = "\u{3042}" - before2 = "\u{3044}" - invalid = "\x80".force_encoding("utf-8") - after1 = "\u{3046}" - after2 = "\u{3048}" - w << before1 + before2 + invalid + after1 + after2 - w.close - assert_equal(before1.encode("euc-jp"), r.getc) - assert_equal(before2.encode("euc-jp"), r.getc) - err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc } - assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes) - assert_equal(after1.encode("euc-jp"), r.getc) - assert_equal(after2.encode("euc-jp"), r.getc) - } + before1 = "\u{3042}" + before2 = "\u{3044}" + invalid = "\x80".force_encoding("utf-8") + after1 = "\u{3046}" + after2 = "\u{3048}" + pipe("utf-8:euc-jp", + proc do |w| + w << before1 + before2 + invalid + after1 + after2 + w.close + end, + proc do |r| + assert_equal(before1.encode("euc-jp"), r.getc) + assert_equal(before2.encode("euc-jp"), r.getc) + err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc } + assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes) + assert_equal(after1.encode("euc-jp"), r.getc) + assert_equal(after2.encode("euc-jp"), r.getc) + end) end def test_getc_invalid3 - with_pipe("utf-16le:euc-jp", binmode: true) {|r, w| - before1 = "\x42\x30".force_encoding("utf-16le") - before2 = "\x44\x30".force_encoding("utf-16le") - invalid = "\x00\xd8".force_encoding("utf-16le") - after1 = "\x46\x30".force_encoding("utf-16le") - after2 = "\x48\x30".force_encoding("utf-16le") - w << before1 + before2 + invalid + after1 + after2 - w.close - assert_equal(before1.encode("euc-jp"), r.getc) - assert_equal(before2.encode("euc-jp"), r.getc) - err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc } - assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes) - assert_equal(after1.encode("euc-jp"), r.getc) - assert_equal(after2.encode("euc-jp"), r.getc) - } + before1 = "\x42\x30".force_encoding("utf-16le") + before2 = "\x44\x30".force_encoding("utf-16le") + invalid = "\x00\xd8".force_encoding("utf-16le") + after1 = "\x46\x30".force_encoding("utf-16le") + after2 = "\x48\x30".force_encoding("utf-16le") + pipe("utf-16le:euc-jp", { :binmode => true }, + proc do |w| + w << before1 + before2 + invalid + after1 + after2 + w.close + end, + proc do |r| + assert_equal(before1.encode("euc-jp"), r.getc) + assert_equal(before2.encode("euc-jp"), r.getc) + err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc } + assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes) + assert_equal(after1.encode("euc-jp"), r.getc) + assert_equal(after2.encode("euc-jp"), r.getc) + end) end def test_read_all - with_pipe("utf-8:euc-jp") {|r, w| - str = "\u3042\u3044" - w << str - w.close - assert_equal(str.encode("euc-jp"), r.read) - } + str = "\u3042\u3044" + pipe("utf-8:euc-jp", + proc do |w| + w << str + w.close + end, + proc do |r| + assert_equal(str.encode("euc-jp"), r.read) + end) end def test_read_all_invalid - with_pipe("utf-8:euc-jp") {|r, w| - before = "\u{3042}\u{3044}" - invalid = "\x80".force_encoding("utf-8") - after = "\u{3046}\u{3048}" - w << before + invalid + after - w.close - err = assert_raise(Encoding::InvalidByteSequenceError) { r.read } - assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes) - assert_equal(after.encode("euc-jp"), r.read) - } + before = "\u{3042}\u{3044}" + invalid = "\x80".force_encoding("utf-8") + after = "\u{3046}\u{3048}" + pipe("utf-8:euc-jp", + proc do |w| + w << before + invalid + after + w.close + end, + proc do |r| + err = assert_raise(Encoding::InvalidByteSequenceError) { r.read } + assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes) + assert_equal(after.encode("euc-jp"), r.read) + end) end def test_file_foreach @@ -788,84 +857,104 @@ end def test_set_encoding - with_pipe("utf-8:euc-jp") {|r, w| - s = "\u3042".force_encoding("ascii-8bit") - s << "\x82\xa0".force_encoding("ascii-8bit") - w << s - w.close - assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) - r.set_encoding("shift_jis:euc-jp") - assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) - } + pipe("utf-8:euc-jp", + proc do |w| + s = "\u3042".force_encoding("ascii-8bit") + s << "\x82\xa0".force_encoding("ascii-8bit") + w << s + w.close + end, + proc do |r| + assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) + r.set_encoding("shift_jis:euc-jp") + assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) + end) end def test_set_encoding2 - with_pipe("utf-8:euc-jp") {|r, w| - s = "\u3042".force_encoding("ascii-8bit") - s << "\x82\xa0".force_encoding("ascii-8bit") - w << s - w.close - assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) - r.set_encoding("shift_jis", "euc-jp") - assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) - } + pipe("utf-8:euc-jp", + proc do |w| + s = "\u3042".force_encoding("ascii-8bit") + s << "\x82\xa0".force_encoding("ascii-8bit") + w << s + w.close + end, + proc do |r| + assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) + r.set_encoding("shift_jis", "euc-jp") + assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) + end) end def test_set_encoding_nil - with_pipe("utf-8:euc-jp") {|r, w| - s = "\u3042".force_encoding("ascii-8bit") - s << "\x82\xa0".force_encoding("ascii-8bit") - w << s - w.close - assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) - r.set_encoding(nil) - assert_equal("\x82\xa0".force_encoding(Encoding.default_external), r.read) - } + pipe("utf-8:euc-jp", + proc do |w| + s = "\u3042".force_encoding("ascii-8bit") + s << "\x82\xa0".force_encoding("ascii-8bit") + w << s + w.close + end, + proc do |r| + assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) + r.set_encoding(nil) + assert_equal("\x82\xa0".force_encoding(Encoding.default_external), r.read) + end) end def test_set_encoding_enc - with_pipe("utf-8:euc-jp") {|r, w| - s = "\u3042".force_encoding("ascii-8bit") - s << "\x82\xa0".force_encoding("ascii-8bit") - w << s - w.close - assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) - r.set_encoding(Encoding::Shift_JIS) - assert_equal("\x82\xa0".force_encoding(Encoding::Shift_JIS), r.getc) - } + pipe("utf-8:euc-jp", + proc do |w| + s = "\u3042".force_encoding("ascii-8bit") + s << "\x82\xa0".force_encoding("ascii-8bit") + w << s + w.close + end, + proc do |r| + assert_equal("\xa4\xa2".force_encoding("euc-jp"), r.getc) + r.set_encoding(Encoding::Shift_JIS) + assert_equal("\x82\xa0".force_encoding(Encoding::Shift_JIS), r.getc) + end) end def test_set_encoding_invalid - with_pipe {|r, w| - w << "\x80" - w.close - r.set_encoding("utf-8:euc-jp", :invalid=>:replace) - assert_equal("?", r.read) - } + pipe(proc do |w| + w << "\x80" + w.close + end, + proc do |r| + r.set_encoding("utf-8:euc-jp", :invalid=>:replace) + assert_equal("?", r.read) + end) end def test_set_encoding_undef - with_pipe {|r, w| - w << "\ufffd" - w.close - r.set_encoding("utf-8", "euc-jp", :undef=>:replace) - assert_equal("?", r.read) - } + pipe(proc do |w| + w << "\ufffd" + w.close + end, + proc do |r| + r.set_encoding("utf-8", "euc-jp", :undef=>:replace) + assert_equal("?", r.read) + end) end def test_set_encoding_undef_replace - with_pipe {|r, w| - w << "\ufffd" - w.close - r.set_encoding("utf-8", "euc-jp", :undef=>:replace, :replace=>"ZZZ") - assert_equal("ZZZ", r.read) - } - with_pipe {|r, w| - w << "\ufffd" - w.close - r.set_encoding("utf-8:euc-jp", :undef=>:replace, :replace=>"ZZZ") - assert_equal("ZZZ", r.read) - } + pipe(proc do |w| + w << "\ufffd" + w.close + end, + proc do |r| + r.set_encoding("utf-8", "euc-jp", :undef=>:replace, :replace=>"ZZZ") + assert_equal("ZZZ", r.read) + end) + pipe(proc do |w| + w << "\ufffd" + w.close + end, + proc do |r| + r.set_encoding("utf-8:euc-jp", :undef=>:replace, :replace=>"ZZZ") + assert_equal("ZZZ", r.read) + end) end def test_set_encoding_binmode @@ -899,56 +988,67 @@ end def test_write_conversion_fixenc - with_pipe {|r, w| - w.set_encoding("iso-2022-jp:utf-8") - t = Thread.new { r.read.force_encoding("ascii-8bit") } - w << "\u3042" - w << "\u3044" - w.close - assert_equal("\e$B$\"$$\e(B".force_encoding("ascii-8bit"), t.value) - } + pipe(proc do |w| + w.set_encoding("iso-2022-jp:utf-8") + w << "\u3042" + w << "\u3044" + w.close + end, + proc do |r| + assert_equal("\e$B$\"$$\e(B".force_encoding("ascii-8bit"), + r.read.force_encoding("ascii-8bit")) + end) end def test_write_conversion_anyenc_stateful - with_pipe {|r, w| - w.set_encoding("iso-2022-jp") - t = Thread.new { r.read.force_encoding("ascii-8bit") } - w << "\u3042" - w << "\x82\xa2".force_encoding("sjis") - w.close - assert_equal("\e$B$\"$$\e(B".force_encoding("ascii-8bit"), t.value) - } + pipe(proc do |w| + w.set_encoding("iso-2022-jp") + w << "\u3042" + w << "\x82\xa2".force_encoding("sjis") + w.close + end, + proc do |r| + assert_equal("\e$B$\"$$\e(B".force_encoding("ascii-8bit"), + r.read.force_encoding("ascii-8bit")) + end) end def test_write_conversion_anyenc_stateless - with_pipe {|r, w| - w.set_encoding("euc-jp") - t = Thread.new { r.read.force_encoding("ascii-8bit") } - w << "\u3042" - w << "\x82\xa2".force_encoding("sjis") - w.close - assert_equal("\xa4\xa2\xa4\xa4".force_encoding("ascii-8bit"), t.value) - } + pipe(proc do |w| + w.set_encoding("euc-jp") + w << "\u3042" + w << "\x82\xa2".force_encoding("sjis") + w.close + end, + proc do |r| + assert_equal("\xa4\xa2\xa4\xa4".force_encoding("ascii-8bit"), + r.read.force_encoding("ascii-8bit")) + end) end def test_write_conversion_anyenc_stateful_nosync - with_pipe {|r, w| - w.sync = false - w.set_encoding("iso-2022-jp") - t = Thread.new { r.read.force_encoding("ascii-8bit") } - w << "\u3042" - w << "\x82\xa2".force_encoding("sjis") - w.close - assert_equal("\e$B$\"$$\e(B".force_encoding("ascii-8bit"), t.value) - } + pipe(proc do |w| + w.sync = false + w.set_encoding("iso-2022-jp") + w << "\u3042" + w << "\x82\xa2".force_encoding("sjis") + w.close + end, + proc do |r| + assert_equal("\e$B$\"$$\e(B".force_encoding("ascii-8bit"), + r.read.force_encoding("ascii-8bit")) + end) end def test_read_stateful - with_pipe("euc-jp:iso-2022-jp") {|r, w| - w << "\xA4\xA2" - w.close - assert_equal("\e$B$\"\e(B".force_encoding("iso-2022-jp"), r.read) - } + pipe("euc-jp:iso-2022-jp", + proc do |w| + w << "\xA4\xA2" + w.close + end, + proc do |r| + assert_equal("\e$B$\"\e(B".force_encoding("iso-2022-jp"), r.read) + end) end def test_stdin_external_encoding_with_reopen @@ -1814,30 +1914,39 @@ end def test_cbuf_select - with_pipe("US-ASCII:UTF-8", :universal_newline => true) do |r, w| - w << "\r\n" - r.ungetc(r.getc) - assert_equal([[r],[],[]], IO.select([r], nil, nil, 1)) - end + pipe("US-ASCII:UTF-8", { :universal_newline => true }, + proc do |w| + w << "\r\n" + end, + proc do |r| + r.ungetc(r.getc) + assert_equal([[r],[],[]], IO.select([r], nil, nil, 1)) + end) end def test_textmode_paragraphmode - with_pipe("US-ASCII:UTF-8", :universal_newline => true) do |r, w| - w << "a\n\n\nc".gsub(/\n/, "\r\n") - w.close - assert_equal("a\n\n", r.gets("")) - assert_equal("c", r.gets(""), "[ruby-core:23723] (18)") - end + pipe("US-ASCII:UTF-8", { :universal_newline => true }, + proc do |w| + w << "a\n\n\nc".gsub(/\n/, "\r\n") + w.close + end, + proc do |r| + assert_equal("a\n\n", r.gets("")) + assert_equal("c", r.gets(""), "[ruby-core:23723] (18)") + end) end def test_textmode_paragraph_binaryread - with_pipe("US-ASCII:UTF-8", :universal_newline => true) do |r, w| - w << "a\n\n\ncdefgh".gsub(/\n/, "\r\n") - w.close - assert_equal("a\n\n", r.gets("")) - assert_equal("c", r.getc) - assert_equal("defgh", r.readpartial(10)) - end + pipe("US-ASCII:UTF-8", { :universal_newline => true }, + proc do |w| + w << "a\n\n\ncdefgh".gsub(/\n/, "\r\n") + w.close + end, + proc do |r| + assert_equal("a\n\n", r.gets("")) + assert_equal("c", r.getc) + assert_equal("defgh", r.readpartial(10)) + end) end def test_textmode_paragraph_nonasciicompat @@ -1847,9 +1956,10 @@ Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_8].each do |e| r.set_encoding(Encoding::US_ASCII, e) - w.print(bug3534[0], "\n\n\n\n", bug3534[1], "\n") + wthr = Thread.new{ w.print(bug3534[0], "\n\n\n\n", bug3534[1], "\n") } assert_equal((bug3534[0]+"\n\n").encode(e), r.gets(""), bug3534[0]) assert_equal((bug3534[1]+"\n").encode(e), r.gets(), bug3534[1]) + wthr.join end end @@ -1862,28 +1972,33 @@ Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_8].each do |e| r.set_encoding(Encoding::US_ASCII, e) - w.print(bug3534[0], "\n\n\n\n", bug3534[1], "\n") + wthr = Thread.new{ w.print(bug3534[0], "\n\n\n\n", bug3534[1], "\n") } assert_equal((bug3534[0]+"\n\n").encode(e), r.gets(""), bug3534[0]) assert_equal((bug3534[1]+"\n").encode(e), r.gets(), bug3534[1]) + wthr.join end end def test_puts_widechar bug = '[ruby-dev:42212]' - r, w = IO.pipe(Encoding::ASCII_8BIT) - r.binmode - w.binmode - w.puts(0x010a.chr(Encoding::UTF_32BE)) - w.puts(0x010a.chr(Encoding::UTF_16BE)) - w.puts(0x0a010000.chr(Encoding::UTF_32LE)) - w.puts(0x0a01.chr(Encoding::UTF_16LE)) - w.close - assert_equal("\x00\x00\x01\x0a\n", r.read(5), bug) - assert_equal("\x01\x0a\n", r.read(3), bug) - assert_equal("\x00\x00\x01\x0a\n", r.read(5), bug) - assert_equal("\x01\x0a\n", r.read(3), bug) - assert_equal("", r.read, bug) - r.close + pipe(Encoding::ASCII_8BIT, + proc do |w| + w.binmode + w.puts(0x010a.chr(Encoding::UTF_32BE)) + w.puts(0x010a.chr(Encoding::UTF_16BE)) + w.puts(0x0a010000.chr(Encoding::UTF_32LE)) + w.puts(0x0a01.chr(Encoding::UTF_16LE)) + w.close + end, + proc do |r| + r.binmode + assert_equal("\x00\x00\x01\x0a\n", r.read(5), bug) + assert_equal("\x01\x0a\n", r.read(3), bug) + assert_equal("\x00\x00\x01\x0a\n", r.read(5), bug) + assert_equal("\x01\x0a\n", r.read(3), bug) + assert_equal("", r.read, bug) + r.close + end) end end Index: test/ruby/test_io.rb =================================================================== --- test/ruby/test_io.rb (revision 29519) +++ test/ruby/test_io.rb (working copy) @@ -22,14 +22,59 @@ IO.method_defined?("nonblock=") end + def pipe(wp, rp) + r, w = IO.pipe + rt = Thread.new { rp.call(r) } + wt = Thread.new { wp.call(w) } + flunk("timeout") unless rt.join(10) && wt.join(10) + ensure + r.close unless !r || r.closed? + w.close unless !w || w.closed? + (rt.kill; rt.join) if rt + (wt.kill; wt.join) if wt + 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) + pipe(proc do |w| + w << content + w.close + end, proc do |r| + yield r + end) + end + + def mkcdtmpdir + Dir.mktmpdir {|d| + Dir.chdir(d) { + yield + } + } + end + def test_pipe r, w = IO.pipe assert_instance_of(IO, r) assert_instance_of(IO, w) - w.print "abc" - w.close - assert_equal("abc", r.read) - r.close + [ + Thread.start{ + w.print "abc" + w.close + }, + Thread.start{ + assert_equal("abc", r.read) + r.close + } + ].each{|thr| thr.join} end def test_pipe_block @@ -38,9 +83,15 @@ x = [r,w] assert_instance_of(IO, r) assert_instance_of(IO, w) - w.print "abc" - w.close - assert_equal("abc", r.read) + [ + Thread.start do + w.print "abc" + w.close + end, + Thread.start do + assert_equal("abc", r.read) + end + ].each{|thr| thr.join} assert(!r.closed?) assert(w.closed?) :foooo @@ -65,58 +116,66 @@ 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 + pipe(proc do |w| + w.print "aaa\nbbb\n" + w.close + end, proc do |r| + assert_equal "aaa\n", r.gets + assert_equal "bbb\n", r.gets + assert_nil r.gets + r.close + end) # 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 + pipe(proc do |w| + w.print "a\n\nb\n\n" + w.close + end, proc do |r| + assert_equal "a\n\nb\n\n", r.gets(nil) + assert_nil r.gets("") + r.close + end) # "\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 + pipe(proc do |w| + w.print "\377xyz" + w.close + end, proc do |r| + r.binmode + assert_equal("\377", r.gets("\377"), "[ruby-dev:24460]") + r.close + end) # "" - 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 + pipe(proc do |w| + w.print "a\n\nb\n\n" + w.close + end, proc do |r| + assert_equal "a\n\n", r.gets(""), "[ruby-core:03771]" + assert_equal "b\n\n", r.gets("") + assert_nil r.gets("") + r.close + end) end def test_gets_limit_extra_arg - with_pipe {|r, w| - r, w = IO.pipe + pipe(proc do |w| w << "0123456789\n0123456789" w.close + end, proc do |r| assert_equal("0123456789\n0", r.gets(nil, 12)) assert_raise(TypeError) { r.gets(3,nil) } - } + end) end # This test cause SEGV. def test_ungetc - r, w = IO.pipe - w.close - s = "a" * 1000 - assert_raise(IOError, "[ruby-dev:31650]") { 200.times { r.ungetc s } } - ensure - r.close + pipe(proc do |w| + w.close + end, proc do |r| + s = "a" * 1000 + assert_raise(IOError, "[ruby-dev:31650]") { 200.times { r.ungetc s } } + end) end def test_ungetbyte @@ -142,13 +201,13 @@ 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 + pipe(proc do |w| + w << "abc def" + w.close + end, proc do |r| + r.each_byte {|byte| break if byte == 32 } + assert_equal("def", r.read, "[ruby-dev:31659]") + end) end def test_each_codepoint @@ -170,35 +229,6 @@ 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 { @@ -235,12 +265,13 @@ IO.copy_stream("src", "nodir/bar") } - with_pipe {|r, w| + pipe(proc do |w| ret = IO.copy_stream("src", w) assert_equal(content.bytesize, ret) w.close + end, proc do |r| assert_equal(content, r.read) - } + end) with_pipe {|r, w| w.close @@ -256,77 +287,85 @@ with_read_pipe("abc") {|r1| assert_equal("a", r1.getc) - with_pipe {|r2, w2| + pipe(proc do |w2| w2.sync = false w2 << "def" ret = IO.copy_stream(r1, w2) assert_equal(2, ret) w2.close + end, proc do |r2| assert_equal("defbc", r2.read) - } + end) } with_read_pipe("abc") {|r1| assert_equal("a", r1.getc) - with_pipe {|r2, w2| + pipe(proc do |w2| w2.sync = false w2 << "def" ret = IO.copy_stream(r1, w2, 1) assert_equal(1, ret) w2.close + end, proc do |r2| assert_equal("defb", r2.read) - } + end) } with_read_pipe("abc") {|r1| assert_equal("a", r1.getc) - with_pipe {|r2, w2| + pipe(proc do |w2| ret = IO.copy_stream(r1, w2) assert_equal(2, ret) w2.close + end, proc do |r2| assert_equal("bc", r2.read) - } + end) } with_read_pipe("abc") {|r1| assert_equal("a", r1.getc) - with_pipe {|r2, w2| + pipe(proc do |w2| ret = IO.copy_stream(r1, w2, 1) assert_equal(1, ret) w2.close + end, proc do |r2| assert_equal("b", r2.read) - } + end) } with_read_pipe("abc") {|r1| assert_equal("a", r1.getc) - with_pipe {|r2, w2| + pipe(proc do |w2| ret = IO.copy_stream(r1, w2, 0) assert_equal(0, ret) w2.close + end, proc do |r2| assert_equal("", r2.read) - } + end) } - with_pipe {|r1, w1| + pipe(proc do |w1| w1 << "abc" + w1 << "def" + w1.close + end, proc do |r1| assert_equal("a", r1.getc) - with_pipe {|r2, w2| - w1 << "def" - w1.close + pipe(proc do |w2| ret = IO.copy_stream(r1, w2) assert_equal(5, ret) w2.close + end, proc do |r2| assert_equal("bcdef", r2.read) - } - } + end) + end) - with_pipe {|r, w| + pipe(proc do |w| ret = IO.copy_stream("src", w, 1, 1) assert_equal(1, ret) w.close + end, proc do |r| assert_equal(content[1,1], r.read) - } + end) if have_nonblock? with_read_pipe("abc") {|r1| @@ -433,15 +472,16 @@ def test_copy_stream_rbuf mkcdtmpdir { begin - with_pipe {|r, w| + pipe(proc do |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 + end, proc do |r| assert_equal("bcd", r.read) - } + end) rescue NotImplementedError skip "pread(2) is not implemtented." end @@ -695,19 +735,20 @@ end def test_copy_stream_strio_rbuf - with_pipe {|r, w| + pipe(proc do |w| w << "abcd" w.close + end, proc do |r| assert_equal("a", r.read(1)) sio = StringIO.new IO.copy_stream(r, sio) assert_equal("bcd", sio.string) - } + end) end def test_copy_stream_src_wbuf mkcdtmpdir { - with_pipe {|r, w| + pipe(proc do |w| File.open("foe", "w+") {|f| f.write "abcd\n" f.rewind @@ -716,17 +757,19 @@ } assert_equal("xycd\n", File.read("foe")) w.close + end, proc do |r| assert_equal("cd\n", r.read) r.close - } + end) } end def test_copy_stream_dst_rbuf mkcdtmpdir { - with_pipe {|r, w| + pipe(proc do |w| w << "xyz" w.close + end, proc do |r| File.open("fom", "w+b") {|f| f.write "abcd\n" f.rewind @@ -735,7 +778,7 @@ IO.copy_stream(r, f) } assert_equal("abxyz", File.read("fom")) - } + end) } end @@ -750,18 +793,6 @@ end end - def pipe(wp, rp) - r, w = IO.pipe - rt = Thread.new { rp.call(r) } - wt = Thread.new { wp.call(w) } - flunk("timeout") unless rt.join(10) && wt.join(10) - ensure - r.close unless !r || r.closed? - w.close unless !w || w.closed? - (rt.kill; rt.join) if rt - (wt.kill; wt.join) if wt - end - def ruby(*args) args = ['-e', '$>.write($<.read)'] if args.empty? ruby = EnvUtil.rubybin