diff options
Diffstat (limited to 'test/-ext-/string')
| -rw-r--r-- | test/-ext-/string/test_capacity.rb | 75 | ||||
| -rw-r--r-- | test/-ext-/string/test_coderange.rb | 60 | ||||
| -rw-r--r-- | test/-ext-/string/test_cstr.rb | 168 | ||||
| -rw-r--r-- | test/-ext-/string/test_ellipsize.rb | 47 | ||||
| -rw-r--r-- | test/-ext-/string/test_enc_associate.rb | 24 | ||||
| -rw-r--r-- | test/-ext-/string/test_enc_str_buf_cat.rb | 25 | ||||
| -rw-r--r-- | test/-ext-/string/test_external_new.rb | 17 | ||||
| -rw-r--r-- | test/-ext-/string/test_fstring.rb | 72 | ||||
| -rw-r--r-- | test/-ext-/string/test_interned_str.rb | 17 | ||||
| -rw-r--r-- | test/-ext-/string/test_modify_expand.rb | 26 | ||||
| -rw-r--r-- | test/-ext-/string/test_nofree.rb | 13 | ||||
| -rw-r--r-- | test/-ext-/string/test_normalize.rb | 110 | ||||
| -rw-r--r-- | test/-ext-/string/test_qsort.rb | 20 | ||||
| -rw-r--r-- | test/-ext-/string/test_rb_str_dup.rb | 18 | ||||
| -rw-r--r-- | test/-ext-/string/test_set_len.rb | 84 | ||||
| -rw-r--r-- | test/-ext-/string/test_too_many_dummy_encodings.rb | 15 |
16 files changed, 791 insertions, 0 deletions
diff --git a/test/-ext-/string/test_capacity.rb b/test/-ext-/string/test_capacity.rb new file mode 100644 index 0000000000..df000f7cdb --- /dev/null +++ b/test/-ext-/string/test_capacity.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true +require 'test/unit' +require '-test-/string' +require 'rbconfig/sizeof' + +class Test_StringCapacity < Test::Unit::TestCase + def test_capacity_embedded + assert_equal GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] - embed_header_size - 1, capa('foo') + assert_equal max_embed_len, capa('1' * max_embed_len) + assert_equal max_embed_len, capa('1' * (max_embed_len - 1)) + end + + def test_capacity_shared + sym = ("a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).to_sym + assert_equal 0, capa(sym.to_s) + end + + def test_capacity_normal + assert_equal max_embed_len + 1, capa('1' * (max_embed_len + 1)) + assert_equal max_embed_len + 100, capa('1' * (max_embed_len + 100)) + end + + def test_s_new_capacity + assert_equal("", String.new(capacity: 1000)) + assert_equal(String, String.new(capacity: 1000).class) + assert_equal(10_000, capa(String.new(capacity: 10_000))) + + assert_equal("", String.new(capacity: -1000)) + assert_equal(capa(String.new(capacity: -10000)), capa(String.new(capacity: -1000))) + end + + def test_io_read + s = String.new(capacity: 1000) + open(__FILE__) {|f|f.read(1024*1024, s)} + assert_equal(1024*1024, capa(s)) + open(__FILE__) {|f|s = f.read(1024*1024)} + assert_operator(capa(s), :<=, s.bytesize+4096) + end + + def test_literal_capacity + s = eval(%{ + # frozen_string_literal: true + "#{"a" * (max_embed_len + 1)}" + }) + assert_equal(s.length, capa(s)) + end + + def test_capacity_frozen + s = String.new("I am testing", capacity: 1000) + s << "a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + s.freeze + assert_equal(s.length, capa(s)) + end + + def test_capacity_fstring + s = String.new("a" * max_embed_len, capacity: max_embed_len * 3) + s << "fstring capacity" + s = -s + assert_equal(s.length, capa(s)) + end + + private + + def capa(str) + Bug::String.capacity(str) + end + + def embed_header_size + GC::INTERNAL_CONSTANTS[:RBASIC_SIZE] + RbConfig::SIZEOF['void*'] + end + + def max_embed_len + GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE] - embed_header_size - 1 + end +end diff --git a/test/-ext-/string/test_coderange.rb b/test/-ext-/string/test_coderange.rb new file mode 100644 index 0000000000..18b256fcea --- /dev/null +++ b/test/-ext-/string/test_coderange.rb @@ -0,0 +1,60 @@ +# coding: ascii-8bit +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" +require "rbconfig/sizeof" + +class Test_StringCoderange < Test::Unit::TestCase + def setup + @sizeof_voidp = RbConfig::SIZEOF["void*"] + @a8 = Encoding::ASCII_8BIT + @a7 = Encoding::US_ASCII + @u8 = Encoding::UTF_8 + end + + def test_ascii8bit + enc = @a8 + str = "a" + str.force_encoding(enc) + assert_equal :"7bit", Bug::String.new(str).coderange_scan + + str = "a\xBE".force_encoding(enc) + assert_equal :valid, Bug::String.new(str).coderange_scan + end + + def test_usascii + enc = @a7 + str = "a" + str.force_encoding(enc) + assert_equal :"7bit", Bug::String.new(str).coderange_scan + + str = "a" * (@sizeof_voidp * 2) + str << "\xBE" + str.force_encoding(enc) + assert_equal :broken, Bug::String.new(str).coderange_scan + end + + def test_utf8 + enc = @u8 + str = "a" + str.force_encoding(enc) + assert_equal :"7bit", Bug::String.new(str).coderange_scan + + str = "a" * (@sizeof_voidp * 3) + str << "aa\xC2\x80" + str.force_encoding(enc) + assert_equal :valid, Bug::String.new(str).coderange_scan + + str = "a" * (@sizeof_voidp * 2) + str << "\xC2\x80" + str << "a" * (@sizeof_voidp * 2) + str.force_encoding(enc) + assert_equal :valid, Bug::String.new(str).coderange_scan + + str = "a" * (@sizeof_voidp * 2) + str << "\xC1\x80" + str << "a" * (@sizeof_voidp * 2) + str.force_encoding(enc) + assert_equal :broken, Bug::String.new(str).coderange_scan + end +end diff --git a/test/-ext-/string/test_cstr.rb b/test/-ext-/string/test_cstr.rb new file mode 100644 index 0000000000..efc64119dc --- /dev/null +++ b/test/-ext-/string/test_cstr.rb @@ -0,0 +1,168 @@ +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" + +class Test_StringCStr < Test::Unit::TestCase + Bug4319 = '[ruby-dev:43094]' + + def test_embed + s = Bug::String.new("abcdef") + s.set_len(3) + s.cstr_unterm('x') + assert_equal(0, s.cstr_term, Bug4319) + end + + def test_long + s = Bug::String.new(Bug::String.new("abcdef")*100000) + s.cstr_unterm('x') + assert_equal(0, s.cstr_term, Bug4319) + end + + def test_shared + s = Bug::String.new(Bug::String.new("abcdef")*5) + s = s.unterminated_substring(0, 29) + assert_equal(0, s.cstr_term, Bug4319) + end + + def test_frozen + s0 = Bug::String.new("abcdefgh"*8) + + [4, 4*3-1, 8*3-1, 64].each do |n| + s = Bug::String.new(s0[0, n]) + s.cstr_unterm('x') + s.freeze + assert_equal(0, s.cstr_term) + WCHARS.each do |enc| + s = s0.encode(enc) + s.set_len(n - n % s[0].bytesize) + s.cstr_unterm('x') + s.freeze + assert_equal(0, s.cstr_term) + end + end + end + + def test_rb_str_new_frozen_embed + # "rbconfi" is the smallest "maximum embeddable string". VWA adds + # a capacity field, which removes one pointer capacity for embedded objects, + # so if VWA is enabled, but there is only one size pool, then the + # maximum embeddable capacity on 32 bit machines is 8 bytes. + str = Bug::String.cstr_noembed("rbconfi") + str = Bug::String.rb_str_new_frozen(str) + assert_equal true, Bug::String.cstr_embedded?(str) + end + + WCHARS = [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE] + + def test_wchar_embed + WCHARS.each do |enc| + s = Bug::String.new("\u{4022}a".encode(enc)) + s.cstr_unterm('x') + assert_nothing_raised(ArgumentError) {s.cstr_term} + s.set_len(s.bytesize / 2) + assert_equal(1, s.size) + s.cstr_unterm('x') + assert_equal(0, s.cstr_term) + end + end + + def test_wchar_long + str = "\u{4022}abcdef" + n = 100 + len = str.size * n + WCHARS.each do |enc| + s = Bug::String.new(Bug::String.new(str.encode(enc))*n) + s.cstr_unterm('x') + assert_nothing_raised(ArgumentError, enc.name) {s.cstr_term} + s.set_len(s.bytesize / 2) + assert_equal(len / 2, s.size, enc.name) + s.cstr_unterm('x') + assert_equal(0, s.cstr_term, enc.name) + end + end + + def test_wchar_lstrip! + assert_wchars_term_char(" a") {|s| s.lstrip!} + end + + def test_wchar_rstrip! + assert_wchars_term_char("a ") {|s| s.rstrip!} + end + + def test_wchar_chop! + assert_wchars_term_char("a\n") {|s| s.chop!} + end + + def test_wchar_chomp! + assert_wchars_term_char("a\n") {|s| s.chomp!} + end + + def test_wchar_aset + assert_wchars_term_char("a"*30) {|s| s[29,1] = ""} + end + + def test_wchar_sub! + assert_wchars_term_char("foobar") {|s| s.sub!(/#{"foo".encode(s.encoding)}/, "")} + end + + def test_wchar_delete! + assert_wchars_term_char("foobar") {|s| s.delete!("ao".encode(s.encoding))} + end + + def test_wchar_squeeze! + assert_wchars_term_char("foo!") {|s| s.squeeze!} + end + + def test_wchar_tr! + assert_wchars_term_char("\u{3042}foobar") {|s| + enc = s.encoding + s.tr!("\u{3042}".encode(enc), "c".encode(enc)) + } + end + + def test_wchar_tr_s! + assert_wchars_term_char("\u{3042}foobar") {|s| + enc = s.encoding + s.tr_s!("\u{3042}".encode(enc), "c".encode(enc)) + } + end + + def test_wchar_replace + assert_wchars_term_char("abc") {|s| + w = s.dup + s.replace("abcdefghijklmnop") + s.replace(w) + } + end + + def test_embedded_from_heap + gh821 = "[GH-821]" + embedded_string = "abcdefghi" + string = embedded_string.gsub("efg", "123") + {}[string] = 1 + non_terminated = "#{string}#{nil}" + assert_nil(Bug::String.cstr_term_char(non_terminated), gh821) + + result = {} + WCHARS.map do |enc| + embedded_string = "ab".encode(enc) + string = embedded_string.gsub("b".encode(enc), "1".encode(enc)) + {}[string] = 1 + non_terminated = "#{string}#{nil}" + c = Bug::String.cstr_term_char(non_terminated) + result[enc] = c if c + end + assert_empty(result, gh821) + end + + def assert_wchars_term_char(str) + result = {} + WCHARS.map do |enc| + s = Bug::String.new(str.encode(enc)) + yield s + c = s.cstr_term_char + result[enc] = c if c + end + assert_empty(result) + end +end diff --git a/test/-ext-/string/test_ellipsize.rb b/test/-ext-/string/test_ellipsize.rb new file mode 100644 index 0000000000..d340abd58a --- /dev/null +++ b/test/-ext-/string/test_ellipsize.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" + +class Test_StringEllipsize < Test::Unit::TestCase + def setup + @foobar = Bug::String.new("foobar") + end + + def assert_equal_with_class(expected, result, *rest) + assert_equal(expected.encoding, result.encoding, *rest) + assert_equal(expected, result, result.encoding.name) + assert_instance_of(String, result, *rest) + end + + def test_longer + assert_equal_with_class("", @foobar.ellipsize(0)) + assert_equal_with_class(".", @foobar.ellipsize(1)) + assert_equal_with_class("..", @foobar.ellipsize(2)) + assert_equal_with_class("...", @foobar.ellipsize(3)) + assert_equal_with_class("f...", @foobar.ellipsize(4)) + assert_equal_with_class("fo...", @foobar.ellipsize(5)) + end + + def test_shorter + assert_same(@foobar, @foobar.ellipsize(6)) + assert_same(@foobar, @foobar.ellipsize(7)) + end + + def test_negative_length + assert_raise(IndexError) {@foobar.ellipsize(-1)} + end + + def test_nonascii + a = "\u3042" + Encoding.list.each do |enc| + next if enc.dummy? + begin + s = a.encode(enc) + e = "...".encode(enc) + rescue + else + assert_equal_with_class(s*12+e, Bug::String.new(s*20).ellipsize(15)) + end + end + end +end diff --git a/test/-ext-/string/test_enc_associate.rb b/test/-ext-/string/test_enc_associate.rb new file mode 100644 index 0000000000..95d1f00cd2 --- /dev/null +++ b/test/-ext-/string/test_enc_associate.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" + +class Test_StrEncAssociate < Test::Unit::TestCase + def test_frozen + s = Bug::String.new("abc") + s.force_encoding(Encoding::US_ASCII) + s.freeze + assert_raise(FrozenError) {s.associate_encoding!(Encoding::US_ASCII)} + assert_raise(FrozenError) {s.associate_encoding!(Encoding::UTF_8)} + end + + Encoding.list.select(&:dummy?).each do |enc| + enc = enc.name.tr('-', '_') + define_method("test_dummy_encoding_index_#{enc}") do + assert_separately(["-r-test-/string", "-", enc], <<-"end;") #do + enc = Encoding.const_get(ARGV[0]) + index = Bug::String.encoding_index(enc) + assert(index < 0xffff, "<%#x> expected but was\n<%#x>" % [index & 0xffff, index]) + end; + end + end +end diff --git a/test/-ext-/string/test_enc_str_buf_cat.rb b/test/-ext-/string/test_enc_str_buf_cat.rb new file mode 100644 index 0000000000..b9a63ec2de --- /dev/null +++ b/test/-ext-/string/test_enc_str_buf_cat.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" + +class Test_StringEncStrBufCat < Test::Unit::TestCase + Bug6509 = '[ruby-dev:45688]' + + def test_unknown + a8_str = "a\xBE".force_encoding(Encoding::ASCII_8BIT) + cr_unknown_str = [0x62].pack('C*') + assert_equal(true, a8_str.valid_encoding?, "an assertion for following tests") + assert_equal(:valid, Bug::String.new(a8_str).coderange, "an assertion for following tests") + assert_equal(:unknown, Bug::String.new(cr_unknown_str).coderange, "an assertion for following tests") + assert_equal(:valid, Bug::String.new(a8_str).enc_str_buf_cat(cr_unknown_str).coderange, Bug6509) + end + + def test_str_conv_enc + str = Bug::String.new("aaa".encode("US-ASCII")) + assert_same(str, str.str_conv_enc_opts("UTF-8", "US-ASCII", 0, nil)) + + str = Bug::String.new("aaa".encode("UTF-16LE").force_encoding("UTF-8")) + assert_predicate(str, :ascii_only?) # cache coderange + assert_equal("aaa", str.str_conv_enc_opts("UTF-16LE", "UTF-8", 0, nil)) + end +end diff --git a/test/-ext-/string/test_external_new.rb b/test/-ext-/string/test_external_new.rb new file mode 100644 index 0000000000..f8ee773b16 --- /dev/null +++ b/test/-ext-/string/test_external_new.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: false +require 'test/unit' +require '-test-/string' + +class Test_StringExternalNew < Test::Unit::TestCase + def test_buf_new + assert_operator(0, :<=, Bug::String.capacity(Bug::String.buf_new(0))) + assert_operator(127, :<=, Bug::String.capacity(Bug::String.buf_new(127))) + assert_operator(128, :<=, Bug::String.capacity(Bug::String.buf_new(128))) + end + + def test_external_new_with_enc + Encoding.list.each do |enc| + assert_equal(enc, Bug::String.external_new(0, enc).encoding) + end + end +end diff --git a/test/-ext-/string/test_fstring.rb b/test/-ext-/string/test_fstring.rb new file mode 100644 index 0000000000..fcec6be543 --- /dev/null +++ b/test/-ext-/string/test_fstring.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: false +require 'test/unit' +require '-test-/string' +require_relative '../symbol/noninterned_name' + +class Test_String_Fstring < Test::Unit::TestCase + include Test_Symbol::NonInterned + + def assert_fstring(str) + fstr = Bug::String.fstring(str) + yield str + yield fstr + end + + def test_rb_enc_interned_str_autoloaded_encoding + assert_separately([], <<~RUBY) + require '-test-/string' + assert_include(Encoding::CESU_8.inspect, 'autoload') + Bug::String.rb_enc_interned_str(Encoding::CESU_8) + RUBY + end + + def test_rb_enc_interned_str_null_encoding + assert_equal Encoding::ASCII_8BIT, Bug::String.rb_enc_interned_str(nil).encoding + end + + def test_rb_enc_str_new_autoloaded_encoding + assert_separately([], <<~RUBY) + require '-test-/string' + assert_include(Encoding::CESU_8.inspect, 'autoload') + Bug::String.rb_enc_str_new(Encoding::CESU_8) + RUBY + end + + def test_rb_enc_str_new_null_encoding + assert_equal Encoding::ASCII_8BIT, Bug::String.rb_enc_str_new(nil).encoding + end + + def test_instance_variable + str = __method__.to_s * 3 + str.instance_variable_set(:@test, 42) + str.freeze + assert_fstring(str) {|s| assert_send([s, :instance_variable_defined?, :@test])} + end + + def test_singleton_method + str = __method__.to_s * 3 + def str.foo + end + str.freeze + assert_fstring(str) {|s| assert_send([s, :respond_to?, :foo])} + end + + def test_singleton_class + str = noninterned_name + fstr = Bug::String.fstring(str) + assert_raise(TypeError) {fstr.singleton_class} + end + + def test_fake_str + assert_equal([*"a".."z"].join(""), Bug::String.fstring_fake_str) + end + + class S < String + end + + def test_subclass + str = S.new(__method__.to_s * 3) + str.freeze + assert_fstring(str) {|s| assert_instance_of(S, s)} + end +end diff --git a/test/-ext-/string/test_interned_str.rb b/test/-ext-/string/test_interned_str.rb new file mode 100644 index 0000000000..a81cb59aa5 --- /dev/null +++ b/test/-ext-/string/test_interned_str.rb @@ -0,0 +1,17 @@ +require 'test/unit' +require '-test-/string' + +class Test_RbInternedStr < Test::Unit::TestCase + def test_interned_str + src = "a" * 20 + interned_str = Bug::String.rb_interned_str_dup(src) + src.clear + src << "b" * 20 + assert_equal "a" * 20, interned_str + end + + def test_interned_str_encoding + src = :ascii.name + assert_equal Encoding::US_ASCII, Bug::String.rb_interned_str_dup(src).encoding + end +end diff --git a/test/-ext-/string/test_modify_expand.rb b/test/-ext-/string/test_modify_expand.rb new file mode 100644 index 0000000000..9aa3b9a6ca --- /dev/null +++ b/test/-ext-/string/test_modify_expand.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" +require "rbconfig/sizeof" + +class Test_StringModifyExpand < Test::Unit::TestCase + def test_modify_expand_memory_leak + assert_no_memory_leak(["-r-test-/string"], + <<-PRE, <<-CMD, "rb_str_modify_expand()", limit: 2.5) + s=Bug::String.new + PRE + size = $initial_size + 10.times{s.modify_expand!(size)} + s.replace("") + CMD + end + + def test_integer_overflow + return if RbConfig::SIZEOF['size_t'] > RbConfig::SIZEOF['long'] + bug12390 = '[ruby-core:75592] [Bug #12390]' + s = Bug::String.new + assert_raise(ArgumentError, bug12390) { + s.modify_expand!(RbConfig::LIMITS["LONG_MAX"]) + } + end +end diff --git a/test/-ext-/string/test_nofree.rb b/test/-ext-/string/test_nofree.rb new file mode 100644 index 0000000000..86681e4652 --- /dev/null +++ b/test/-ext-/string/test_nofree.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: false +require 'test/unit' + +class Test_StringNoFree < Test::Unit::TestCase + def test_no_memory_leak + bug10942 = '[ruby-core:68436] [Bug #10942] no leak on nofree string' + code = '.times {Bug::String.nofree << "a" * 100}' + assert_no_memory_leak(%w(-r-test-/string), + "100_000#{code}", + "1_000_000#{code}", + bug10942, rss: true) + end +end diff --git a/test/-ext-/string/test_normalize.rb b/test/-ext-/string/test_normalize.rb new file mode 100644 index 0000000000..80b21dff38 --- /dev/null +++ b/test/-ext-/string/test_normalize.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" +require "tempfile" + +class Test_StringNormalize < Test::Unit::TestCase +=begin + def test_normalize_all + exclude = [ + #0x340, 0x341, 0x343, 0x344 + ] + (0x0080..0xFFFD).each do |n| + next if 0xD800 <= n && n <= 0xDFFF + next if exclude.include? n + code = n.to_s(16) + Tempfile.create("#{code}-#{n.chr(Encoding::UTF_8)}-") do |tempfile| + ary = Dir.glob(File.expand_path("../#{code}-*", tempfile.path)) + assert_equal 1, ary.size + result = ary[0] + rn = result[/\/\h+-(.+?)-/, 1] + #assert_equal tempfile.path, result, "#{rn.dump} is not U+#{n.to_s(16)}" + r2 = Bug::String.new(result ).normalize_ospath + rn2 = r2[/\/\h+-(.+?)-/, 1] + if tempfile.path == result + if tempfile.path == r2 + else + puts "U+#{n.to_s(16)} shouldn't be r2#{rn2.dump}" + end + else + if tempfile.path == r2 + # puts "U+#{n.to_s(16)} shouldn't be r#{rn.dump}" + elsif result == r2 + puts "U+#{n.to_s(16)} shouldn't be #{rn.dump}" + else + puts "U+#{n.to_s(16)} shouldn't be r#{rn.dump} r2#{rn2.dump}" + end + end + end + end + end +=end + + def test_normalize + %[ + \u304C \u304B\u3099 + \u3077 \u3075\u309A + \u308F\u3099 \u308F\u3099 + \u30F4 \u30A6\u3099 + \u30DD \u30DB\u309A + \u30AB\u303A \u30AB\u303A + \u00C1 A\u0301 + B\u030A B\u030A + \u0386 \u0391\u0301 + \u03D3 \u03D2\u0301 + \u0401 \u0415\u0308 + \u2260 =\u0338 + \u{c548} \u{110b}\u{1161}\u{11ab} + ].scan(/(\S+)\s+(\S+)/) do |expected, src| + result = Bug::String.new(src).normalize_ospath + assert_equal expected, result, + "#{expected.dump} is expected but #{src.dump}" + end + end + + def test_not_normalize_kc + %W[ + \u2460 + \u2162 + \u3349 + \u33A1 + \u337B + \u2116 + \u33CD + \u2121 + \u32A4 + \u3231 + ].each do |src| + result = Bug::String.new(src).normalize_ospath + assert_equal src, result, + "#{src.dump} is expected not to be normalized, but #{result.dump}" + end + end + + def test_dont_normalize_hfsplus + %W[ + \u2190\u0338 + \u219A + \u212B + \uF90A + \uF9F4 + \uF961 \uF9DB + \uF96F \uF3AA + \uF915 \uF95C \uF9BF + \uFA0C + \uFA10 + \uFA19 + \uFA26 + ].each do |src| + result = Bug::String.new(src).normalize_ospath + assert_equal src, result, + "#{src.dump} is expected not to be normalized, but #{result.dump}" + end + end + + def test_invalid_sequence + assert_separately(%w[-r-test-/string], <<-'end;') + assert_equal("\u{fffd}", Bug::String.new("\xff").normalize_ospath) + end; + end +end if Bug::String.method_defined?(:normalize_ospath) diff --git a/test/-ext-/string/test_qsort.rb b/test/-ext-/string/test_qsort.rb new file mode 100644 index 0000000000..94aff8c3c4 --- /dev/null +++ b/test/-ext-/string/test_qsort.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" + +class Test_StringQSort < Test::Unit::TestCase + def test_qsort + s = Bug::String.new("xxozfxx") + s.qsort! + assert_equal("foxxxxz", s) + end + + def test_qsort_slice + s = Bug::String.new("xxofzx1") + s.qsort!(nil, nil, 3) + assert_equal("fzxxxo1", s) + s = Bug::String.new("xxofzx231") + s.qsort!(nil, nil, 3) + assert_equal("231fzxxxo", s) + end +end diff --git a/test/-ext-/string/test_rb_str_dup.rb b/test/-ext-/string/test_rb_str_dup.rb new file mode 100644 index 0000000000..c76a90252f --- /dev/null +++ b/test/-ext-/string/test_rb_str_dup.rb @@ -0,0 +1,18 @@ +require 'test/unit' +require '-test-/string' + +class Test_RbStrDup < Test::Unit::TestCase + def test_nested_shared_non_frozen + orig_str = "a" * GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE] + str = Bug::String.rb_str_dup(Bug::String.rb_str_dup(orig_str)) + assert_send([Bug::String, :shared_string?, str]) + assert_not_send([Bug::String, :sharing_with_shared?, str], '[Bug #15792]') + end + + def test_nested_shared_frozen + orig_str = "a" * GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE] + str = Bug::String.rb_str_dup(Bug::String.rb_str_dup(orig_str).freeze) + assert_send([Bug::String, :shared_string?, str]) + assert_not_send([Bug::String, :sharing_with_shared?, str], '[Bug #15792]') + end +end diff --git a/test/-ext-/string/test_set_len.rb b/test/-ext-/string/test_set_len.rb new file mode 100644 index 0000000000..1531d76167 --- /dev/null +++ b/test/-ext-/string/test_set_len.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" + +class Test_StrSetLen < Test::Unit::TestCase + def setup + # Make string long enough so that it is not embedded + @range_end = ("0".ord + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).chr + @s0 = [*"0"..@range_end].join("").freeze + @s1 = Bug::String.new(@s0) + end + + def teardown + orig = [*"0"..@range_end].join("") + assert_equal(orig, @s0) + end + + def test_non_shared + @s1.modify! + assert_equal("012", @s1.set_len(3)) + end + + def test_shared + assert_raise(RuntimeError) { + @s1.set_len(3) + } + end + + def test_capacity_equals_to_new_size + bug12757 = "[ruby-core:77257] [Bug #12757]" + # fill to ensure capacity does not decrease with force_encoding + str = Bug::String.new("\x00" * 128, capacity: 128) + str.force_encoding("UTF-32BE") + assert_equal 128, Bug::String.capacity(str) + assert_equal 127, str.set_len(127).bytesize, bug12757 + end + + def test_coderange_after_append + u = -"\u3042" + str = Bug::String.new(encoding: Encoding::UTF_8) + bsize = u.bytesize + str.append(u) + assert_equal 0, str.bytesize + str.set_len(bsize) + assert_equal bsize, str.bytesize + assert_predicate str, :valid_encoding? + assert_not_predicate str, :ascii_only? + assert_equal u, str + end + + def test_coderange_after_trunc + u = -"\u3042" + bsize = u.bytesize + str = Bug::String.new(u) + str.set_len(bsize - 1) + assert_equal bsize - 1, str.bytesize + assert_not_predicate str, :valid_encoding? + assert_not_predicate str, :ascii_only? + str.append(u.byteslice(-1)) + str.set_len(bsize) + assert_equal bsize, str.bytesize + assert_predicate str, :valid_encoding? + assert_not_predicate str, :ascii_only? + assert_equal u, str + end + + def test_valid_encoding_after_resized + s = "\0\0".force_encoding(Encoding::UTF_16BE) + str = Bug::String.new(s) + assert_predicate str, :valid_encoding? + str.resize(1) + assert_not_predicate str, :valid_encoding? + str.resize(2) + assert_predicate str, :valid_encoding? + str.resize(3) + assert_not_predicate str, :valid_encoding? + + s = "\xDB\x00\xDC\x00".force_encoding(Encoding::UTF_16BE) + str = Bug::String.new(s) + assert_predicate str, :valid_encoding? + str.resize(2) + assert_not_predicate str, :valid_encoding? + end +end diff --git a/test/-ext-/string/test_too_many_dummy_encodings.rb b/test/-ext-/string/test_too_many_dummy_encodings.rb new file mode 100644 index 0000000000..b96b40db7b --- /dev/null +++ b/test/-ext-/string/test_too_many_dummy_encodings.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: false +require 'test/unit' +require "-test-/string" + +class Test_TooManyDummyEncodings < Test::Unit::TestCase + def test_exceed_encoding_table_size + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + require "-test-/string" + assert_raise_with_message(EncodingError, /too many encoding/) do + 1_000.times{|i| Bug::String.rb_define_dummy_encoding("R_#{i}") } # now 256 entries + end + end; + end +end |
