mirror of
https://github.com/ruby/ruby.git
synced 2025-08-23 13:04:13 +02:00

StringIO does not warn for unchilled unfrozen string or for frozen
string, so it should not warn for chilled string.
4ac33b8c70
1074 lines
29 KiB
Ruby
1074 lines
29 KiB
Ruby
# frozen_string_literal: false
|
|
require 'test/unit'
|
|
require 'stringio'
|
|
require "rbconfig/sizeof"
|
|
require_relative '../ruby/ut_eof'
|
|
|
|
class TestStringIO < Test::Unit::TestCase
|
|
include TestEOF
|
|
def open_file(content)
|
|
f = StringIO.new(content)
|
|
yield f
|
|
end
|
|
alias open_file_rw open_file
|
|
|
|
include TestEOF::Seek
|
|
|
|
def test_do_not_mutate_shared_buffers
|
|
# Ensure we have two strings that are not embedded but have the same shared
|
|
# string reference.
|
|
#
|
|
# In this case, we must use eval because we need two strings literals that
|
|
# are long enough they cannot be embedded, but also contain the same bytes.
|
|
|
|
a = eval("+"+("x" * 1024).dump)
|
|
b = eval("+"+("x" * 1024).dump)
|
|
|
|
s = StringIO.new(b)
|
|
s.getc
|
|
s.ungetc '#'
|
|
|
|
# We mutated b, so a should not be mutated
|
|
assert_equal("x", a[0])
|
|
end
|
|
|
|
def test_version
|
|
assert_kind_of(String, StringIO::VERSION)
|
|
end
|
|
|
|
def test_initialize
|
|
assert_kind_of StringIO, StringIO.new
|
|
assert_kind_of StringIO, StringIO.new('str')
|
|
assert_kind_of StringIO, StringIO.new('str', 'r+')
|
|
assert_kind_of StringIO, StringIO.new(nil)
|
|
assert_raise(ArgumentError) { StringIO.new('', 'x') }
|
|
assert_raise(ArgumentError) { StringIO.new('', 'rx') }
|
|
assert_raise(ArgumentError) { StringIO.new('', 'rbt') }
|
|
assert_raise(TypeError) { StringIO.new(Object) }
|
|
|
|
o = Object.new
|
|
def o.to_str
|
|
nil
|
|
end
|
|
assert_raise(TypeError) { StringIO.new(o) }
|
|
|
|
o = Object.new
|
|
def o.to_str
|
|
'str'
|
|
end
|
|
assert_kind_of StringIO, StringIO.new(o)
|
|
end
|
|
|
|
def test_null
|
|
io = StringIO.new(nil)
|
|
assert_nil io.gets
|
|
io.puts "abc"
|
|
assert_nil io.string
|
|
|
|
# Null device StringIO just drop ungot string
|
|
io.ungetc '#'
|
|
assert_nil io.getc
|
|
end
|
|
|
|
def test_truncate
|
|
io = StringIO.new("")
|
|
io.puts "abc"
|
|
assert_equal(0, io.truncate(0))
|
|
io.puts "def"
|
|
assert_equal("\0\0\0\0def\n", io.string, "[ruby-dev:24190]")
|
|
assert_raise(Errno::EINVAL) { io.truncate(-1) }
|
|
assert_equal(0, io.truncate(10))
|
|
assert_equal("\0\0\0\0def\n\0\0", io.string)
|
|
end
|
|
|
|
def test_seek_beyond_eof
|
|
io = StringIO.new
|
|
n = 100
|
|
io.seek(n)
|
|
io.print "last"
|
|
assert_equal("\0" * n + "last", io.string, "[ruby-dev:24194]")
|
|
end
|
|
|
|
def test_overwrite
|
|
stringio = StringIO.new
|
|
responses = ['', 'just another ruby', 'hacker']
|
|
responses.each do |resp|
|
|
stringio.puts(resp)
|
|
stringio.rewind
|
|
end
|
|
assert_equal("hacker\nother ruby\n", stringio.string, "[ruby-core:3836]")
|
|
end
|
|
|
|
def test_gets
|
|
assert_equal(nil, StringIO.new("").gets)
|
|
assert_equal("\n", StringIO.new("\n").gets)
|
|
assert_equal("a\n", StringIO.new("a\n").gets)
|
|
assert_equal("a\n", StringIO.new("a\nb\n").gets)
|
|
assert_equal("a", StringIO.new("a").gets)
|
|
assert_equal("a\n", StringIO.new("a\nb").gets)
|
|
assert_equal("abc\n", StringIO.new("abc\n\ndef\n").gets)
|
|
assert_equal("abc\n\ndef\n", StringIO.new("abc\n\ndef\n").gets(nil))
|
|
assert_equal("abc\n\n", StringIO.new("abc\n\ndef\n").gets(""))
|
|
stringio = StringIO.new("abc\n\ndef\n")
|
|
assert_equal("abc\n\n", stringio.gets(""))
|
|
assert_equal("def\n", stringio.gets(""))
|
|
assert_raise(TypeError){StringIO.new("").gets(1, 1)}
|
|
assert_nothing_raised {StringIO.new("").gets(nil, nil)}
|
|
|
|
assert_string("", Encoding::UTF_8, StringIO.new("foo").gets(0))
|
|
end
|
|
|
|
def test_gets_utf_16
|
|
stringio = StringIO.new("line1\nline2\nline3\n".encode("utf-16le"))
|
|
assert_equal("line1\n".encode("utf-16le"), stringio.gets)
|
|
assert_equal("line2\n".encode("utf-16le"), stringio.gets)
|
|
assert_equal("line3\n".encode("utf-16le"), stringio.gets)
|
|
assert_nil(stringio.gets)
|
|
end
|
|
|
|
def test_gets_chomp
|
|
assert_equal(nil, StringIO.new("").gets(chomp: true))
|
|
assert_equal("", StringIO.new("\n").gets(chomp: true))
|
|
assert_equal("a", StringIO.new("a\n").gets(chomp: true))
|
|
assert_equal("a", StringIO.new("a\nb\n").gets(chomp: true))
|
|
assert_equal("a", StringIO.new("a").gets(chomp: true))
|
|
assert_equal("a", StringIO.new("a\nb").gets(chomp: true))
|
|
assert_equal("abc", StringIO.new("abc\n\ndef\n").gets(chomp: true))
|
|
assert_equal("abc\n\ndef\n", StringIO.new("abc\n\ndef\n").gets(nil, chomp: true))
|
|
assert_equal("abc", StringIO.new("abc\n\ndef\n").gets("", chomp: true))
|
|
stringio = StringIO.new("abc\n\ndef\n")
|
|
assert_equal("abc", stringio.gets("", chomp: true))
|
|
assert_equal("def\n", stringio.gets("", chomp: true))
|
|
|
|
assert_string("", Encoding::UTF_8, StringIO.new("\n").gets(chomp: true))
|
|
|
|
assert_equal("", StringIO.new("ab").gets("ab", chomp: true))
|
|
end
|
|
|
|
def test_gets_chomp_eol
|
|
assert_equal(nil, StringIO.new("").gets(chomp: true))
|
|
assert_equal("", StringIO.new("\r\n").gets(chomp: true))
|
|
assert_equal("a", StringIO.new("a\r\n").gets(chomp: true))
|
|
assert_equal("a", StringIO.new("a\r\nb\r\n").gets(chomp: true))
|
|
assert_equal("a", StringIO.new("a").gets(chomp: true))
|
|
assert_equal("a", StringIO.new("a\r\nb").gets(chomp: true))
|
|
assert_equal("abc", StringIO.new("abc\r\n\r\ndef\r\n").gets(chomp: true))
|
|
assert_equal("abc\r\n\r\ndef\r\n", StringIO.new("abc\r\n\r\ndef\r\n").gets(nil, chomp: true))
|
|
assert_equal("abc", StringIO.new("abc\r\n\r\ndef\r\n").gets("", chomp: true))
|
|
stringio = StringIO.new("abc\r\n\r\ndef\r\n")
|
|
assert_equal("abc", stringio.gets("", chomp: true))
|
|
assert_equal("def\r\n", stringio.gets("", chomp: true))
|
|
end
|
|
|
|
def test_readlines
|
|
assert_equal([], StringIO.new("").readlines)
|
|
assert_equal(["\n"], StringIO.new("\n").readlines)
|
|
assert_equal(["a\n"], StringIO.new("a\n").readlines)
|
|
assert_equal(["a\n", "b\n"], StringIO.new("a\nb\n").readlines)
|
|
assert_equal(["a"], StringIO.new("a").readlines)
|
|
assert_equal(["a\n", "b"], StringIO.new("a\nb").readlines)
|
|
assert_equal(["abc\n", "\n", "def\n"], StringIO.new("abc\n\ndef\n").readlines)
|
|
assert_equal(["abc\n\ndef\n"], StringIO.new("abc\n\ndef\n").readlines(nil), "[ruby-dev:34591]")
|
|
assert_equal(["abc\n\n", "def\n"], StringIO.new("abc\n\ndef\n").readlines(""))
|
|
end
|
|
|
|
def test_write
|
|
s = ""
|
|
f = StringIO.new(s, "w")
|
|
f.print("foo")
|
|
f.close
|
|
assert_equal("foo", s)
|
|
|
|
f = StringIO.new(s, File::WRONLY)
|
|
f.print("bar")
|
|
f.close
|
|
assert_equal("bar", s)
|
|
|
|
f = StringIO.new(s, "a")
|
|
o = Object.new
|
|
def o.to_s; "baz"; end
|
|
f.print(o)
|
|
f.close
|
|
assert_equal("barbaz", s)
|
|
ensure
|
|
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")
|
|
f.write_nonblock("foo")
|
|
f.close
|
|
assert_equal("foo", s)
|
|
|
|
f = StringIO.new(s, File::WRONLY)
|
|
f.write_nonblock("bar")
|
|
f.close
|
|
assert_equal("bar", s)
|
|
|
|
f = StringIO.new(s, "a")
|
|
o = Object.new
|
|
def o.to_s; "baz"; end
|
|
f.write_nonblock(o)
|
|
f.close
|
|
assert_equal("barbaz", s)
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_write_encoding
|
|
s = "".force_encoding(Encoding::UTF_8)
|
|
f = StringIO.new(s)
|
|
f.print("\u{3053 3093 306b 3061 306f ff01}".b)
|
|
assert_equal(Encoding::UTF_8, s.encoding, "honor the original encoding over ASCII-8BIT")
|
|
end
|
|
|
|
def test_write_encoding_conversion
|
|
convertible = "\u{3042}"
|
|
inconvertible = "\u{1f363}"
|
|
conversion_encoding = Encoding::Windows_31J
|
|
|
|
s = StringIO.new.set_encoding(conversion_encoding)
|
|
s.write(convertible)
|
|
assert_equal(conversion_encoding, s.string.encoding)
|
|
|
|
s = StringIO.new.set_encoding(Encoding::UTF_8)
|
|
s.write("foo".force_encoding("ISO-8859-1"), convertible)
|
|
assert_equal(Encoding::UTF_8, s.string.encoding)
|
|
|
|
s = StringIO.new.set_encoding(Encoding::US_ASCII)
|
|
s.write("foo".force_encoding("US-ASCII"), convertible)
|
|
assert_equal(Encoding::UTF_8, s.string.encoding)
|
|
|
|
all_assertions do |a|
|
|
[
|
|
inconvertible,
|
|
convertible + inconvertible,
|
|
[convertible, inconvertible],
|
|
["a", inconvertible],
|
|
].each do |data|
|
|
a.for(data.inspect) do
|
|
s = StringIO.new.set_encoding(conversion_encoding)
|
|
assert_raise(Encoding::CompatibilityError) do
|
|
s.write(*data)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_write_integer_overflow
|
|
f = StringIO.new
|
|
f.pos = StringIO::MAX_LENGTH
|
|
assert_raise(ArgumentError) {
|
|
f.write("pos + len overflows")
|
|
}
|
|
end
|
|
|
|
def test_write_with_multiple_arguments
|
|
s = ""
|
|
f = StringIO.new(s, "w")
|
|
f.write("foo", "bar")
|
|
f.close
|
|
assert_equal("foobar", s)
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_set_encoding
|
|
bug10285 = '[ruby-core:65240] [Bug #10285]'
|
|
f = StringIO.new()
|
|
f.set_encoding(Encoding::ASCII_8BIT)
|
|
f.write("quz \x83 mat".b)
|
|
s = "foo \x97 bar".force_encoding(Encoding::WINDOWS_1252)
|
|
assert_nothing_raised(Encoding::CompatibilityError, bug10285) {
|
|
f.write(s)
|
|
}
|
|
assert_equal(Encoding::ASCII_8BIT, f.string.encoding, bug10285)
|
|
|
|
bug11827 = '[ruby-core:72189] [Bug #11827]'
|
|
f = StringIO.new("foo\x83".freeze)
|
|
assert_nothing_raised(RuntimeError, bug11827) {
|
|
f.set_encoding(Encoding::ASCII_8BIT)
|
|
}
|
|
assert_equal("foo\x83".b, f.gets)
|
|
|
|
f = StringIO.new()
|
|
f.set_encoding("ISO-8859-16:ISO-8859-1")
|
|
assert_equal(Encoding::ISO_8859_16, f.external_encoding)
|
|
assert_equal(Encoding::ISO_8859_16, f.string.encoding)
|
|
assert_nil(f.internal_encoding)
|
|
end
|
|
|
|
def test_mode_error
|
|
f = StringIO.new("", "r")
|
|
assert_raise(IOError) { f.write("foo") }
|
|
|
|
f = StringIO.new("", "w")
|
|
assert_raise(IOError) { f.read }
|
|
|
|
assert_raise(Errno::EACCES) { StringIO.new("".freeze, "w") }
|
|
s = ""
|
|
f = StringIO.new(s, "w")
|
|
s.freeze
|
|
assert_raise(IOError) { f.write("foo") }
|
|
|
|
assert_raise(IOError) { StringIO.allocate.read }
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_open
|
|
s = ""
|
|
StringIO.open("foo") {|f| s = f.read }
|
|
assert_equal("foo", s)
|
|
end
|
|
|
|
def test_isatty
|
|
assert_equal(false, StringIO.new("").isatty)
|
|
end
|
|
|
|
def test_fsync
|
|
assert_equal(0, StringIO.new("").fsync)
|
|
end
|
|
|
|
def test_sync
|
|
assert_equal(true, StringIO.new("").sync)
|
|
assert_equal(false, StringIO.new("").sync = false)
|
|
end
|
|
|
|
def test_set_fcntl
|
|
assert_raise(NotImplementedError) { StringIO.new("").fcntl }
|
|
end
|
|
|
|
def test_close
|
|
f = StringIO.new("")
|
|
f.close
|
|
assert_nil(f.close)
|
|
|
|
f = StringIO.new("")
|
|
f.close_read
|
|
f.close_write
|
|
assert_nil(f.close)
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_close_read
|
|
f = StringIO.new("")
|
|
f.close_read
|
|
assert_raise(IOError) { f.read }
|
|
assert_nothing_raised(IOError) {f.close_read}
|
|
f.close
|
|
|
|
f = StringIO.new("", "w")
|
|
assert_raise(IOError) { f.close_read }
|
|
f.close
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_close_write
|
|
f = StringIO.new("")
|
|
f.close_write
|
|
assert_raise(IOError) { f.write("foo") }
|
|
assert_nothing_raised(IOError) {f.close_write}
|
|
f.close
|
|
|
|
f = StringIO.new("", "r")
|
|
assert_raise(IOError) { f.close_write }
|
|
f.close
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_closed
|
|
f = StringIO.new("")
|
|
assert_equal(false, f.closed?)
|
|
f.close
|
|
assert_equal(true, f.closed?)
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_closed_read
|
|
f = StringIO.new("")
|
|
assert_equal(false, f.closed_read?)
|
|
f.close_write
|
|
assert_equal(false, f.closed_read?)
|
|
f.close_read
|
|
assert_equal(true, f.closed_read?)
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_closed_write
|
|
f = StringIO.new("")
|
|
assert_equal(false, f.closed_write?)
|
|
f.close_read
|
|
assert_equal(false, f.closed_write?)
|
|
f.close_write
|
|
assert_equal(true, f.closed_write?)
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_dup
|
|
f1 = StringIO.new("1234")
|
|
assert_equal("1", f1.getc)
|
|
f2 = f1.dup
|
|
assert_equal("2", f2.getc)
|
|
assert_equal("3", f1.getc)
|
|
assert_equal("4", f2.getc)
|
|
assert_equal(nil, f1.getc)
|
|
assert_equal(true, f2.eof?)
|
|
f1.close
|
|
assert_equal(false, f2.closed?, '[ruby-core:48443]')
|
|
ensure
|
|
f1.close unless f1.closed?
|
|
f2.close unless f2.closed?
|
|
end
|
|
|
|
def test_lineno
|
|
f = StringIO.new("foo\nbar\nbaz\n")
|
|
assert_equal([0, "foo\n"], [f.lineno, f.gets])
|
|
assert_equal([1, "bar\n"], [f.lineno, f.gets])
|
|
f.lineno = 1000
|
|
assert_equal([1000, "baz\n"], [f.lineno, f.gets])
|
|
assert_equal([1001, nil], [f.lineno, f.gets])
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_pos
|
|
f = StringIO.new("foo\nbar\nbaz\n")
|
|
assert_equal([0, "foo\n"], [f.pos, f.gets])
|
|
assert_equal([4, "bar\n"], [f.pos, f.gets])
|
|
assert_raise(Errno::EINVAL) { f.pos = -1 }
|
|
f.pos = 1
|
|
assert_equal([1, "oo\n"], [f.pos, f.gets])
|
|
assert_equal([4, "bar\n"], [f.pos, f.gets])
|
|
assert_equal([8, "baz\n"], [f.pos, f.gets])
|
|
assert_equal([12, nil], [f.pos, f.gets])
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_reopen
|
|
f = StringIO.new("foo\nbar\nbaz\n")
|
|
assert_equal("foo\n", f.gets)
|
|
f.reopen("qux\nquux\nquuux\n")
|
|
assert_equal("qux\n", f.gets)
|
|
|
|
f2 = StringIO.new("")
|
|
f2.reopen(f)
|
|
assert_equal("quux\n", f2.gets)
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_seek
|
|
f = StringIO.new("1234")
|
|
assert_raise(Errno::EINVAL) { f.seek(-1) }
|
|
f.seek(-1, 2)
|
|
assert_equal("4", f.getc)
|
|
assert_raise(Errno::EINVAL) { f.seek(1, 3) }
|
|
f.close
|
|
assert_raise(IOError) { f.seek(0) }
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_seek_frozen_string
|
|
f = StringIO.new(-"1234")
|
|
assert_equal(0, f.seek(1))
|
|
end
|
|
|
|
def test_each_byte
|
|
f = StringIO.new("1234")
|
|
a = []
|
|
f.each_byte {|c| a << c }
|
|
assert_equal(%w(1 2 3 4).map {|c| c.ord }, a)
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_each_byte_closed
|
|
f = StringIO.new("1234")
|
|
assert_equal("1".ord, f.each_byte {|c| f.close; break c })
|
|
f = StringIO.new("1234")
|
|
assert_raise(IOError) do
|
|
f.each_byte { f.close }
|
|
end
|
|
end
|
|
|
|
def test_getbyte
|
|
f = StringIO.new("1234")
|
|
assert_equal("1".ord, f.getbyte)
|
|
assert_equal("2".ord, f.getbyte)
|
|
assert_equal("3".ord, f.getbyte)
|
|
assert_equal("4".ord, f.getbyte)
|
|
assert_equal(nil, f.getbyte)
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_ungetbyte
|
|
s = "foo\nbar\n"
|
|
t = StringIO.new(s, "r")
|
|
t.ungetbyte(0x41)
|
|
assert_equal(0x41, t.getbyte)
|
|
t.ungetbyte("qux")
|
|
assert_equal("quxfoo\n", t.gets)
|
|
t.set_encoding("utf-8")
|
|
t.ungetbyte(0x89)
|
|
t.ungetbyte(0x8e)
|
|
t.ungetbyte("\xe7")
|
|
t.ungetbyte("\xe7\xb4\x85")
|
|
assert_equal("\u7d05\u7389bar\n", t.gets)
|
|
assert_equal("q\u7d05\u7389bar\n", s)
|
|
t.pos = 1
|
|
t.ungetbyte("\u{30eb 30d3 30fc}")
|
|
assert_equal(0, t.pos)
|
|
assert_equal("\u{30eb 30d3 30fc}\u7d05\u7389bar\n", s)
|
|
|
|
assert_nothing_raised {t.ungetbyte(-1)}
|
|
assert_nothing_raised {t.ungetbyte(256)}
|
|
assert_nothing_raised {t.ungetbyte(1<<64)}
|
|
end
|
|
|
|
def test_ungetc
|
|
s = "1234"
|
|
f = StringIO.new(s, "r")
|
|
assert_nothing_raised { f.ungetc("x") }
|
|
assert_equal("x", f.getc) # bug? -> it's a feature from 1.9.
|
|
assert_equal("1", f.getc)
|
|
|
|
s = "1234"
|
|
f = StringIO.new(s, "r")
|
|
assert_equal("1", f.getc)
|
|
f.ungetc("y".ord)
|
|
assert_equal("y", f.getc)
|
|
assert_equal("2", f.getc)
|
|
|
|
assert_raise(RangeError) {f.ungetc(0x1ffffff)}
|
|
assert_raise(RangeError) {f.ungetc(0xffffffffffffff)}
|
|
ensure
|
|
f.close unless f.closed?
|
|
end
|
|
|
|
def test_readchar
|
|
f = StringIO.new("1234")
|
|
a = ""
|
|
assert_raise(EOFError) { loop { a << f.readchar } }
|
|
assert_equal("1234", a)
|
|
end
|
|
|
|
def test_readbyte
|
|
f = StringIO.new("1234")
|
|
a = []
|
|
assert_raise(EOFError) { loop { a << f.readbyte } }
|
|
assert_equal("1234".unpack("C*"), a)
|
|
end
|
|
|
|
def test_each_char
|
|
f = StringIO.new("1234")
|
|
assert_equal(%w(1 2 3 4), f.each_char.to_a)
|
|
end
|
|
|
|
def test_each_char_closed
|
|
f = StringIO.new("1234")
|
|
assert_equal("1", f.each_char {|c| f.close; break c })
|
|
f = StringIO.new("1234")
|
|
assert_raise(IOError) do
|
|
f.each_char { f.close }
|
|
end
|
|
end
|
|
|
|
def test_each_codepoint
|
|
f = StringIO.new("1234")
|
|
assert_equal([49, 50, 51, 52], f.each_codepoint.to_a)
|
|
end
|
|
|
|
def test_each_codepoint_closed
|
|
f = StringIO.new("1234")
|
|
assert_equal("1".ord, f.each_codepoint {|c| f.close; break c })
|
|
f = StringIO.new("1234")
|
|
assert_raise(IOError) do
|
|
f.each_codepoint { f.close }
|
|
end
|
|
end
|
|
|
|
def test_each_codepoint_enumerator
|
|
io = StringIO.new('你好построить')
|
|
|
|
chinese_part = io.each_codepoint.take(2).pack('U*')
|
|
russian_part = io.read(40).force_encoding('UTF-8')
|
|
|
|
assert_equal("你好", chinese_part)
|
|
assert_equal("построить", russian_part)
|
|
end
|
|
|
|
def test_gets2
|
|
f = StringIO.new("foo\nbar\nbaz\n")
|
|
assert_equal("fo", f.gets(2))
|
|
|
|
o = Object.new
|
|
def o.to_str; "z"; end
|
|
assert_equal("o\nbar\nbaz", f.gets(o))
|
|
|
|
f = StringIO.new("foo\nbar\nbaz\n")
|
|
assert_equal("foo\nbar\nbaz", f.gets("az"))
|
|
f = StringIO.new("a" * 10000 + "zz!")
|
|
assert_equal("a" * 10000 + "zz", f.gets("zz"))
|
|
f = StringIO.new("a" * 10000 + "zz!")
|
|
assert_equal("a" * 10000 + "zz!", f.gets("zzz"))
|
|
|
|
bug4112 = '[ruby-dev:42674]'
|
|
["a".encode("utf-16be"), "\u3042"].each do |s|
|
|
assert_equal(s, StringIO.new(s).gets(1), bug4112)
|
|
assert_equal(s, StringIO.new(s).gets(nil, 1), bug4112)
|
|
end
|
|
end
|
|
|
|
def test_each_string_sep
|
|
f = StringIO.new('a||b||c')
|
|
assert_equal(["a||", "b||", "c"], f.each("||").to_a)
|
|
f.rewind
|
|
assert_equal(["a", "b", "c"], f.each("||", chomp: true).to_a)
|
|
end
|
|
|
|
def test_each
|
|
f = StringIO.new("foo\nbar\nbaz\n")
|
|
assert_equal(["foo\n", "bar\n", "baz\n"], f.each.to_a)
|
|
f.rewind
|
|
assert_equal(["foo", "bar", "baz"], f.each(chomp: true).to_a)
|
|
f = StringIO.new("foo\nbar\n\n\nbaz\n")
|
|
assert_equal(["foo\nbar\n\n\n", "baz\n"], f.each("").to_a)
|
|
f.rewind
|
|
assert_equal(["foo\nbar", "baz\n"], f.each("", chomp: true).to_a)
|
|
|
|
f = StringIO.new("foo\r\nbar\r\n\r\n\r\nbaz\r\n")
|
|
assert_equal(["foo\r\nbar\r\n\r\n\r\n", "baz\r\n"], f.each("").to_a)
|
|
f.rewind
|
|
assert_equal(["foo\r\nbar", "baz\r\n"], f.each("", chomp: true).to_a)
|
|
|
|
f = StringIO.new("abc\n\ndef\n")
|
|
assert_equal(["ab", "c\n", "\nd", "ef", "\n"], f.each(nil, 2, chomp: true).to_a)
|
|
end
|
|
|
|
def test_putc
|
|
s = ""
|
|
f = StringIO.new(s, "w")
|
|
f.putc("1")
|
|
f.putc("2")
|
|
f.putc("3")
|
|
f.close
|
|
assert_equal("123", s)
|
|
|
|
s = "foo"
|
|
f = StringIO.new(s, "a")
|
|
f.putc("1")
|
|
f.putc("2")
|
|
f.putc("3")
|
|
f.close
|
|
assert_equal("foo123", s)
|
|
end
|
|
|
|
def test_putc_nonascii
|
|
s = ""
|
|
f = StringIO.new(s, "w")
|
|
f.putc("\u{3042}")
|
|
f.putc(0x3044)
|
|
f.close
|
|
assert_equal("\u{3042}D", s)
|
|
|
|
s = "foo"
|
|
f = StringIO.new(s, "a")
|
|
f.putc("\u{3042}")
|
|
f.putc(0x3044)
|
|
f.close
|
|
assert_equal("foo\u{3042}D", s)
|
|
end
|
|
|
|
def test_read
|
|
f = StringIO.new("\u3042\u3044")
|
|
assert_raise(ArgumentError) { f.read(-1) }
|
|
assert_raise(ArgumentError) { f.read(1, 2, 3) }
|
|
assert_equal("\u3042\u3044", f.read)
|
|
assert_nil(f.read(1))
|
|
f.rewind
|
|
assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read(f.size))
|
|
|
|
bug5207 = '[ruby-core:39026]'
|
|
f.rewind
|
|
assert_equal("\u3042\u3044", f.read(nil, nil), bug5207)
|
|
f.rewind
|
|
s = ""
|
|
assert_same(s, f.read(nil, s))
|
|
assert_equal("\u3042\u3044", s, bug5207)
|
|
f.rewind
|
|
# not empty buffer
|
|
s = "0123456789"
|
|
assert_same(s, f.read(nil, s))
|
|
assert_equal("\u3042\u3044", s)
|
|
|
|
bug13806 = '[ruby-core:82349] [Bug #13806]'
|
|
assert_string("", Encoding::UTF_8, f.read, bug13806)
|
|
assert_string("", Encoding::UTF_8, f.read(nil, nil), bug13806)
|
|
s.force_encoding(Encoding::US_ASCII)
|
|
assert_same(s, f.read(nil, s))
|
|
assert_string("", Encoding::UTF_8, s, bug13806)
|
|
|
|
bug20418 = '[Bug #20418] ™€®'.b
|
|
f = StringIO.new(bug20418)
|
|
s = ""
|
|
assert_equal(Encoding::UTF_8, s.encoding, bug20418)
|
|
f.read(4, s)
|
|
assert_equal(Encoding::UTF_8, s.encoding, bug20418)
|
|
|
|
f.rewind
|
|
s = ""
|
|
f.read(nil, s)
|
|
assert_equal(Encoding::ASCII_8BIT, s.encoding, bug20418)
|
|
end
|
|
|
|
def test_readpartial
|
|
f = StringIO.new("\u3042\u3044")
|
|
assert_raise(ArgumentError) { f.readpartial(-1) }
|
|
assert_raise(ArgumentError) { f.readpartial(1, 2, 3) }
|
|
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
|
|
# not empty buffer
|
|
s = '0123456789'.b
|
|
assert_equal("\u3042\u3044".b, f.readpartial(f.size, s))
|
|
end
|
|
|
|
def test_read_nonblock
|
|
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".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
|
|
# not empty buffer
|
|
s = '0123456789'.b
|
|
assert_equal("\u3042\u3044".b, f.read_nonblock(f.size, s))
|
|
end
|
|
|
|
def test_sysread
|
|
f = StringIO.new("sysread \u{30c6 30b9 30c8}")
|
|
assert_equal "sysread \u{30c6 30b9 30c8}", f.sysread
|
|
assert_equal "", f.sysread
|
|
assert_raise(EOFError) { f.sysread(1) }
|
|
f.rewind
|
|
assert_equal Encoding::ASCII_8BIT, f.sysread(3).encoding
|
|
end
|
|
|
|
def test_pread
|
|
f = StringIO.new("pread")
|
|
f.read
|
|
|
|
assert_equal "pre".b, f.pread(3, 0)
|
|
assert_equal "read".b, f.pread(4, 1)
|
|
assert_equal Encoding::ASCII_8BIT, f.pread(4, 1).encoding
|
|
|
|
buf = "".b
|
|
f.pread(3, 0, buf)
|
|
assert_equal "pre".b, buf
|
|
f.pread(4, 1, buf)
|
|
assert_equal "read".b, buf
|
|
|
|
assert_raise(EOFError) { f.pread(1, 5) }
|
|
assert_raise(ArgumentError) { f.pread(-1, 0) }
|
|
assert_raise(Errno::EINVAL) { f.pread(3, -1) }
|
|
|
|
assert_equal "".b, StringIO.new("").pread(0, 0)
|
|
assert_equal "".b, StringIO.new("").pread(0, -10)
|
|
|
|
buf = "stale".b
|
|
assert_equal "stale".b, StringIO.new("").pread(0, 0, buf)
|
|
assert_equal "stale".b, buf
|
|
end
|
|
|
|
def test_size
|
|
f = StringIO.new("1234")
|
|
assert_equal(4, f.size)
|
|
end
|
|
|
|
# This test is should in ruby/test_method.rb
|
|
# However this test depends on stringio library,
|
|
# we write it here.
|
|
class C < StringIO
|
|
alias old_init initialize
|
|
attr_reader :foo
|
|
def initialize
|
|
@foo = :ok
|
|
old_init
|
|
end
|
|
end
|
|
|
|
def test_method
|
|
assert_equal(:ok, C.new.foo, 'Bug #632 [ruby-core:19282]')
|
|
end
|
|
|
|
def test_ungetc_pos
|
|
b = '\\b00010001 \\B00010001 \\b1 \\B1 \\b000100011'
|
|
s = StringIO.new( b )
|
|
expected_pos = 0
|
|
while n = s.getc
|
|
assert_equal( expected_pos + 1, s.pos )
|
|
|
|
s.ungetc( n )
|
|
assert_equal( expected_pos, s.pos )
|
|
assert_equal( n, s.getc )
|
|
|
|
expected_pos += 1
|
|
end
|
|
end
|
|
|
|
def test_ungetc_padding
|
|
s = StringIO.new()
|
|
s.pos = 2
|
|
s.ungetc("a")
|
|
assert_equal("\0""a", s.string)
|
|
s.pos = 0
|
|
s.ungetc("b")
|
|
assert_equal("b""\0""a", s.string)
|
|
end
|
|
|
|
def test_ungetc_fill
|
|
count = 100
|
|
s = StringIO.new
|
|
s.print 'a' * count
|
|
s.ungetc('b' * (count * 5))
|
|
assert_equal((count * 5), s.string.size)
|
|
assert_match(/\Ab+\z/, s.string)
|
|
end
|
|
|
|
def test_ungetc_same_string
|
|
s = StringIO.new("abc" * 30)
|
|
s.ungetc(s.string)
|
|
assert_match(/\A(?:abc){60}\z/, s.string)
|
|
|
|
s = StringIO.new("abc" * 30)
|
|
s.pos = 70 # ("abc".size * 30 - 70).divmod(3) == [6, 2]
|
|
s.ungetc(s.string)
|
|
assert_match(/\A(?:abc){30}bc(?:abc){6}\z/, s.string)
|
|
end
|
|
|
|
def test_ungetbyte_pos
|
|
b = '\\b00010001 \\B00010001 \\b1 \\B1 \\b000100011'
|
|
s = StringIO.new( b )
|
|
expected_pos = 0
|
|
while n = s.getbyte
|
|
assert_equal( expected_pos + 1, s.pos )
|
|
|
|
s.ungetbyte( n )
|
|
assert_equal( expected_pos, s.pos )
|
|
assert_equal( n, s.getbyte )
|
|
|
|
expected_pos += 1
|
|
end
|
|
end
|
|
|
|
def test_ungetbyte_padding
|
|
s = StringIO.new()
|
|
s.pos = 2
|
|
s.ungetbyte("a".ord)
|
|
assert_equal("\0""a", s.string)
|
|
s.pos = 0
|
|
s.ungetbyte("b".ord)
|
|
assert_equal("b""\0""a", s.string)
|
|
end
|
|
|
|
def test_ungetbyte_fill
|
|
count = 100
|
|
s = StringIO.new
|
|
s.print 'a' * count
|
|
s.ungetbyte('b' * (count * 5))
|
|
assert_equal((count * 5), s.string.size)
|
|
assert_match(/\Ab+\z/, s.string)
|
|
end
|
|
|
|
def test_ungetbyte_same_string
|
|
s = StringIO.new("abc" * 30)
|
|
s.ungetc(s.string)
|
|
assert_match(/\A(?:abc){60}\z/, s.string)
|
|
|
|
s = StringIO.new("abc" * 30)
|
|
s.pos = 70 # ("abc".size * 30 - 70).divmod(3) == [6, 2]
|
|
s.ungetbyte(s.string)
|
|
assert_match(/\A(?:abc){30}bc(?:abc){6}\z/, s.string)
|
|
end
|
|
|
|
def test_frozen
|
|
s = StringIO.new
|
|
s.freeze
|
|
bug = '[ruby-core:33648]'
|
|
exception_class = defined?(FrozenError) ? FrozenError : RuntimeError
|
|
assert_raise(exception_class, bug) {s.puts("foo")}
|
|
assert_raise(exception_class, bug) {s.string = "foo"}
|
|
assert_raise(exception_class, bug) {s.reopen("")}
|
|
end
|
|
|
|
def test_frozen_string
|
|
s = StringIO.new("".freeze)
|
|
bug = '[ruby-core:48530]'
|
|
assert_raise(IOError, bug) {s.write("foo")}
|
|
assert_raise(IOError, bug) {s.ungetc("a")}
|
|
assert_raise(IOError, bug) {s.ungetbyte("a")}
|
|
end
|
|
|
|
def test_readlines_limit_0
|
|
assert_raise(ArgumentError, "[ruby-dev:43392]") { StringIO.new.readlines(0) }
|
|
end
|
|
|
|
def test_each_line_limit_0
|
|
assert_raise(ArgumentError, "[ruby-dev:43392]") { StringIO.new.each_line(0){} }
|
|
assert_raise(ArgumentError, "[ruby-dev:43392]") { StringIO.new.each_line("a",0){} }
|
|
end
|
|
|
|
def test_binmode
|
|
s = StringIO.new
|
|
s.set_encoding('utf-8')
|
|
assert_same s, s.binmode
|
|
|
|
bug_11945 = '[ruby-core:72699] [Bug #11945]'
|
|
assert_equal Encoding::ASCII_8BIT, s.external_encoding, bug_11945
|
|
end
|
|
|
|
def test_new_block_warning
|
|
assert_warn(/does not take block/) do
|
|
StringIO.new {}
|
|
end
|
|
end
|
|
|
|
def test_overflow
|
|
intptr_max = RbConfig::LIMITS["INTPTR_MAX"]
|
|
return if intptr_max > StringIO::MAX_LENGTH
|
|
limit = intptr_max - 0x10
|
|
assert_separately(%w[-rstringio], "#{<<-"begin;"}\n#{<<-"end;"}")
|
|
begin;
|
|
limit = #{limit}
|
|
ary = []
|
|
begin
|
|
x = "a"*0x100000
|
|
break if [x].pack("p").unpack("i!")[0] < 0
|
|
ary << x
|
|
end while ary.size <= 100
|
|
s = StringIO.new(x)
|
|
s.gets("xxx", limit)
|
|
assert_equal(0x100000, s.pos)
|
|
end;
|
|
end
|
|
|
|
def test_encoding_write
|
|
s = StringIO.new("", "w:utf-32be")
|
|
s.print "abc"
|
|
assert_equal("abc".encode("utf-32be"), s.string)
|
|
end
|
|
|
|
def test_encoding_read
|
|
s = StringIO.new("abc".encode("utf-32be"), "r:utf-8")
|
|
assert_equal("\0\0\0a\0\0\0b\0\0\0c", s.read)
|
|
end
|
|
|
|
%w/UTF-8 UTF-16BE UTF-16LE UTF-32BE UTF-32LE/.each do |name|
|
|
define_method("test_strip_bom:#{name}") do
|
|
text = "\uFEFF\u0100a"
|
|
content = text.encode(name)
|
|
result = StringIO.new(content, mode: 'rb:BOM|UTF-8').read
|
|
assert_equal(Encoding.find(name), result.encoding, name)
|
|
assert_equal(content[1..-1].b, result.b, name)
|
|
|
|
StringIO.open(content) {|f|
|
|
assert_equal(Encoding.find(name), f.set_encoding_by_bom)
|
|
}
|
|
end
|
|
end
|
|
|
|
def test_binary_encoding_read_and_default_internal
|
|
verbose, $VERBOSE = $VERBOSE, nil
|
|
default_internal = Encoding.default_internal
|
|
Encoding.default_internal = Encoding::UTF_8
|
|
$VERBOSE = verbose
|
|
assert_equal Encoding::BINARY, StringIO.new("Hello".b).read.encoding
|
|
ensure
|
|
$VERBOSE = nil
|
|
Encoding.default_internal = default_internal
|
|
$VERBOSE = verbose
|
|
end
|
|
|
|
def test_coderange_after_overwrite
|
|
s = StringIO.new("".b)
|
|
|
|
s.write("a=b&c=d")
|
|
s.rewind
|
|
assert_predicate(s.string, :ascii_only?)
|
|
s.write "\u{431 43e 433 443 441}"
|
|
assert_not_predicate(s.string, :ascii_only?)
|
|
|
|
s = StringIO.new("\u{3042}")
|
|
s.rewind
|
|
assert_not_predicate(s.string, :ascii_only?)
|
|
s.write('aaaa')
|
|
assert_predicate(s.string, :ascii_only?)
|
|
end
|
|
|
|
require "objspace"
|
|
if ObjectSpace.respond_to?(:dump) && ObjectSpace.dump(eval(%{"test"})).include?('"chilled":true') # Ruby 3.4+ chilled strings
|
|
def test_chilled_string
|
|
chilled_string = eval(%{""})
|
|
io = StringIO.new(chilled_string)
|
|
assert_warning(/literal string will be frozen/) { io << "test" }
|
|
assert_equal("test", io.string)
|
|
assert_same(chilled_string, io.string)
|
|
end
|
|
|
|
def test_chilled_string_string_set
|
|
io = StringIO.new
|
|
chilled_string = eval(%{""})
|
|
io.string = chilled_string
|
|
assert_warning(/literal string will be frozen/) { io << "test" }
|
|
assert_equal("test", io.string)
|
|
assert_same(chilled_string, io.string)
|
|
end
|
|
|
|
def test_chilled_string_set_enocoding
|
|
chilled_string = eval(%{""})
|
|
io = StringIO.new(chilled_string)
|
|
assert_warning("") { io.set_encoding(Encoding::BINARY) }
|
|
assert_same(chilled_string, io.string)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def assert_string(content, encoding, str, mesg = nil)
|
|
assert_equal([content, encoding], [str, str.encoding], mesg)
|
|
end
|
|
end
|