diff options
Diffstat (limited to 'test/-ext-/string')
-rw-r--r-- | test/-ext-/string/test_capacity.rb | 40 | ||||
-rw-r--r-- | test/-ext-/string/test_chilled.rb | 19 | ||||
-rw-r--r-- | test/-ext-/string/test_cstr.rb | 6 | ||||
-rw-r--r-- | test/-ext-/string/test_fstring.rb | 34 | ||||
-rw-r--r-- | test/-ext-/string/test_rb_str_dup.rb | 6 | ||||
-rw-r--r-- | test/-ext-/string/test_set_len.rb | 39 | ||||
-rw-r--r-- | test/-ext-/string/test_too_many_dummy_encodings.rb | 15 |
7 files changed, 122 insertions, 37 deletions
diff --git a/test/-ext-/string/test_capacity.rb b/test/-ext-/string/test_capacity.rb index df59e76778..2c6c51fdda 100644 --- a/test/-ext-/string/test_capacity.rb +++ b/test/-ext-/string/test_capacity.rb @@ -4,27 +4,26 @@ require '-test-/string' require 'rbconfig/sizeof' class Test_StringCapacity < Test::Unit::TestCase - def capa(str) - Bug::String.capacity(str) - end - def test_capacity_embedded - size = RbConfig::SIZEOF['void*'] * 3 - 1 - assert_equal size, capa('foo') + 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 - assert_equal 0, capa(:abcdefghijklmnopqrstuvwxyz.to_s) + sym = ("a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).to_sym + assert_equal 0, capa(sym.to_s) end def test_capacity_normal - assert_equal 128, capa('1'*128) + 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(10000, capa(String.new(capacity: 10000))) + assert_equal(10_000 - 1, capa(String.new(capacity: 10_000))) # Real capa doesn't account for termlen assert_equal("", String.new(capacity: -1000)) assert_equal(capa(String.new(capacity: -10000)), capa(String.new(capacity: -1000))) @@ -39,21 +38,38 @@ class Test_StringCapacity < Test::Unit::TestCase end def test_literal_capacity - s = "I am testing string 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 << "fstring capacity" + s << "a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] s.freeze assert_equal(s.length, capa(s)) end def test_capacity_fstring - s = String.new("I am testing", capacity: 1000) + 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 + 3 * 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_chilled.rb b/test/-ext-/string/test_chilled.rb new file mode 100644 index 0000000000..dccab61ced --- /dev/null +++ b/test/-ext-/string/test_chilled.rb @@ -0,0 +1,19 @@ +require 'test/unit' +require '-test-/string' + +class Test_String_ChilledString < Test::Unit::TestCase + def test_rb_str_chilled_p + str = "" + assert_equal true, Bug::String.rb_str_chilled_p(str) + end + + def test_rb_str_chilled_p_frozen + str = "".freeze + assert_equal false, Bug::String.rb_str_chilled_p(str) + end + + def test_rb_str_chilled_p_mutable + str = "".dup + assert_equal false, Bug::String.rb_str_chilled_p(str) + end +end diff --git a/test/-ext-/string/test_cstr.rb b/test/-ext-/string/test_cstr.rb index d909781700..efc64119dc 100644 --- a/test/-ext-/string/test_cstr.rb +++ b/test/-ext-/string/test_cstr.rb @@ -43,7 +43,11 @@ class Test_StringCStr < Test::Unit::TestCase end def test_rb_str_new_frozen_embed - str = Bug::String.cstr_noembed("rbconfig.rb") + # "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 diff --git a/test/-ext-/string/test_fstring.rb b/test/-ext-/string/test_fstring.rb index 9b4956ecef..fcec6be543 100644 --- a/test/-ext-/string/test_fstring.rb +++ b/test/-ext-/string/test_fstring.rb @@ -15,19 +15,27 @@ class Test_String_Fstring < Test::Unit::TestCase def test_rb_enc_interned_str_autoloaded_encoding assert_separately([], <<~RUBY) require '-test-/string' - assert_include(Encoding::Windows_31J.inspect, 'autoload') - Bug::String.rb_enc_interned_str(Encoding::Windows_31J) + 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::Windows_31J.inspect, 'autoload') - Bug::String.rb_enc_str_new(Encoding::Windows_31J) + 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) @@ -49,6 +57,10 @@ class Test_String_Fstring < Test::Unit::TestCase 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 @@ -57,18 +69,4 @@ class Test_String_Fstring < Test::Unit::TestCase str.freeze assert_fstring(str) {|s| assert_instance_of(S, s)} end - - def test_shared_string_safety - _unused = -('a' * 30).force_encoding(Encoding::ASCII) - begin - verbose_back, $VERBOSE = $VERBOSE, nil - str = ('a' * 30).force_encoding(Encoding::ASCII).taint - ensure - $VERBOSE = verbose_back - end - frozen_str = Bug::String.rb_str_new_frozen(str) - assert_fstring(frozen_str) {|s| assert_equal(str, s)} - GC.start - assert_equal('a' * 30, str, "[Bug #16151]") - end end diff --git a/test/-ext-/string/test_rb_str_dup.rb b/test/-ext-/string/test_rb_str_dup.rb index 49b6af9598..c76a90252f 100644 --- a/test/-ext-/string/test_rb_str_dup.rb +++ b/test/-ext-/string/test_rb_str_dup.rb @@ -3,13 +3,15 @@ require '-test-/string' class Test_RbStrDup < Test::Unit::TestCase def test_nested_shared_non_frozen - str = Bug::String.rb_str_dup(Bug::String.rb_str_dup("a" * 50)) + 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 - str = Bug::String.rb_str_dup(Bug::String.rb_str_dup("a" * 50).freeze) + 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 diff --git a/test/-ext-/string/test_set_len.rb b/test/-ext-/string/test_set_len.rb index 58f51012fb..e3eff75d9b 100644 --- a/test/-ext-/string/test_set_len.rb +++ b/test/-ext-/string/test_set_len.rb @@ -4,23 +4,25 @@ require "-test-/string" class Test_StrSetLen < Test::Unit::TestCase def setup - @s0 = [*"a".."z"].join("").freeze + # 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 = [*"a".."z"].join("") + orig = [*"0"..@range_end].join("") assert_equal(orig, @s0) end def test_non_shared @s1.modify! - assert_equal("abc", @s1.set_len(3)) + assert_equal("012", @s1.set_len(3)) end def test_shared assert_raise(RuntimeError) { - assert_equal("abc", @s1.set_len(3)) + @s1.set_len(3) } end @@ -32,4 +34,33 @@ class Test_StrSetLen < Test::Unit::TestCase 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 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 |