summaryrefslogtreecommitdiff
path: root/test/-ext-/string
diff options
context:
space:
mode:
Diffstat (limited to 'test/-ext-/string')
-rw-r--r--test/-ext-/string/test_capacity.rb40
-rw-r--r--test/-ext-/string/test_chilled.rb19
-rw-r--r--test/-ext-/string/test_cstr.rb6
-rw-r--r--test/-ext-/string/test_fstring.rb34
-rw-r--r--test/-ext-/string/test_rb_str_dup.rb6
-rw-r--r--test/-ext-/string/test_set_len.rb39
-rw-r--r--test/-ext-/string/test_too_many_dummy_encodings.rb15
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