summaryrefslogtreecommitdiff
path: root/test/ruby/test_string.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_string.rb')
-rw-r--r--test/ruby/test_string.rb1625
1 files changed, 1437 insertions, 188 deletions
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 4d9d172ccf..6c00aa15f9 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -1,11 +1,11 @@
+# frozen_string_literal: false
require 'test/unit'
-require_relative 'envutil'
-
-# use of $= is deprecated after 1.7.1
-def pre_1_7_1
-end
class TestString < Test::Unit::TestCase
+ WIDE_ENCODINGS = [
+ Encoding::UTF_16BE, Encoding::UTF_16LE,
+ Encoding::UTF_32BE, Encoding::UTF_32LE,
+ ]
def initialize(*args)
@cls = String
@@ -15,12 +15,104 @@ class TestString < Test::Unit::TestCase
super
end
- def S(str)
- @cls.new(str)
+ def S(*args, **kw)
+ @cls.new(*args, **kw)
end
def test_s_new
- assert_equal("RUBY", S("RUBY"))
+ assert_equal("", S())
+ assert_equal(Encoding::ASCII_8BIT, S().encoding)
+
+ assert_equal("", S(""))
+ assert_equal(__ENCODING__, S("").encoding)
+
+ src = "RUBY"
+ assert_equal(src, S(src))
+ assert_equal(__ENCODING__, S(src).encoding)
+
+ src.force_encoding("euc-jp")
+ assert_equal(src, S(src))
+ assert_equal(Encoding::EUC_JP, S(src).encoding)
+
+
+ assert_equal("", S(encoding: "euc-jp"))
+ assert_equal(Encoding::EUC_JP, S(encoding: "euc-jp").encoding)
+
+ assert_equal("", S("", encoding: "euc-jp"))
+ assert_equal(Encoding::EUC_JP, S("", encoding: "euc-jp").encoding)
+
+ src = "RUBY"
+ assert_equal(src, S(src, encoding: "euc-jp"))
+ assert_equal(Encoding::EUC_JP, S(src, encoding: "euc-jp").encoding)
+
+ src.force_encoding("euc-jp")
+ assert_equal(src, S(src, encoding: "utf-8"))
+ assert_equal(Encoding::UTF_8, S(src, encoding: "utf-8").encoding)
+
+ assert_equal("", S(capacity: 1000))
+ assert_equal(Encoding::ASCII_8BIT, S(capacity: 1000).encoding)
+
+ assert_equal("", S(capacity: 1000, encoding: "euc-jp"))
+ assert_equal(Encoding::EUC_JP, S(capacity: 1000, encoding: "euc-jp").encoding)
+
+ assert_equal("", S("", capacity: 1000))
+ assert_equal(__ENCODING__, S("", capacity: 1000).encoding)
+
+ assert_equal("", S("", capacity: 1000, encoding: "euc-jp"))
+ assert_equal(Encoding::EUC_JP, S("", capacity: 1000, encoding: "euc-jp").encoding)
+ end
+
+ def test_initialize
+ str = S("").freeze
+ assert_equal("", str.__send__(:initialize))
+ assert_raise(FrozenError){ str.__send__(:initialize, 'abc') }
+ assert_raise(FrozenError){ str.__send__(:initialize, capacity: 1000) }
+ assert_raise(FrozenError){ str.__send__(:initialize, 'abc', capacity: 1000) }
+ assert_raise(FrozenError){ str.__send__(:initialize, encoding: 'euc-jp') }
+ assert_raise(FrozenError){ str.__send__(:initialize, 'abc', encoding: 'euc-jp') }
+ assert_raise(FrozenError){ str.__send__(:initialize, 'abc', capacity: 1000, encoding: 'euc-jp') }
+
+ str = S("")
+ assert_equal("mystring", str.__send__(:initialize, "mystring"))
+ str = S("mystring")
+ assert_equal("mystring", str.__send__(:initialize, str))
+ str = S("")
+ assert_equal("mystring", str.__send__(:initialize, "mystring", capacity: 1000))
+ str = S("mystring")
+ assert_equal("mystring", str.__send__(:initialize, str, capacity: 1000))
+ end
+
+ def test_initialize_shared
+ String.new(str = "mystring" * 10).__send__(:initialize, capacity: str.bytesize)
+ assert_equal("mystring", str[0, 8])
+ end
+
+ def test_initialize_nonstring
+ assert_raise(TypeError) {
+ S(1)
+ }
+ assert_raise(TypeError) {
+ S(1, capacity: 1000)
+ }
+ end
+
+ def test_initialize_memory_leak
+ assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
+code = proc {('x'*100000).__send__(:initialize, '')}
+1_000.times(&code)
+PREP
+100_000.times(&code)
+CODE
+ end
+
+ # Bug #18154
+ def test_initialize_nofree_memory_leak
+ assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
+code = proc {0.to_s.__send__(:initialize, capacity: 10000)}
+1_000.times(&code)
+PREP
+100_000.times(&code)
+CODE
end
def test_AREF # '[]'
@@ -126,20 +218,6 @@ class TestString < Test::Unit::TestCase
s[S("Foo")] = S("Bar")
assert_equal(S("BarBar"), s)
- pre_1_7_1 do
- s = S("FooBar")
- s[S("Foo")] = S("xyz")
- assert_equal(S("xyzBar"), s)
-
- $= = true
- s = S("FooBar")
- s[S("FOO")] = S("Bar")
- assert_equal(S("BarBar"), s)
- s[S("FOO")] = S("xyz")
- assert_equal(S("BarBar"), s)
- $= = false
- end
-
s = S("a string")
s[0..s.size] = S("another string")
assert_equal(S("another string"), s)
@@ -151,6 +229,8 @@ class TestString < Test::Unit::TestCase
assert_equal("fobar", s)
assert_raise(ArgumentError) { "foo"[1, 2, 3] = "" }
+
+ assert_raise(IndexError) {"foo"[RbConfig::LIMITS["LONG_MIN"]] = "l"}
end
def test_CMP # '<=>'
@@ -160,18 +240,13 @@ class TestString < Test::Unit::TestCase
assert_equal(-1, S("ABCDEF") <=> S("abcdef"))
- pre_1_7_1 do
- $= = true
- assert_equal(0, S("ABCDEF") <=> S("abcdef"))
- $= = false
- end
-
assert_nil("foo" <=> Object.new)
o = Object.new
def o.to_str; "bar"; end
- assert_nil("foo" <=> o)
+ assert_equal(1, "foo" <=> o)
+ class << o;remove_method :to_str;end
def o.<=>(x); nil; end
assert_nil("foo" <=> o)
@@ -181,22 +256,16 @@ class TestString < Test::Unit::TestCase
class << o;remove_method :<=>;end
def o.<=>(x); 2**100; end
- assert_equal(-(2**100), "foo" <=> o)
+ assert_equal(-1, "foo" <=> o)
end
def test_EQUAL # '=='
- assert_equal(false, S("foo") == :foo)
- assert(S("abcdef") == S("abcdef"))
-
- pre_1_7_1 do
- $= = true
- assert(S("CAT") == S('cat'))
- assert(S("CaT") == S('cAt'))
- $= = false
- end
+ assert_not_equal(:foo, S("foo"))
+ assert_equal(S("abcdef"), S("abcdef"))
- assert(S("CAT") != S('cat'))
- assert(S("CaT") != S('cAt'))
+ assert_not_equal(S("CAT"), S('cat'))
+ assert_not_equal(S("CaT"), S('cAt'))
+ assert_not_equal(S("cat\0""dog"), S("cat\0"))
o = Object.new
def o.to_str; end
@@ -209,7 +278,7 @@ class TestString < Test::Unit::TestCase
def test_LSHIFT # '<<'
assert_equal(S("world!"), S("world") << 33)
- assert_equal(S("world!"), S("world") << S('!'))
+ assert_equal(S("world!"), S("world") << S("!"))
s = "a"
10.times {|i|
@@ -234,12 +303,6 @@ class TestString < Test::Unit::TestCase
assert_equal(10, S("FeeFieFoo-Fum") =~ /Fum$/)
assert_equal(nil, S("FeeFieFoo-Fum") =~ /FUM$/)
- pre_1_7_1 do
- $= = true
- assert_equal(10, S("FeeFieFoo-Fum") =~ /FUM$/)
- $= = false
- end
-
o = Object.new
def o.=~(x); x + "bar"; end
assert_equal("foobar", S("foo") =~ o)
@@ -278,11 +341,12 @@ class TestString < Test::Unit::TestCase
end
def casetest(a, b, rev=false)
+ msg = proc {"#{a} should#{' not' if rev} match #{b}"}
case a
- when b
- assert(!rev)
- else
- assert(rev)
+ when b
+ assert(!rev, msg)
+ else
+ assert(rev, msg)
end
end
@@ -290,13 +354,6 @@ class TestString < Test::Unit::TestCase
# assert_equal(true, S("foo") === :foo)
casetest(S("abcdef"), S("abcdef"))
- pre_1_7_1 do
- $= = true
- casetest(S("CAT"), S('cat'))
- casetest(S("CaT"), S('cAt'))
- $= = false
- end
-
casetest(S("CAT"), S('cat'), true) # Reverse the test - we don't want to
casetest(S("CaT"), S('cAt'), true) # find these in the case.
end
@@ -339,6 +396,8 @@ class TestString < Test::Unit::TestCase
end
def test_chomp
+ verbose, $VERBOSE = $VERBOSE, nil
+
assert_equal(S("hello"), S("hello").chomp("\n"))
assert_equal(S("hello"), S("hello\n").chomp("\n"))
save = $/
@@ -354,9 +413,62 @@ class TestString < Test::Unit::TestCase
$/ = save
assert_equal(S("a").hash, S("a\u0101").chomp(S("\u0101")).hash, '[ruby-core:22414]')
+
+ s = S("hello")
+ assert_equal("hel", s.chomp('lo'))
+ assert_equal("hello", s)
+
+ s = S("hello")
+ assert_equal("hello", s.chomp('he'))
+ assert_equal("hello", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal("\u{3053 3093 306b}", s.chomp("\u{3061 306f}"))
+ assert_equal("\u{3053 3093 306b 3061 306f}", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal("\u{3053 3093 306b 3061 306f}", s.chomp('lo'))
+ assert_equal("\u{3053 3093 306b 3061 306f}", s)
+
+ s = S("hello")
+ assert_equal("hello", s.chomp("\u{3061 306f}"))
+ assert_equal("hello", s)
+
+ # skip if argument is a broken string
+ s = S("\xe3\x81\x82")
+ assert_equal("\xe3\x81\x82", s.chomp("\x82"))
+ assert_equal("\xe3\x81\x82", s)
+
+ s = S("\x95\x5c").force_encoding("Shift_JIS")
+ assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s.chomp("\x5c"))
+ assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s)
+
+ # clear coderange
+ s = S("hello\u{3053 3093}")
+ assert_not_predicate(s, :ascii_only?)
+ assert_predicate(s.chomp("\u{3053 3093}"), :ascii_only?)
+
+ # argument should be converted to String
+ klass = Class.new { def to_str; 'a'; end }
+ s = S("abba")
+ assert_equal("abb", s.chomp(klass.new))
+ assert_equal("abba", s)
+
+ # chomp removes any of "\n", "\r\n", "\r" when "\n" is specified
+ s = "foo\n"
+ assert_equal("foo", s.chomp("\n"))
+ s = "foo\r\n"
+ assert_equal("foo", s.chomp("\n"))
+ s = "foo\r"
+ assert_equal("foo", s.chomp("\n"))
+ ensure
+ $/ = save
+ $VERBOSE = verbose
end
def test_chomp!
+ verbose, $VERBOSE = $VERBOSE, nil
+
a = S("hello")
a.chomp!(S("\n"))
@@ -410,6 +522,70 @@ class TestString < Test::Unit::TestCase
assert_equal("foo\r", s)
assert_equal(S("a").hash, S("a\u0101").chomp!(S("\u0101")).hash, '[ruby-core:22414]')
+
+ s = S("").freeze
+ assert_raise_with_message(FrozenError, /frozen/) {s.chomp!}
+ $VERBOSE = nil # EnvUtil.suppress_warning resets $VERBOSE to the original state
+
+ s = S("ax")
+ o = Struct.new(:s).new(s)
+ def o.to_str
+ s.freeze
+ "x"
+ end
+ assert_raise_with_message(FrozenError, /frozen/) {s.chomp!(o)}
+ $VERBOSE = nil # EnvUtil.suppress_warning resets $VERBOSE to the original state
+
+ s = S("hello")
+ assert_equal("hel", s.chomp!('lo'))
+ assert_equal("hel", s)
+
+ s = S("hello")
+ assert_equal(nil, s.chomp!('he'))
+ assert_equal("hello", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal("\u{3053 3093 306b}", s.chomp!("\u{3061 306f}"))
+ assert_equal("\u{3053 3093 306b}", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal(nil, s.chomp!('lo'))
+ assert_equal("\u{3053 3093 306b 3061 306f}", s)
+
+ s = S("hello")
+ assert_equal(nil, s.chomp!("\u{3061 306f}"))
+ assert_equal("hello", s)
+
+ # skip if argument is a broken string
+ s = S("\xe3\x81\x82")
+ assert_equal(nil, s.chomp!("\x82"))
+ assert_equal("\xe3\x81\x82", s)
+
+ s = S("\x95\x5c").force_encoding("Shift_JIS")
+ assert_equal(nil, s.chomp!("\x5c"))
+ assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s)
+
+ # clear coderange
+ s = S("hello\u{3053 3093}")
+ assert_not_predicate(s, :ascii_only?)
+ assert_predicate(s.chomp!("\u{3053 3093}"), :ascii_only?)
+
+ # argument should be converted to String
+ klass = Class.new { def to_str; 'a'; end }
+ s = S("abba")
+ assert_equal("abb", s.chomp!(klass.new))
+ assert_equal("abb", s)
+
+ # chomp removes any of "\n", "\r\n", "\r" when "\n" is specified
+ s = "foo\n"
+ assert_equal("foo", s.chomp!("\n"))
+ s = "foo\r\n"
+ assert_equal("foo", s.chomp!("\n"))
+ s = "foo\r"
+ assert_equal("foo", s.chomp!("\n"))
+ ensure
+ $/ = save
+ $VERBOSE = verbose
end
def test_chop
@@ -448,31 +624,37 @@ class TestString < Test::Unit::TestCase
end
def test_clone
- for taint in [ false, true ]
- for untrust in [ false, true ]
- for frozen in [ false, true ]
- a = S("Cool")
- a.taint if taint
- a.untrust if untrust
- a.freeze if frozen
- b = a.clone
-
- assert_equal(a, b)
- assert(a.__id__ != b.__id__)
- assert_equal(a.frozen?, b.frozen?)
- assert_equal(a.untrusted?, b.untrusted?)
- assert_equal(a.tainted?, b.tainted?)
- end
- end
+ for frozen in [ false, true ]
+ a = S("Cool")
+ a.freeze if frozen
+ b = a.clone
+
+ assert_equal(a, b)
+ assert_not_same(a, b)
+ assert_equal(a.frozen?, b.frozen?)
end
- null = File.exist?("/dev/null") ? "/dev/null" : "NUL" # maybe DOSISH
- assert_equal("", File.read(null).clone, '[ruby-dev:32819] reported by Kazuhiro NISHIYAMA')
+ assert_equal("", File.read(IO::NULL).clone, '[ruby-dev:32819] reported by Kazuhiro NISHIYAMA')
end
def test_concat
assert_equal(S("world!"), S("world").concat(33))
assert_equal(S("world!"), S("world").concat(S('!')))
+ b = S("sn")
+ assert_equal(S("snsnsn"), b.concat(b, b))
+
+ bug7090 = '[ruby-core:47751]'
+ result = S("").force_encoding(Encoding::UTF_16LE)
+ result << 0x0300
+ expected = S("\u0300".encode(Encoding::UTF_16LE))
+ assert_equal(expected, result, bug7090)
+ assert_raise(TypeError) { 'foo' << :foo }
+ assert_raise(FrozenError) { 'foo'.freeze.concat('bar') }
+ end
+
+ def test_concat_literals
+ s="." * 50
+ assert_equal(Encoding::UTF_8, "#{s}x".encoding)
end
def test_count
@@ -483,15 +665,50 @@ class TestString < Test::Unit::TestCase
assert_equal(4, a.count(S("ej-m")))
assert_equal(0, S("y").count(S("a\\-z")))
assert_equal(5, "abc\u{3042 3044 3046}".count("^a"))
+ assert_equal(1, "abc\u{3042 3044 3046}".count("\u3042"))
assert_equal(5, "abc\u{3042 3044 3046}".count("^\u3042"))
assert_equal(2, "abc\u{3042 3044 3046}".count("a-z", "^a"))
+ assert_equal(0, "abc\u{3042 3044 3046}".count("a", "\u3042"))
+ assert_equal(0, "abc\u{3042 3044 3046}".count("\u3042", "a"))
+ assert_equal(0, "abc\u{3042 3044 3046}".count("\u3042", "\u3044"))
+ assert_equal(4, "abc\u{3042 3044 3046}".count("^a", "^\u3044"))
+ assert_equal(4, "abc\u{3042 3044 3046}".count("^\u3044", "^a"))
+ assert_equal(4, "abc\u{3042 3044 3046}".count("^\u3042", "^\u3044"))
assert_raise(ArgumentError) { "foo".count }
end
+ def crypt_supports_des_crypt?
+ /openbsd/ !~ RUBY_PLATFORM
+ end
+
def test_crypt
- assert_equal(S('aaGUC/JkO9/Sc'), S("mypassword").crypt(S("aa")))
- assert(S('aaGUC/JkO9/Sc') != S("mypassword").crypt(S("ab")))
+ if crypt_supports_des_crypt?
+ pass = "aaGUC/JkO9/Sc"
+ good_salt = "aa"
+ bad_salt = "ab"
+ else
+ pass = "$2a$04$0WVaz0pV3jzfZ5G5tpmHWuBQGbkjzgtSc3gJbmdy0GAGMa45MFM2."
+ good_salt = "$2a$04$0WVaz0pV3jzfZ5G5tpmHWu"
+ bad_salt = "$2a$04$0WVaz0pV3jzfZ5G5tpmHXu"
+ end
+ assert_equal(S(pass), S("mypassword").crypt(S(good_salt)))
+ assert_not_equal(S(pass), S("mypassword").crypt(S(bad_salt)))
+ assert_raise(ArgumentError) {S("mypassword").crypt(S(""))}
+ assert_raise(ArgumentError) {S("mypassword").crypt(S("\0a"))}
+ assert_raise(ArgumentError) {S("mypassword").crypt(S("a\0"))}
+ assert_raise(ArgumentError) {S("poison\u0000null").crypt(S("aa"))}
+ WIDE_ENCODINGS.each do |enc|
+ assert_raise(ArgumentError) {S("mypassword").crypt(S("aa".encode(enc)))}
+ assert_raise(ArgumentError) {S("mypassword".encode(enc)).crypt(S("aa"))}
+ end
+
+ @cls == String and
+ assert_no_memory_leak([], "s = ''; salt_proc = proc{#{(crypt_supports_des_crypt? ? '..' : good_salt).inspect}}", "#{<<~"begin;"}\n#{<<~'end;'}")
+
+ begin;
+ 1000.times { s.crypt(-salt_proc.call).clear }
+ end;
end
def test_delete
@@ -503,11 +720,14 @@ class TestString < Test::Unit::TestCase
assert_equal("a".hash, "a\u0101".delete("\u0101").hash, '[ruby-talk:329267]')
assert_equal(true, "a\u0101".delete("\u0101").ascii_only?)
assert_equal(true, "a\u3041".delete("\u3041").ascii_only?)
- assert_equal(false, "a\u3041\u3042".tr("\u3041", "a").ascii_only?)
+ assert_equal(false, "a\u3041\u3042".delete("\u3041").ascii_only?)
assert_equal("a", "abc\u{3042 3044 3046}".delete("^a"))
assert_equal("bc\u{3042 3044 3046}", "abc\u{3042 3044 3046}".delete("a"))
assert_equal("\u3042", "abc\u{3042 3044 3046}".delete("^\u3042"))
+
+ bug6160 = '[ruby-dev:45374]'
+ assert_equal("", '\\'.delete('\\'), bug6160)
end
def test_delete!
@@ -549,6 +769,7 @@ class TestString < Test::Unit::TestCase
assert_equal(S("hello"), S("hello").downcase)
assert_equal(S("hello"), S("HELLO").downcase)
assert_equal(S("abc hello 123"), S("abc HELLO 123").downcase)
+ assert_equal(S("h\0""ello"), S("h\0""ELLO").downcase)
end
def test_downcase!
@@ -561,34 +782,110 @@ class TestString < Test::Unit::TestCase
a=S("hello")
assert_nil(a.downcase!)
assert_equal(S("hello"), a)
+
+ a = S("h\0""ELLO")
+ b = a.dup
+ assert_equal(S("h\0""ello"), a.downcase!)
+ assert_equal(S("h\0""ello"), a)
+ assert_equal(S("h\0""ELLO"), b)
end
def test_dump
a= S("Test") << 1 << 2 << 3 << 9 << 13 << 10
assert_equal(S('"Test\\x01\\x02\\x03\\t\\r\\n"'), a.dump)
+ b= S("\u{7F}")
+ assert_equal(S('"\\x7F"'), b.dump)
+ b= S("\u{AB}")
+ assert_equal(S('"\\u00AB"'), b.dump)
+ b= S("\u{ABC}")
+ assert_equal(S('"\\u0ABC"'), b.dump)
+ b= S("\uABCD")
+ assert_equal(S('"\\uABCD"'), b.dump)
+ b= S("\u{ABCDE}")
+ assert_equal(S('"\\u{ABCDE}"'), b.dump)
+ b= S("\u{10ABCD}")
+ assert_equal(S('"\\u{10ABCD}"'), b.dump)
+ end
+
+ def test_undump
+ a = S("Test") << 1 << 2 << 3 << 9 << 13 << 10
+ assert_equal(a, S('"Test\\x01\\x02\\x03\\t\\r\\n"').undump)
+ assert_equal(S("\\ca"), S('"\\ca"').undump)
+ assert_equal(S("\u{7F}"), S('"\\x7F"').undump)
+ assert_equal(S("\u{7F}A"), S('"\\x7FA"').undump)
+ assert_equal(S("\u{AB}"), S('"\\u00AB"').undump)
+ assert_equal(S("\u{ABC}"), S('"\\u0ABC"').undump)
+ assert_equal(S("\uABCD"), S('"\\uABCD"').undump)
+ assert_equal(S("\uABCD"), S('"\\uABCD"').undump)
+ assert_equal(S("\u{ABCDE}"), S('"\\u{ABCDE}"').undump)
+ assert_equal(S("\u{10ABCD}"), S('"\\u{10ABCD}"').undump)
+ assert_equal(S("\u{ABCDE 10ABCD}"), S('"\\u{ABCDE 10ABCD}"').undump)
+ assert_equal(S(""), S('"\\u{}"').undump)
+ assert_equal(S(""), S('"\\u{ }"').undump)
+
+ assert_equal(S("\u3042".encode("sjis")), S('"\x82\xA0"'.force_encoding("sjis")).undump)
+ assert_equal(S("\u8868".encode("sjis")), S("\"\\x95\\\\\"".force_encoding("sjis")).undump)
+
+ assert_equal(S("äöü"), S('"\u00E4\u00F6\u00FC"').undump)
+ assert_equal(S("äöü"), S('"\xC3\xA4\xC3\xB6\xC3\xBC"').undump)
+
+ assert_equal(Encoding::UTF_8, S('"\\u3042"').encode(Encoding::EUC_JP).undump.encoding)
+
+ assert_equal("abc".encode(Encoding::UTF_16LE),
+ '"a\x00b\x00c\x00".force_encoding("UTF-16LE")'.undump)
+
+ assert_equal('\#', '"\\\\#"'.undump)
+ assert_equal('\#{', '"\\\\\#{"'.undump)
+
+ assert_raise(RuntimeError) { S('\u3042').undump }
+ assert_raise(RuntimeError) { S('"\x82\xA0\u3042"'.force_encoding("SJIS")).undump }
+ assert_raise(RuntimeError) { S('"\u3042\x82\xA0"'.force_encoding("SJIS")).undump }
+ assert_raise(RuntimeError) { S('"".force_encoding()').undump }
+ assert_raise(RuntimeError) { S('"".force_encoding("').undump }
+ assert_raise(RuntimeError) { S('"".force_encoding("UNKNOWN")').undump }
+ assert_raise(RuntimeError) { S('"\u3042".force_encoding("UTF-16LE")').undump }
+ assert_raise(RuntimeError) { S('"\x00\x00".force_encoding("UTF-16LE")"').undump }
+ assert_raise(RuntimeError) { S('"\x00\x00".force_encoding("'+("a"*9999999)+'")"').undump }
+ assert_raise(RuntimeError) { S(%("\u00E4")).undump }
+ assert_raise(RuntimeError) { S('"').undump }
+ assert_raise(RuntimeError) { S('"""').undump }
+ assert_raise(RuntimeError) { S('""""').undump }
+
+ assert_raise(RuntimeError) { S('"a').undump }
+ assert_raise(RuntimeError) { S('"\u"').undump }
+ assert_raise(RuntimeError) { S('"\u{"').undump }
+ assert_raise(RuntimeError) { S('"\u304"').undump }
+ assert_raise(RuntimeError) { S('"\u304Z"').undump }
+ assert_raise(RuntimeError) { S('"\udfff"').undump }
+ assert_raise(RuntimeError) { S('"\u{dfff}"').undump }
+ assert_raise(RuntimeError) { S('"\u{3042"').undump }
+ assert_raise(RuntimeError) { S('"\u{3042 "').undump }
+ assert_raise(RuntimeError) { S('"\u{110000}"').undump }
+ assert_raise(RuntimeError) { S('"\u{1234567}"').undump }
+ assert_raise(RuntimeError) { S('"\x"').undump }
+ assert_raise(RuntimeError) { S('"\xA"').undump }
+ assert_raise(RuntimeError) { S('"\\"').undump }
+ assert_raise(RuntimeError) { S(%("\0")).undump }
+ assert_raise_with_message(RuntimeError, /invalid/) {
+ '"\\u{007F}".xxxxxx'.undump
+ }
end
def test_dup
- for taint in [ false, true ]
- for untrust in [ false, true ]
- for frozen in [ false, true ]
- a = S("hello")
- a.taint if taint
- a.untrust if untrust
- a.freeze if frozen
- b = a.dup
-
- assert_equal(a, b)
- assert(a.__id__ != b.__id__)
- assert(!b.frozen?)
- assert_equal(a.tainted?, b.tainted?)
- assert_equal(a.untrusted?, b.untrusted?)
- end
- end
+ for frozen in [ false, true ]
+ a = S("hello")
+ a.freeze if frozen
+ b = a.dup
+
+ assert_equal(a, b)
+ assert_not_same(a, b)
+ assert_not_predicate(b, :frozen?)
end
end
def test_each
+ verbose, $VERBOSE = $VERBOSE, nil
+
save = $/
$/ = "\n"
res=[]
@@ -598,61 +895,302 @@ class TestString < Test::Unit::TestCase
res=[]
S("hello\n\n\nworld").lines(S('')).each {|x| res << x}
- assert_equal(S("hello\n\n\n"), res[0])
- assert_equal(S("world"), res[1])
+ assert_equal(S("hello\n\n"), res[0])
+ assert_equal(S("world"), res[1])
$/ = "!"
res=[]
S("hello!world").lines.each {|x| res << x}
assert_equal(S("hello!"), res[0])
assert_equal(S("world"), res[1])
+ ensure
$/ = save
+ $VERBOSE = verbose
end
def test_each_byte
+ s = S("ABC")
+
+ res = []
+ assert_equal s.object_id, s.each_byte {|x| res << x }.object_id
+ assert_equal(65, res[0])
+ assert_equal(66, res[1])
+ assert_equal(67, res[2])
+
+ assert_equal 65, s.each_byte.next
+ end
+
+ def test_bytes
+ s = S("ABC")
+ assert_equal [65, 66, 67], s.bytes
+
res = []
- S("ABC").each_byte {|x| res << x }
+ assert_equal s.object_id, s.bytes {|x| res << x }.object_id
assert_equal(65, res[0])
assert_equal(66, res[1])
assert_equal(67, res[2])
+ s = S("ABC")
+ res = []
+ assert_same s, s.bytes {|x| res << x }
+ assert_equal [65, 66, 67], res
+ end
+
+ def test_each_codepoint
+ # Single byte optimization
+ assert_equal 65, S("ABC").each_codepoint.next
+
+ s = S("\u3042\u3044\u3046")
+
+ res = []
+ assert_equal s.object_id, s.each_codepoint {|x| res << x }.object_id
+ assert_equal(0x3042, res[0])
+ assert_equal(0x3044, res[1])
+ assert_equal(0x3046, res[2])
+
+ assert_equal 0x3042, s.each_codepoint.next
+ end
+
+ def test_codepoints
+ # Single byte optimization
+ assert_equal [65, 66, 67], S("ABC").codepoints
+
+ s = S("\u3042\u3044\u3046")
+ assert_equal [0x3042, 0x3044, 0x3046], s.codepoints
+
+ res = []
+ assert_equal s.object_id, s.codepoints {|x| res << x }.object_id
+ assert_equal(0x3042, res[0])
+ assert_equal(0x3044, res[1])
+ assert_equal(0x3046, res[2])
+ s = S("ABC")
+ res = []
+ assert_same s, s.codepoints {|x| res << x }
+ assert_equal [65, 66, 67], res
+ end
+
+ def test_each_char
+ s = S("ABC")
+
+ res = []
+ assert_equal s.object_id, s.each_char {|x| res << x }.object_id
+ assert_equal("A", res[0])
+ assert_equal("B", res[1])
+ assert_equal("C", res[2])
+
+ assert_equal "A", S("ABC").each_char.next
+ end
+
+ def test_chars
+ s = S("ABC")
+ assert_equal ["A", "B", "C"], s.chars
+
+ res = []
+ assert_equal s.object_id, s.chars {|x| res << x }.object_id
+ assert_equal("A", res[0])
+ assert_equal("B", res[1])
+ assert_equal("C", res[2])
+ end
+
+ def test_each_grapheme_cluster
+ [
+ "\u{0D 0A}",
+ "\u{20 200d}",
+ "\u{600 600}",
+ "\u{600 20}",
+ "\u{261d 1F3FB}",
+ "\u{1f600}",
+ "\u{20 308}",
+ "\u{1F477 1F3FF 200D 2640 FE0F}",
+ "\u{1F468 200D 1F393}",
+ "\u{1F46F 200D 2642 FE0F}",
+ "\u{1f469 200d 2764 fe0f 200d 1f469}",
+ ].each do |g|
+ assert_equal [g], g.each_grapheme_cluster.to_a
+ assert_equal 1, g.each_grapheme_cluster.size
+ end
+
+ [
+ ["\u{a 324}", ["\u000A", "\u0324"]],
+ ["\u{d 324}", ["\u000D", "\u0324"]],
+ ["abc", ["a", "b", "c"]],
+ ].each do |str, grapheme_clusters|
+ assert_equal grapheme_clusters, str.each_grapheme_cluster.to_a
+ assert_equal grapheme_clusters.size, str.each_grapheme_cluster.size
+ end
+
+ s = ("x"+"\u{10ABCD}"*250000)
+ assert_empty(s.each_grapheme_cluster {s.clear})
+ end
+
+ def test_grapheme_clusters
+ [
+ "\u{20 200d}",
+ "\u{600 600}",
+ "\u{600 20}",
+ "\u{261d 1F3FB}",
+ "\u{1f600}",
+ "\u{20 308}",
+ "\u{1F477 1F3FF 200D 2640 FE0F}",
+ "\u{1F468 200D 1F393}",
+ "\u{1F46F 200D 2642 FE0F}",
+ "\u{1f469 200d 2764 fe0f 200d 1f469}",
+ ].product([Encoding::UTF_8, *WIDE_ENCODINGS]) do |g, enc|
+ g = g.encode(enc)
+ assert_equal [g], g.grapheme_clusters
+ end
+
+ [
+ "\u{a 324}",
+ "\u{d 324}",
+ "abc",
+ ].product([Encoding::UTF_8, *WIDE_ENCODINGS]) do |g, enc|
+ g = g.encode(enc)
+ assert_equal g.chars, g.grapheme_clusters
+ end
+ assert_equal ["a", "b", "c"], "abc".b.grapheme_clusters
+
+ s = "ABC".b
+ res = []
+ assert_same s, s.grapheme_clusters {|x| res << x }
+ assert_equal(3, res.size)
+ assert_equal("A", res[0])
+ assert_equal("B", res[1])
+ assert_equal("C", res[2])
end
def test_each_line
+ verbose, $VERBOSE = $VERBOSE, nil
+
save = $/
$/ = "\n"
res=[]
- S("hello\nworld").lines.each {|x| res << x}
+ S("hello\nworld").each_line {|x| res << x}
assert_equal(S("hello\n"), res[0])
assert_equal(S("world"), res[1])
res=[]
- S("hello\n\n\nworld").lines(S('')).each {|x| res << x}
- assert_equal(S("hello\n\n\n"), res[0])
- assert_equal(S("world"), res[1])
+ S("hello\n\n\nworld").each_line(S('')) {|x| res << x}
+ assert_equal(S("hello\n\n"), res[0])
+ assert_equal(S("world"), res[1])
+
+ res=[]
+ S("hello\r\n\r\nworld").each_line(S('')) {|x| res << x}
+ assert_equal(S("hello\r\n\r\n"), res[0])
+ assert_equal(S("world"), res[1])
$/ = "!"
res=[]
- S("hello!world").lines.each {|x| res << x}
+ S("hello!world").each_line {|x| res << x}
assert_equal(S("hello!"), res[0])
assert_equal(S("world"), res[1])
+ $/ = "ab"
+
+ res=[]
+ S("a").lines.each {|x| res << x}
+ assert_equal(1, res.size)
+ assert_equal(S("a"), res[0])
+
$/ = save
s = nil
"foo\nbar".each_line(nil) {|s2| s = s2 }
assert_equal("foo\nbar", s)
+
+ assert_equal "hello\n", S("hello\nworld").each_line.next
+ assert_equal "hello\nworld", S("hello\nworld").each_line(nil).next
+
+ bug7646 = "[ruby-dev:46827]"
+ assert_nothing_raised(bug7646) do
+ "\n\u0100".each_line("\n") {}
+ end
+ ensure
+ $/ = save
+ $VERBOSE = verbose
+ end
+
+ def test_each_line_chomp
+ res = []
+ S("hello\nworld").each_line("\n", chomp: true) {|x| res << x}
+ assert_equal(S("hello"), res[0])
+ assert_equal(S("world"), res[1])
+
+ res = []
+ S("hello\n\n\nworld").each_line(S(''), chomp: true) {|x| res << x}
+ assert_equal(S("hello\n"), res[0])
+ assert_equal(S("world"), res[1])
+
+ res = []
+ S("hello\r\n\r\nworld").each_line(S(''), chomp: true) {|x| res << x}
+ assert_equal(S("hello\r\n"), res[0])
+ assert_equal(S("world"), res[1])
+
+ res = []
+ S("hello!world").each_line(S('!'), chomp: true) {|x| res << x}
+ assert_equal(S("hello"), res[0])
+ assert_equal(S("world"), res[1])
+
+ res = []
+ S("a").each_line(S('ab'), chomp: true).each {|x| res << x}
+ assert_equal(1, res.size)
+ assert_equal(S("a"), res[0])
+
+ s = nil
+ "foo\nbar".each_line(nil, chomp: true) {|s2| s = s2 }
+ assert_equal("foo\nbar", s)
+
+ assert_equal "hello", S("hello\nworld").each_line(chomp: true).next
+ assert_equal "hello\nworld", S("hello\nworld").each_line(nil, chomp: true).next
+
+ res = []
+ S("").each_line(chomp: true) {|x| res << x}
+ assert_equal([], res)
+
+ res = []
+ S("\n").each_line(chomp: true) {|x| res << x}
+ assert_equal([S("")], res)
+
+ res = []
+ S("\r\n").each_line(chomp: true) {|x| res << x}
+ assert_equal([S("")], res)
+
+ res = []
+ S("a\n b\n").each_line(" ", chomp: true) {|x| res << x}
+ assert_equal([S("a\n"), S("b\n")], res)
+ end
+
+ def test_lines
+ s = S("hello\nworld")
+ assert_equal ["hello\n", "world"], s.lines
+ assert_equal ["hello\nworld"], s.lines(nil)
+
+ res = []
+ assert_equal s.object_id, s.lines {|x| res << x }.object_id
+ assert_equal(S("hello\n"), res[0])
+ assert_equal(S("world"), res[1])
end
def test_empty?
- assert(S("").empty?)
- assert(!S("not").empty?)
+ assert_empty(S(""))
+ assert_not_empty(S("not"))
+ end
+
+ def test_end_with?
+ assert_send([S("hello"), :end_with?, S("llo")])
+ assert_not_send([S("hello"), :end_with?, S("ll")])
+ assert_send([S("hello"), :end_with?, S("el"), S("lo")])
+ assert_send([S("hello"), :end_with?, S("")])
+ assert_not_send([S("hello"), :end_with?])
+
+ bug5536 = '[ruby-core:40623]'
+ assert_raise(TypeError, bug5536) {S("str").end_with? :not_convertible_to_string}
end
def test_eql?
a = S("hello")
- assert(a.eql?(S("hello")))
- assert(a.eql?(a))
+ assert_operator(a, :eql?, S("hello"))
+ assert_operator(a, :eql?, a)
end
def test_gsub
@@ -662,12 +1200,7 @@ class TestString < Test::Unit::TestCase
S("hello").gsub(/./) { |s| s[0].to_s + S(' ')})
assert_equal(S("HELL-o"),
S("hello").gsub(/(hell)(.)/) { |s| $1.upcase + S('-') + $2 })
-
- a = S("hello")
- a.taint
- a.untrust
- assert(a.gsub(/./, S('X')).tainted?)
- assert(a.gsub(/./, S('X')).untrusted?)
+ assert_equal(S("<>h<>e<>l<>l<>o<>"), S("hello").gsub(S(''), S('<\0>')))
assert_equal("z", "abc".gsub(/./, "a" => "z"), "moved from btest/knownbug")
@@ -687,6 +1220,11 @@ class TestString < Test::Unit::TestCase
c.force_encoding Encoding::US_ASCII
assert_equal Encoding::UTF_8, a.gsub(/world/, c).encoding
+
+ assert_equal S("a\u{e9}apos&lt;"), S("a\u{e9}'&lt;").gsub("'", "apos")
+
+ bug9849 = '[ruby-core:62669] [Bug #9849]'
+ assert_equal S("\u{3042 3042 3042}!foo!"), S("\u{3042 3042 3042}/foo/").gsub("/", "!"), bug9849
end
def test_gsub!
@@ -708,13 +1246,6 @@ class TestString < Test::Unit::TestCase
a.gsub!(/(hell)(.)/) { |s| $1.upcase + S('-') + $2 }
assert_equal(S("HELL-o"), a)
- r = S('X')
- r.taint
- r.untrust
- a.gsub!(/./, r)
- assert(a.tainted?)
- assert(a.untrusted?)
-
a = S("hello")
assert_nil(a.sub!(S('X'), S('Y')))
end
@@ -741,21 +1272,11 @@ class TestString < Test::Unit::TestCase
def test_hash
assert_equal(S("hello").hash, S("hello").hash)
- assert(S("hello").hash != S("helLO").hash)
+ assert_not_equal(S("hello").hash, S("helLO").hash)
bug4104 = '[ruby-core:33500]'
assert_not_equal(S("a").hash, S("a\0").hash, bug4104)
- end
-
- def test_hash_random
- str = 'abc'
- a = [str.hash.to_s]
- 3.times {
- assert_in_out_err(["-e", "print #{str.dump}.hash"], "") do |r, e|
- a += r
- assert_equal([], e)
- end
- }
- assert_not_equal([str.hash.to_s], a.uniq)
+ bug9172 = '[ruby-core:58658] [Bug #9172]'
+ assert_not_equal(S("sub-setter").hash, S("discover").hash, bug9172)
end
def test_hex
@@ -769,10 +1290,10 @@ class TestString < Test::Unit::TestCase
end
def test_include?
- assert( S("foobar").include?(?f))
- assert( S("foobar").include?(S("foo")))
- assert(!S("foobar").include?(S("baz")))
- assert(!S("foobar").include?(?z))
+ assert_include(S("foobar"), ?f)
+ assert_include(S("foobar"), S("foo"))
+ assert_not_include(S("foobar"), S("baz"))
+ assert_not_include(S("foobar"), ?z)
end
def test_index
@@ -792,6 +1313,20 @@ class TestString < Test::Unit::TestCase
assert_nil(S("hello").index(S("z")))
assert_nil(S("hello").index(/z./))
+ assert_equal(0, S("").index(S("")))
+ assert_equal(0, S("").index(//))
+ assert_nil(S("").index(S("hello")))
+ assert_nil(S("").index(/hello/))
+ assert_equal(0, S("hello").index(S("")))
+ assert_equal(0, S("hello").index(//))
+
+ s = S("long") * 1000 << "x"
+ assert_nil(s.index(S("y")))
+ assert_equal(4 * 1000, s.index(S("x")))
+ s << "yx"
+ assert_equal(4 * 1000, s.index(S("x")))
+ assert_equal(4 * 1000, s.index(S("xyx")))
+
o = Object.new
def o.to_str; "bar"; end
assert_equal(3, "foobarbarbaz".index(o))
@@ -799,11 +1334,21 @@ class TestString < Test::Unit::TestCase
assert_nil("foo".index(//, -100))
assert_nil($~)
+
+ assert_equal(2, S("abcdbce").index(/b\Kc/))
+ end
+
+ def test_insert
+ assert_equal("Xabcd", S("abcd").insert(0, 'X'))
+ assert_equal("abcXd", S("abcd").insert(3, 'X'))
+ assert_equal("abcdX", S("abcd").insert(4, 'X'))
+ assert_equal("abXcd", S("abcd").insert(-3, 'X'))
+ assert_equal("abcdX", S("abcd").insert(-1, 'X'))
end
def test_intern
assert_equal(:koala, S("koala").intern)
- assert(:koala != S("Koala").intern)
+ assert_not_equal(:koala, S("Koala").intern)
end
def test_length
@@ -832,6 +1377,9 @@ class TestString < Test::Unit::TestCase
assert_equal(S("AAAAA000"), S("ZZZZ999").next)
assert_equal(S("*+"), S("**").next)
+
+ assert_equal(S("!"), S(" ").next)
+ assert_equal(S(""), S("").next)
end
def test_next!
@@ -868,6 +1416,10 @@ class TestString < Test::Unit::TestCase
a = S("**")
assert_equal(S("*+"), a.next!)
assert_equal(S("*+"), a)
+
+ a = S(" ")
+ assert_equal(S("!"), a.next!)
+ assert_equal(S("!"), a)
end
def test_oct
@@ -887,12 +1439,8 @@ class TestString < Test::Unit::TestCase
assert_equal(S("foobar"), a.replace(S("foobar")))
a = S("foo")
- a.taint
- a.untrust
b = a.replace(S("xyz"))
assert_equal(S("xyz"), b)
- assert(b.tainted?)
- assert(b.untrusted?)
s = "foo" * 100
s2 = ("bar" * 100).dup
@@ -904,10 +1452,10 @@ class TestString < Test::Unit::TestCase
assert_equal(s2, s)
fs = "".freeze
- assert_raise(RuntimeError) { fs.replace("a") }
- assert_raise(RuntimeError) { fs.replace(fs) }
+ assert_raise(FrozenError) { fs.replace("a") }
+ assert_raise(FrozenError) { fs.replace(fs) }
assert_raise(ArgumentError) { fs.replace() }
- assert_raise(RuntimeError) { fs.replace(42) }
+ assert_raise(FrozenError) { fs.replace(42) }
end
def test_reverse
@@ -957,6 +1505,11 @@ class TestString < Test::Unit::TestCase
assert_nil("foo".rindex(//, -100))
assert_nil($~)
+
+ assert_equal(3, "foo".rindex(//))
+ assert_equal([3, 3], $~.offset(0))
+
+ assert_equal(5, S("abcdbce").rindex(/b\Kc/))
end
def test_rjust
@@ -984,13 +1537,15 @@ class TestString < Test::Unit::TestCase
a.scan(/(...)/) { |w| res << w }
assert_equal([[S("cru")], [S("el ")], [S("wor")]],res)
- a = S("hello")
- a.taint
- a.untrust
- res = []
- a.scan(/./) { |w| res << w }
- assert(res[0].tainted?, '[ruby-core:33338] #4087')
- assert(res[0].untrusted?, '[ruby-core:33338] #4087')
+ /h/ =~ a
+ a.scan(/x/)
+ assert_nil($~)
+
+ /h/ =~ a
+ a.scan('x')
+ assert_nil($~)
+
+ assert_equal(%w[1 2 3], S("a1 a2 a3").scan(/a\K./))
end
def test_size
@@ -1025,6 +1580,11 @@ class TestString < Test::Unit::TestCase
assert_equal(S("Bar"), S("FooBar").slice(S("Bar")))
assert_nil(S("FooBar").slice(S("xyzzy")))
assert_nil(S("FooBar").slice(S("plugh")))
+
+ bug9882 = '[ruby-core:62842] [Bug #9882]'
+ substr = S("\u{30c6 30b9 30c8 2019}#{bug9882}").slice(4..-1)
+ assert_equal(S(bug9882).hash, substr.hash, bug9882)
+ assert_predicate(substr, :ascii_only?, bug9882)
end
def test_slice!
@@ -1041,8 +1601,10 @@ class TestString < Test::Unit::TestCase
a = S("FooBar")
if @aref_slicebang_silent
assert_nil( a.slice!(6) )
+ assert_nil( a.slice!(6r) )
else
assert_raise(IndexError) { a.slice!(6) }
+ assert_raise(IndexError) { a.slice!(6r) }
end
assert_equal(S("FooBar"), a)
@@ -1127,19 +1689,11 @@ class TestString < Test::Unit::TestCase
assert_equal(S("Bar"), a.slice!(S("Bar")))
assert_equal(S("Foo"), a)
- pre_1_7_1 do
- a=S("FooBar")
- assert_nil(a.slice!(S("xyzzy")))
- assert_equal(S("FooBar"), a)
- assert_nil(a.slice!(S("plugh")))
- assert_equal(S("FooBar"), a)
- end
-
assert_raise(ArgumentError) { "foo".slice! }
end
def test_split
- assert_nil($;)
+ fs, $; = $;, nil
assert_equal([S("a"), S("b"), S("c")], S(" a b\t c ").split)
assert_equal([S("a"), S("b"), S("c")], S(" a b\t c ").split(S(" ")))
@@ -1161,9 +1715,71 @@ class TestString < Test::Unit::TestCase
assert_equal([S("a"), S(""), S("b"), S("c"), S("")], S("a||b|c|").split(S('|'), -1))
assert_equal([], "".split(//, 1))
+ ensure
+ EnvUtil.suppress_warning {$; = fs}
+ end
+
+ def test_split_with_block
+ fs, $; = $;, nil
+ result = []; S(" a b\t c ").split {|s| result << s}
+ assert_equal([S("a"), S("b"), S("c")], result)
+ result = []; S(" a b\t c ").split(S(" ")) {|s| result << s}
+ assert_equal([S("a"), S("b"), S("c")], result)
- assert_equal("[2, 3]", [1,2,3].slice!(1,10000).inspect, "moved from btest/knownbug")
+ result = []; S(" a | b | c ").split(S("|")) {|s| result << s}
+ assert_equal([S(" a "), S(" b "), S(" c ")], result)
+
+ result = []; S("aXXbXXcXX").split(/X./) {|s| result << s}
+ assert_equal([S("a"), S("b"), S("c")], result)
+
+ result = []; S("abc").split(//) {|s| result << s}
+ assert_equal([S("a"), S("b"), S("c")], result)
+
+ result = []; S("a|b|c").split(S('|'), 1) {|s| result << s}
+ assert_equal([S("a|b|c")], result)
+
+ result = []; S("a|b|c").split(S('|'), 2) {|s| result << s}
+ assert_equal([S("a"), S("b|c")], result)
+ result = []; S("a|b|c").split(S('|'), 3) {|s| result << s}
+ assert_equal([S("a"), S("b"), S("c")], result)
+
+ result = []; S("a|b|c|").split(S('|'), -1) {|s| result << s}
+ assert_equal([S("a"), S("b"), S("c"), S("")], result)
+ result = []; S("a|b|c||").split(S('|'), -1) {|s| result << s}
+ assert_equal([S("a"), S("b"), S("c"), S(""), S("")], result)
+
+ result = []; S("a||b|c|").split(S('|')) {|s| result << s}
+ assert_equal([S("a"), S(""), S("b"), S("c")], result)
+ result = []; S("a||b|c|").split(S('|'), -1) {|s| result << s}
+ assert_equal([S("a"), S(""), S("b"), S("c"), S("")], result)
+
+ result = []; "".split(//, 1) {|s| result << s}
+ assert_equal([], result)
+
+ result = []; "aaa,bbb,ccc,ddd".split(/,/) {|s| result << s.gsub(/./, "A")}
+ assert_equal(["AAA"]*4, result)
+ ensure
+ EnvUtil.suppress_warning {$; = fs}
+ end
+
+ def test_fs
+ assert_raise_with_message(TypeError, /\$;/) {
+ $; = []
+ }
+ assert_separately(%W[-W0], "#{<<~"begin;"}\n#{<<~'end;'}")
+ bug = '[ruby-core:79582] $; must not be GCed'
+ begin;
+ $; = " "
+ $a = nil
+ alias $; $a
+ alias $-F $a
+ GC.start
+ assert_equal([], "".split, bug)
+ end;
+ end
+
+ def test_split_encoding
bug6206 = '[ruby-dev:45441]'
Encoding.list.each do |enc|
next unless enc.ascii_compatible?
@@ -1172,6 +1788,41 @@ class TestString < Test::Unit::TestCase
end
end
+ def test_split_wchar
+ bug8642 = '[ruby-core:56036] [Bug #8642]'
+ WIDE_ENCODINGS.each do |enc|
+ s = S("abc,def".encode(enc))
+ assert_equal(["abc", "def"].map {|c| c.encode(enc)},
+ s.split(",".encode(enc)),
+ "#{bug8642} in #{enc.name}")
+ end
+ end
+
+ def test_split_invalid_sequence
+ bug10886 = '[ruby-core:68229] [Bug #10886]'
+ broken = S("\xa1".force_encoding("utf-8"))
+ assert_raise(ArgumentError, bug10886) {
+ S("a,b").split(broken)
+ }
+ end
+
+ def test_split_invalid_argument
+ assert_raise(TypeError) {
+ S("a,b").split(BasicObject.new)
+ }
+ end
+
+ def test_split_dupped
+ s = "abc"
+ s.split("b", 1).map(&:upcase!)
+ assert_equal("abc", s)
+ end
+
+ def test_split_lookbehind
+ assert_equal([S("ab"), S("d")], S("abcd").split(/(?<=b)c/))
+ assert_equal([S("ab"), S("d")], S("abcd").split(/b\Kc/))
+ end
+
def test_squeeze
assert_equal(S("abc"), S("aaabbbbccc").squeeze)
assert_equal(S("aa bb cc"), S("aa bb cc").squeeze(S(" ")))
@@ -1197,9 +1848,24 @@ class TestString < Test::Unit::TestCase
assert_nil(a.squeeze!)
end
+ def test_start_with?
+ assert_send([S("hello"), :start_with?, S("hel")])
+ assert_not_send([S("hello"), :start_with?, S("el")])
+ assert_send([S("hello"), :start_with?, S("el"), S("he")])
+
+ bug5536 = '[ruby-core:40623]'
+ assert_raise(TypeError, bug5536) {S("str").start_with? :not_convertible_to_string}
+
+ assert_equal(true, "hello".start_with?(/hel/))
+ assert_equal("hel", $&)
+ assert_equal(false, "hello".start_with?(/el/))
+ assert_nil($&)
+ end
+
def test_strip
assert_equal(S("x"), S(" x ").strip)
assert_equal(S("x"), S(" \n\r\t x \t\r\n\n ").strip)
+ assert_equal(S("x"), S("\x00x\x00").strip)
assert_equal("0b0 ".force_encoding("UTF-16BE"),
"\x00 0b0 ".force_encoding("UTF-16BE").strip)
@@ -1218,6 +1884,10 @@ class TestString < Test::Unit::TestCase
assert_equal(S("x"), a.strip!)
assert_equal(S("x"), a)
+ a = S("\x00x\x00")
+ assert_equal(S("x"), a.strip!)
+ assert_equal(S("x"), a)
+
a = S("x")
assert_nil(a.strip!)
assert_equal(S("x") ,a)
@@ -1231,6 +1901,7 @@ class TestString < Test::Unit::TestCase
assert_equal(S("HELL-o"), S("hello").sub(/(hell)(.)/) {
|s| $1.upcase + S('-') + $2
})
+ assert_equal(S("h<e>llo"), S("hello").sub('e', S('<\0>')))
assert_equal(S("a\\aba"), S("ababa").sub(/b/, '\\'))
assert_equal(S("ab\\aba"), S("ababa").sub(/(b)/, '\1\\'))
@@ -1262,13 +1933,6 @@ class TestString < Test::Unit::TestCase
assert_equal(S("a\\&aba"), S("ababa").sub(/b/, '\\\\&'))
assert_equal(S("a\\baba"), S("ababa").sub(/b/, '\\\\\&'))
- a = S("hello")
- a.taint
- a.untrust
- x = a.sub(/./, S('X'))
- assert(x.tainted?)
- assert(x.untrusted?)
-
o = Object.new
def o.to_str; "bar"; end
assert_equal("fooBARbaz", "foobarbaz".sub(o, "BAR"))
@@ -1282,6 +1946,16 @@ class TestString < Test::Unit::TestCase
o = Object.new
def o.to_s; self; end
assert_match(/^foo#<Object:0x.*>baz$/, "foobarbaz".sub("bar") { o })
+
+ assert_equal(S("Abc"), S("abc").sub("a", "A"))
+ m = nil
+ assert_equal(S("Abc"), S("abc").sub("a") {m = $~; "A"})
+ assert_equal(S("a"), m[0])
+ assert_equal(/a/, m.regexp)
+ bug = '[ruby-core:78686] [Bug #13042] other than regexp has no name references'
+ assert_raise_with_message(IndexError, /oops/, bug) {
+ 'hello'.gsub('hello', '\k<oops>')
+ }
end
def test_sub!
@@ -1306,12 +1980,11 @@ class TestString < Test::Unit::TestCase
a=S("hello")
assert_nil(a.sub!(/X/, S('Y')))
- r = S('X')
- r.taint
- r.untrust
- a.sub!(/./, r)
- assert(a.tainted?)
- assert(a.untrusted?)
+ bug16105 = '[Bug #16105] heap-use-after-free'
+ a = S("ABCDEFGHIJKLMNOPQRSTUVWXYZ012345678")
+ b = a.dup
+ c = a.slice(1, 100)
+ assert_equal("AABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", b.sub!(c, b), bug16105)
end
def test_succ
@@ -1330,10 +2003,18 @@ class TestString < Test::Unit::TestCase
assert_equal("abce", "abcd".succ)
assert_equal("THX1139", "THX1138".succ)
- assert_equal("<<koalb>>", "<<koala>>".succ)
+ assert_equal("<\<koalb>>", "<\<koala>>".succ)
assert_equal("2000aaa", "1999zzz".succ)
assert_equal("AAAA0000", "ZZZ9999".succ)
assert_equal("**+", "***".succ)
+
+ assert_equal("!", " ".succ)
+ assert_equal("", "".succ)
+
+ bug = '[ruby-core:83062] [Bug #13952]'
+ s = "\xff".b
+ assert_not_predicate(s, :ascii_only?)
+ assert_predicate(s.succ, :ascii_only?, bug)
end
def test_succ!
@@ -1375,6 +2056,14 @@ class TestString < Test::Unit::TestCase
assert_equal(S("No.10"), a.succ!)
assert_equal(S("No.10"), a)
+ a = S(" ")
+ assert_equal(S("!"), a.succ!)
+ assert_equal(S("!"), a)
+
+ a = S("")
+ assert_equal(S(""), a.succ!)
+ assert_equal(S(""), a)
+
assert_equal("aaaaaaaaaaaa", "zzzzzzzzzzz".succ!)
assert_equal("aaaaaaaaaaaaaaaaaaaaaaaa", "zzzzzzzzzzzzzzzzzzzzzzz".succ!)
end
@@ -1385,7 +2074,9 @@ class TestString < Test::Unit::TestCase
n += S("\001")
assert_equal(16, n.sum(17))
n[0] = 2.chr
- assert(15 != n.sum)
+ assert_not_equal(15, n.sum)
+ assert_equal(17, n.sum(0))
+ assert_equal(17, n.sum(-1))
end
def check_sum(str, bits=16)
@@ -1400,7 +2091,7 @@ class TestString < Test::Unit::TestCase
assert_equal(294, "abc".sum)
check_sum("abc")
check_sum("\x80")
- 0.upto(70) {|bits|
+ -3.upto(70) {|bits|
check_sum("xyz", bits)
}
end
@@ -1416,6 +2107,8 @@ class TestString < Test::Unit::TestCase
def test_swapcase
assert_equal(S("hi&LOW"), S("HI&low").swapcase)
+ s = S("")
+ assert_not_same(s, s.swapcase)
end
def test_swapcase!
@@ -1468,6 +2161,13 @@ class TestString < Test::Unit::TestCase
assert_equal(0x4000000000000000, "4611686018427387904".to_i(10))
assert_equal(1, "1__2".to_i(10))
assert_equal(1, "1_z".to_i(10))
+
+ bug6192 = '[ruby-core:43566]'
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-16be").to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-16le").to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-32be").to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-32le").to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("iso-2022-jp").to_i}
end
def test_to_s
@@ -1506,6 +2206,15 @@ class TestString < Test::Unit::TestCase
assert_equal(true, "\u0101".tr("\u0101", "a").ascii_only?)
assert_equal(true, "\u3041".tr("\u3041", "a").ascii_only?)
assert_equal(false, "\u3041\u3042".tr("\u3041", "a").ascii_only?)
+
+ bug6156 = '[ruby-core:43335]'
+ bug13950 = '[ruby-core:83056] [Bug #13950]'
+ str, range, star = %w[b a-z *].map{|s|s.encode("utf-16le")}
+ result = str.tr(range, star)
+ assert_equal(star, result, bug6156)
+ assert_not_predicate(str, :ascii_only?)
+ assert_not_predicate(star, :ascii_only?)
+ assert_not_predicate(result, :ascii_only?, bug13950)
end
def test_tr!
@@ -1635,6 +2344,7 @@ class TestString < Test::Unit::TestCase
assert_equal(S("HELLO"), S("hello").upcase)
assert_equal(S("HELLO"), S("HELLO").upcase)
assert_equal(S("ABC HELLO 123"), S("abc HELLO 123").upcase)
+ assert_equal(S("H\0""ELLO"), S("H\0""ello").upcase)
end
def test_upcase!
@@ -1647,6 +2357,12 @@ class TestString < Test::Unit::TestCase
a = S("HELLO")
assert_nil(a.upcase!)
assert_equal(S("HELLO"), a)
+
+ a = S("H\0""ello")
+ b = a.dup
+ assert_equal(S("H\0""ELLO"), a.upcase!)
+ assert_equal(S("H\0""ELLO"), a)
+ assert_equal(S("H\0""ello"), b)
end
def test_upto
@@ -1693,7 +2409,7 @@ class TestString < Test::Unit::TestCase
end
def test_frozen_check
- assert_raise(RuntimeError) {
+ assert_raise(FrozenError) {
s = ""
s.sub!(/\A/) { s.freeze; "zzz" }
}
@@ -1753,10 +2469,6 @@ class TestString < Test::Unit::TestCase
assert_nil(l.slice!(/\A.*\n/), "[ruby-dev:31665]")
end
- def test_end_with?
- assert("abc".end_with?("c"))
- end
-
def test_times2
s1 = ''
100.times {|n|
@@ -1779,7 +2491,7 @@ class TestString < Test::Unit::TestCase
def test_match_method
assert_equal("bar", "foobarbaz".match(/bar/).to_s)
- o = /foo/
+ o = Regexp.new('foo')
def o.match(x, y, z); x + y + z; end
assert_equal("foobarbaz", "foo".match(o, "bar", "baz"))
x = nil
@@ -1789,6 +2501,50 @@ class TestString < Test::Unit::TestCase
assert_raise(ArgumentError) { "foo".match }
end
+ def test_match_p_regexp
+ /backref/ =~ 'backref'
+ # must match here, but not in a separate method, e.g., assert_send,
+ # to check if $~ is affected or not.
+ assert_equal(true, "".match?(//))
+ assert_equal(true, :abc.match?(/.../))
+ assert_equal(true, 'abc'.match?(/b/))
+ assert_equal(true, 'abc'.match?(/b/, 1))
+ assert_equal(true, 'abc'.match?(/../, 1))
+ assert_equal(true, 'abc'.match?(/../, -2))
+ assert_equal(false, 'abc'.match?(/../, -4))
+ assert_equal(false, 'abc'.match?(/../, 4))
+ assert_equal(true, "\u3042xx".match?(/../, 1))
+ assert_equal(false, "\u3042x".match?(/../, 1))
+ assert_equal(true, ''.match?(/\z/))
+ assert_equal(true, 'abc'.match?(/\z/))
+ assert_equal(true, 'Ruby'.match?(/R.../))
+ assert_equal(false, 'Ruby'.match?(/R.../, 1))
+ assert_equal(false, 'Ruby'.match?(/P.../))
+ assert_equal('backref', $&)
+ end
+
+ def test_match_p_string
+ /backref/ =~ 'backref'
+ # must match here, but not in a separate method, e.g., assert_send,
+ # to check if $~ is affected or not.
+ assert_equal(true, "".match?(''))
+ assert_equal(true, :abc.match?('...'))
+ assert_equal(true, 'abc'.match?('b'))
+ assert_equal(true, 'abc'.match?('b', 1))
+ assert_equal(true, 'abc'.match?('..', 1))
+ assert_equal(true, 'abc'.match?('..', -2))
+ assert_equal(false, 'abc'.match?('..', -4))
+ assert_equal(false, 'abc'.match?('..', 4))
+ assert_equal(true, "\u3042xx".match?('..', 1))
+ assert_equal(false, "\u3042x".match?('..', 1))
+ assert_equal(true, ''.match?('\z'))
+ assert_equal(true, 'abc'.match?('\z'))
+ assert_equal(true, 'Ruby'.match?('R...'))
+ assert_equal(false, 'Ruby'.match?('R...', 1))
+ assert_equal(false, 'Ruby'.match?('P...'))
+ assert_equal('backref', $&)
+ end
+
def test_clear
s = "foo" * 100
s.clear
@@ -1803,6 +2559,14 @@ class TestString < Test::Unit::TestCase
assert_instance_of(String, s.to_s)
end
+ def test_inspect_nul
+ bug8290 = '[ruby-core:54458]'
+ s = "\0" + "12"
+ assert_equal '"\u000012"', s.inspect, bug8290
+ s = "\0".b + "12"
+ assert_equal '"\x0012"', s.inspect, bug8290
+ end
+
def test_partition
assert_equal(%w(he l lo), "hello".partition(/l/))
assert_equal(%w(he l lo), "hello".partition("l"))
@@ -1816,6 +2580,18 @@ class TestString < Test::Unit::TestCase
s = S("a:".force_encoding(enc))
assert_equal([enc]*3, s.partition("|").map(&:encoding), bug6206)
end
+
+ assert_equal(["\u30E6\u30FC\u30B6", "@", "\u30C9\u30E1.\u30A4\u30F3"],
+ "\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3".partition(/[@.]/))
+
+ bug = '[ruby-core:82911]'
+ hello = "hello"
+ hello.partition("hi").map(&:upcase!)
+ assert_equal("hello", hello, bug)
+
+ assert_equal(["", "", "foo"], "foo".partition(/^=*/))
+
+ assert_equal([S("ab"), S("c"), S("dbce")], S("abcdbce").partition(/b\Kc/))
end
def test_rpartition
@@ -1831,10 +2607,26 @@ class TestString < Test::Unit::TestCase
s = S("a:".force_encoding(enc))
assert_equal([enc]*3, s.rpartition("|").map(&:encoding), bug6206)
end
+
+ bug8138 = '[ruby-dev:47183]'
+ assert_equal(["\u30E6\u30FC\u30B6@\u30C9\u30E1", ".", "\u30A4\u30F3"],
+ "\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3".rpartition(/[@.]/), bug8138)
+
+ bug = '[ruby-core:82911]'
+ hello = "hello"
+ hello.rpartition("hi").map(&:upcase!)
+ assert_equal("hello", hello, bug)
+
+ assert_equal([S("abcdb"), S("c"), S("e")], S("abcdbce").rpartition(/b\Kc/))
end
def test_setter
assert_raise(TypeError) { $/ = 1 }
+ name = "\u{5206 884c}"
+ assert_separately([], <<-"end;") # do
+ alias $#{name} $/
+ assert_raise_with_message(TypeError, /\\$#{name}/) { $#{name} = 1 }
+ end;
end
def test_to_id
@@ -1889,7 +2681,33 @@ class TestString < Test::Unit::TestCase
=end
def test_casecmp
+ assert_equal(0, "FoO".casecmp("fOO"))
+ assert_equal(1, "FoO".casecmp("BaR"))
+ assert_equal(-1, "baR".casecmp("FoO"))
assert_equal(1, "\u3042B".casecmp("\u3042a"))
+ assert_equal(-1, "foo".casecmp("foo\0"))
+
+ assert_nil("foo".casecmp(:foo))
+ assert_nil("foo".casecmp(Object.new))
+
+ o = Object.new
+ def o.to_str; "fOO"; end
+ assert_equal(0, "FoO".casecmp(o))
+ end
+
+ def test_casecmp?
+ assert_equal(true, 'FoO'.casecmp?('fOO'))
+ assert_equal(false, 'FoO'.casecmp?('BaR'))
+ assert_equal(false, 'baR'.casecmp?('FoO'))
+ assert_equal(true, 'äöü'.casecmp?('ÄÖÜ'))
+ assert_equal(false, "foo".casecmp?("foo\0"))
+
+ assert_nil("foo".casecmp?(:foo))
+ assert_nil("foo".casecmp?(Object.new))
+
+ o = Object.new
+ def o.to_str; "fOO"; end
+ assert_equal(true, "FoO".casecmp?(o))
end
def test_upcase2
@@ -1901,10 +2719,281 @@ class TestString < Test::Unit::TestCase
end
def test_rstrip
+ assert_equal(" hello", " hello ".rstrip)
assert_equal("\u3042", "\u3042 ".rstrip)
+ assert_equal("\u3042", "\u3042\u0000".rstrip)
assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip }
end
+ def test_rstrip_bang
+ s1 = S(" hello ")
+ assert_equal(" hello", s1.rstrip!)
+ assert_equal(" hello", s1)
+
+ s2 = S("\u3042 ")
+ assert_equal("\u3042", s2.rstrip!)
+ assert_equal("\u3042", s2)
+
+ s3 = S(" \u3042")
+ assert_equal(nil, s3.rstrip!)
+ assert_equal(" \u3042", s3)
+
+ s4 = S("\u3042")
+ assert_equal(nil, s4.rstrip!)
+ assert_equal("\u3042", s4)
+
+ s5 = S("\u3042\u0000")
+ assert_equal("\u3042", s5.rstrip!)
+ assert_equal("\u3042", s5)
+
+ assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip! }
+ end
+
+ def test_lstrip
+ assert_equal("hello ", " hello ".lstrip)
+ assert_equal("\u3042", " \u3042".lstrip)
+ assert_equal("hello ", "\x00hello ".lstrip)
+ end
+
+ def test_lstrip_bang
+ s1 = S(" hello ")
+ assert_equal("hello ", s1.lstrip!)
+ assert_equal("hello ", s1)
+
+ s2 = S("\u3042 ")
+ assert_equal(nil, s2.lstrip!)
+ assert_equal("\u3042 ", s2)
+
+ s3 = S(" \u3042")
+ assert_equal("\u3042", s3.lstrip!)
+ assert_equal("\u3042", s3)
+
+ s4 = S("\u3042")
+ assert_equal(nil, s4.lstrip!)
+ assert_equal("\u3042", s4)
+
+ s5 = S("\u0000\u3042")
+ assert_equal("\u3042", s5.lstrip!)
+ assert_equal("\u3042", s5)
+
+ end
+
+ def test_delete_prefix
+ assert_raise(TypeError) { 'hello'.delete_prefix(nil) }
+ assert_raise(TypeError) { 'hello'.delete_prefix(1) }
+ assert_raise(TypeError) { 'hello'.delete_prefix(/hel/) }
+
+ s = S("hello")
+ assert_equal("lo", s.delete_prefix('hel'))
+ assert_equal("hello", s)
+
+ s = S("hello")
+ assert_equal("hello", s.delete_prefix('lo'))
+ assert_equal("hello", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal("\u{306b 3061 306f}", s.delete_prefix("\u{3053 3093}"))
+ assert_equal("\u{3053 3093 306b 3061 306f}", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal("\u{3053 3093 306b 3061 306f}", s.delete_prefix('hel'))
+ assert_equal("\u{3053 3093 306b 3061 306f}", s)
+
+ s = S("hello")
+ assert_equal("hello", s.delete_prefix("\u{3053 3093}"))
+ assert_equal("hello", s)
+
+ # skip if argument is a broken string
+ s = S("\xe3\x81\x82")
+ assert_equal("\xe3\x81\x82", s.delete_prefix("\xe3"))
+ assert_equal("\xe3\x81\x82", s)
+
+ s = S("\x95\x5c").force_encoding("Shift_JIS")
+ assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s.delete_prefix("\x95"))
+ assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s)
+
+ # clear coderange
+ s = S("\u{3053 3093}hello")
+ assert_not_predicate(s, :ascii_only?)
+ assert_predicate(s.delete_prefix("\u{3053 3093}"), :ascii_only?)
+
+ # argument should be converted to String
+ klass = Class.new { def to_str; 'a'; end }
+ s = S("abba")
+ assert_equal("bba", s.delete_prefix(klass.new))
+ assert_equal("abba", s)
+ end
+
+ def test_delete_prefix_bang
+ assert_raise(TypeError) { 'hello'.delete_prefix!(nil) }
+ assert_raise(TypeError) { 'hello'.delete_prefix!(1) }
+ assert_raise(TypeError) { 'hello'.delete_prefix!(/hel/) }
+
+ s = S("hello")
+ assert_equal("lo", s.delete_prefix!('hel'))
+ assert_equal("lo", s)
+
+ s = S("hello")
+ assert_equal(nil, s.delete_prefix!('lo'))
+ assert_equal("hello", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal("\u{306b 3061 306f}", s.delete_prefix!("\u{3053 3093}"))
+ assert_equal("\u{306b 3061 306f}", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal(nil, s.delete_prefix!('hel'))
+ assert_equal("\u{3053 3093 306b 3061 306f}", s)
+
+ s = S("hello")
+ assert_equal(nil, s.delete_prefix!("\u{3053 3093}"))
+ assert_equal("hello", s)
+
+ # skip if argument is a broken string
+ s = S("\xe3\x81\x82")
+ assert_equal(nil, s.delete_prefix!("\xe3"))
+ assert_equal("\xe3\x81\x82", s)
+
+ # clear coderange
+ s = S("\u{3053 3093}hello")
+ assert_not_predicate(s, :ascii_only?)
+ assert_predicate(s.delete_prefix!("\u{3053 3093}"), :ascii_only?)
+
+ # argument should be converted to String
+ klass = Class.new { def to_str; 'a'; end }
+ s = S("abba")
+ assert_equal("bba", s.delete_prefix!(klass.new))
+ assert_equal("bba", s)
+
+ s = S("ax").freeze
+ assert_raise_with_message(FrozenError, /frozen/) {s.delete_prefix!("a")}
+
+ s = S("ax")
+ o = Struct.new(:s).new(s)
+ def o.to_str
+ s.freeze
+ "a"
+ end
+ assert_raise_with_message(FrozenError, /frozen/) {s.delete_prefix!(o)}
+ end
+
+ def test_delete_suffix
+ assert_raise(TypeError) { 'hello'.delete_suffix(nil) }
+ assert_raise(TypeError) { 'hello'.delete_suffix(1) }
+ assert_raise(TypeError) { 'hello'.delete_suffix(/hel/) }
+
+ s = S("hello")
+ assert_equal("hel", s.delete_suffix('lo'))
+ assert_equal("hello", s)
+
+ s = S("hello")
+ assert_equal("hello", s.delete_suffix('he'))
+ assert_equal("hello", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal("\u{3053 3093 306b}", s.delete_suffix("\u{3061 306f}"))
+ assert_equal("\u{3053 3093 306b 3061 306f}", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal("\u{3053 3093 306b 3061 306f}", s.delete_suffix('lo'))
+ assert_equal("\u{3053 3093 306b 3061 306f}", s)
+
+ s = S("hello")
+ assert_equal("hello", s.delete_suffix("\u{3061 306f}"))
+ assert_equal("hello", s)
+
+ # skip if argument is a broken string
+ s = S("\xe3\x81\x82")
+ assert_equal("\xe3\x81\x82", s.delete_suffix("\x82"))
+ assert_equal("\xe3\x81\x82", s)
+
+ # clear coderange
+ s = S("hello\u{3053 3093}")
+ assert_not_predicate(s, :ascii_only?)
+ assert_predicate(s.delete_suffix("\u{3053 3093}"), :ascii_only?)
+
+ # argument should be converted to String
+ klass = Class.new { def to_str; 'a'; end }
+ s = S("abba")
+ assert_equal("abb", s.delete_suffix(klass.new))
+ assert_equal("abba", s)
+
+ # chomp removes any of "\n", "\r\n", "\r" when "\n" is specified,
+ # but delete_suffix does not
+ s = "foo\n"
+ assert_equal("foo", s.delete_suffix("\n"))
+ s = "foo\r\n"
+ assert_equal("foo\r", s.delete_suffix("\n"))
+ s = "foo\r"
+ assert_equal("foo\r", s.delete_suffix("\n"))
+ end
+
+ def test_delete_suffix_bang
+ assert_raise(TypeError) { 'hello'.delete_suffix!(nil) }
+ assert_raise(TypeError) { 'hello'.delete_suffix!(1) }
+ assert_raise(TypeError) { 'hello'.delete_suffix!(/hel/) }
+
+ s = S("hello").freeze
+ assert_raise_with_message(FrozenError, /frozen/) {s.delete_suffix!('lo')}
+
+ s = S("ax")
+ o = Struct.new(:s).new(s)
+ def o.to_str
+ s.freeze
+ "x"
+ end
+ assert_raise_with_message(FrozenError, /frozen/) {s.delete_suffix!(o)}
+
+ s = S("hello")
+ assert_equal("hel", s.delete_suffix!('lo'))
+ assert_equal("hel", s)
+
+ s = S("hello")
+ assert_equal(nil, s.delete_suffix!('he'))
+ assert_equal("hello", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal("\u{3053 3093 306b}", s.delete_suffix!("\u{3061 306f}"))
+ assert_equal("\u{3053 3093 306b}", s)
+
+ s = S("\u{3053 3093 306b 3061 306f}")
+ assert_equal(nil, s.delete_suffix!('lo'))
+ assert_equal("\u{3053 3093 306b 3061 306f}", s)
+
+ s = S("hello")
+ assert_equal(nil, s.delete_suffix!("\u{3061 306f}"))
+ assert_equal("hello", s)
+
+ # skip if argument is a broken string
+ s = S("\xe3\x81\x82")
+ assert_equal(nil, s.delete_suffix!("\x82"))
+ assert_equal("\xe3\x81\x82", s)
+
+ s = S("\x95\x5c").force_encoding("Shift_JIS")
+ assert_equal(nil, s.delete_suffix!("\x5c"))
+ assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s)
+
+ # clear coderange
+ s = S("hello\u{3053 3093}")
+ assert_not_predicate(s, :ascii_only?)
+ assert_predicate(s.delete_suffix!("\u{3053 3093}"), :ascii_only?)
+
+ # argument should be converted to String
+ klass = Class.new { def to_str; 'a'; end }
+ s = S("abba")
+ assert_equal("abb", s.delete_suffix!(klass.new))
+ assert_equal("abb", s)
+
+ # chomp removes any of "\n", "\r\n", "\r" when "\n" is specified,
+ # but delete_suffix does not
+ s = "foo\n"
+ assert_equal("foo", s.delete_suffix!("\n"))
+ s = "foo\r\n"
+ assert_equal("foo\r", s.delete_suffix!("\n"))
+ s = "foo\r"
+ assert_equal(nil, s.delete_suffix!("\n"))
+ end
+
=begin
def test_symbol_table_overflow
assert_in_out_err([], <<-INPUT, [], /symbol table overflow \(symbol [a-z]{8}\) \(RuntimeError\)/)
@@ -1913,6 +3002,23 @@ class TestString < Test::Unit::TestCase
end
=end
+ def test_nesting_shared
+ a = ('a' * 24).encode(Encoding::ASCII).gsub('x', '')
+ hash = {}
+ hash[a] = true
+ assert_equal(('a' * 24), a)
+ 4.times { GC.start }
+ assert_equal(('a' * 24), a, '[Bug #15792]')
+ end
+
+ def test_nesting_shared_b
+ a = ('j' * 24).b.b
+ eval('', binding, a)
+ assert_equal(('j' * 24), a)
+ 4.times { GC.start }
+ assert_equal(('j' * 24), a, '[Bug #15934]')
+ end
+
def test_shared_force_encoding
s = "\u{3066}\u{3059}\u{3068}".gsub(//, '')
h = {}
@@ -1928,18 +3034,21 @@ class TestString < Test::Unit::TestCase
def test_ascii_incomat_inspect
bug4081 = '[ruby-core:33283]'
- [Encoding::UTF_16LE, Encoding::UTF_16BE,
- Encoding::UTF_32LE, Encoding::UTF_32BE].each do |e|
+ WIDE_ENCODINGS.each do |e|
assert_equal('"abc"', "abc".encode(e).inspect)
assert_equal('"\\u3042\\u3044\\u3046"', "\u3042\u3044\u3046".encode(e).inspect)
assert_equal('"ab\\"c"', "ab\"c".encode(e).inspect, bug4081)
end
begin
+ verbose, $VERBOSE = $VERBOSE, nil
ext = Encoding.default_external
Encoding.default_external = "us-ascii"
+ $VERBOSE = verbose
i = "abc\"\\".force_encoding("utf-8").inspect
ensure
+ $VERBOSE = nil
Encoding.default_external = ext
+ $VERBOSE = verbose
end
assert_equal('"abc\\"\\\\"', i, bug4081)
end
@@ -1950,7 +3059,9 @@ class TestString < Test::Unit::TestCase
end
def test_prepend
- assert_equal(S("hello world!"), "world!".prepend("hello "))
+ assert_equal(S("hello world!"), "!".prepend("hello ", "world"))
+ b = S("ue")
+ assert_equal(S("ueueue"), b.prepend(b, b))
foo = Object.new
def foo.to_str
@@ -1995,5 +3106,143 @@ class TestString < Test::Unit::TestCase
assert_equal(u("\x81\x82"), "\u3042".byteslice(1..2))
assert_equal(u("\x82")+("\u3042"*9), ("\u3042"*10).byteslice(2, 28))
+
+ bug7954 = '[ruby-dev:47108]'
+ assert_equal(false, "\u3042".byteslice(0, 2).valid_encoding?, bug7954)
+ assert_equal(false, ("\u3042"*10).byteslice(0, 20).valid_encoding?, bug7954)
+ end
+
+ def test_unknown_string_option
+ str = nil
+ assert_nothing_raised(SyntaxError) do
+ eval(%{
+ str = begin"hello"end
+ })
+ end
+ assert_equal "hello", str
+ end
+
+ def test_eq_tilde_can_be_overridden
+ assert_separately([], <<-RUBY)
+ class String
+ undef =~
+ def =~(str)
+ "foo"
+ end
+ end
+
+ assert_equal("foo", "" =~ //)
+ RUBY
+ end
+
+ class Bug9581 < String
+ def =~ re; :foo end
+ end
+
+ def test_regexp_match_subclass
+ s = Bug9581.new("abc")
+ r = /abc/
+ assert_equal(:foo, s =~ r)
+ assert_equal(:foo, s.send(:=~, r))
+ assert_equal(:foo, s.send(:=~, /abc/))
+ assert_equal(:foo, s =~ /abc/, "should not use optimized instruction")
+ end
+
+ def test_LSHIFT_neary_long_max
+ return unless @cls == String
+ assert_ruby_status([], <<-'end;', '[ruby-core:61886] [Bug #9709]', timeout: 20)
+ begin
+ a = "a" * 0x4000_0000
+ a << "a" * 0x1_0000
+ rescue NoMemoryError
+ end
+ end;
+ end if [0].pack("l!").bytesize < [nil].pack("p").bytesize
+ # enable only when string size range is smaller than memory space
+
+ def test_uplus_minus
+ str = "foo"
+ assert_not_predicate(str, :frozen?)
+ assert_not_predicate(+str, :frozen?)
+ assert_predicate(-str, :frozen?)
+
+ assert_same(str, +str)
+ assert_not_same(str, -str)
+
+ str = "bar".freeze
+ assert_predicate(str, :frozen?)
+ assert_not_predicate(+str, :frozen?)
+ assert_predicate(-str, :frozen?)
+
+ assert_not_same(str, +str)
+ assert_same(str, -str)
+
+ bar = %w(b a r).join('')
+ assert_same(str, -bar, "uminus deduplicates [Feature #13077]")
+ end
+
+ def test_uminus_frozen
+ # embedded
+ str1 = ("foobar" * 3).freeze
+ str2 = ("foobar" * 3).freeze
+ assert_not_same str1, str2
+ assert_same str1, -str1
+ assert_same str1, -str2
+
+ # regular
+ str1 = ("foobar" * 4).freeze
+ str2 = ("foobar" * 4).freeze
+ assert_not_same str1, str2
+ assert_same str1, -str1
+ assert_same str1, -str2
+ end
+
+ def test_uminus_no_freeze_not_bare
+ str = @cls.new("foo")
+ assert_instance_of(@cls, -str)
+ assert_equal(false, str.frozen?)
+
+ str = @cls.new("foo")
+ str.instance_variable_set(:@iv, 1)
+ assert_instance_of(@cls, -str)
+ assert_equal(false, str.frozen?)
+ assert_equal(1, str.instance_variable_get(:@iv))
+
+ str = @cls.new("foo")
+ assert_instance_of(@cls, -str)
+ assert_equal(false, str.frozen?)
+ end
+
+ def test_ord
+ assert_equal(97, "a".ord)
+ assert_equal(97, "abc".ord)
+ assert_equal(0x3042, "\u3042\u3043".ord)
+ assert_raise(ArgumentError) { "".ord }
+ end
+
+ def test_chr
+ assert_equal("a", "abcde".chr)
+ assert_equal("a", "a".chr)
+ assert_equal("\u3042", "\u3042\u3043".chr)
+ assert_equal('', ''.chr)
+ end
+
+ def test_substr_code_range
+ data = "\xff" + "a"*200
+ assert_not_predicate(data, :valid_encoding?)
+ assert_predicate(data[100..-1], :valid_encoding?)
+ end
+
+ def test_slice_bang_code_range
+ str = "[Bug #19739] ABC OÜ"
+ str.slice!(/ oü$/i)
+ assert_predicate str, :ascii_only?
+ end
+end
+
+class TestString2 < TestString
+ def initialize(*args)
+ super
+ @cls = S2
end
end