2016-01-27 06:37:02 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
require 'test/unit'
|
|
|
|
require '-test-/string'
|
2016-01-27 07:04:47 -05:00
|
|
|
require 'rbconfig/sizeof'
|
2016-01-27 06:37:02 -05:00
|
|
|
|
|
|
|
class Test_StringCapacity < Test::Unit::TestCase
|
2017-10-22 07:27:06 -04:00
|
|
|
def test_capacity_embedded
|
2022-02-01 09:25:12 -05:00
|
|
|
assert_equal GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] - embed_header_size - 1, capa('foo')
|
2021-08-26 10:06:32 -04:00
|
|
|
assert_equal max_embed_len, capa('1' * max_embed_len)
|
|
|
|
assert_equal max_embed_len, capa('1' * (max_embed_len - 1))
|
2016-01-27 06:37:02 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_capacity_shared
|
2022-02-01 09:25:12 -05:00
|
|
|
sym = ("a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).to_sym
|
|
|
|
assert_equal 0, capa(sym.to_s)
|
2016-01-27 06:37:02 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def test_capacity_normal
|
2021-08-26 10:06:32 -04:00
|
|
|
assert_equal max_embed_len + 1, capa('1' * (max_embed_len + 1))
|
|
|
|
assert_equal max_embed_len + 100, capa('1' * (max_embed_len + 100))
|
2016-02-16 22:21:35 -05:00
|
|
|
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("", String.new(capacity: -1000))
|
|
|
|
assert_equal(capa(String.new(capacity: -10000)), capa(String.new(capacity: -1000)))
|
2016-01-27 06:37:02 -05:00
|
|
|
end
|
2017-08-31 04:21:46 -04:00
|
|
|
|
|
|
|
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
|
Resize capacity for fstring
When a string is #frozen, it's capacity is resized to fit (if it is much
larger), since we know it will no longer be mutated.
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "bytesize":30, "capacity":1000, "value":"...
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000).freeze)
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "bytesize":30, "value":"...
(ObjectSpace.dump doesn't show capacity if capacity is equal to bytesize)
Previously, if we dedup into an fstring, using String#-@, capacity would
not be reduced.
> puts ObjectSpace.dump(-String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "fstring":true, "bytesize":30, "capacity":1000, "value":"...
This commit makes rb_fstring call rb_str_resize, the same as
rb_str_freeze does.
Closes: https://github.com/ruby/ruby/pull/2256
2019-06-25 12:01:57 -04:00
|
|
|
|
|
|
|
def test_literal_capacity
|
2021-08-26 10:06:32 -04:00
|
|
|
s = eval(%{
|
|
|
|
# frozen_string_literal: true
|
|
|
|
"#{"a" * (max_embed_len + 1)}"
|
|
|
|
})
|
Resize capacity for fstring
When a string is #frozen, it's capacity is resized to fit (if it is much
larger), since we know it will no longer be mutated.
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "bytesize":30, "capacity":1000, "value":"...
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000).freeze)
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "bytesize":30, "value":"...
(ObjectSpace.dump doesn't show capacity if capacity is equal to bytesize)
Previously, if we dedup into an fstring, using String#-@, capacity would
not be reduced.
> puts ObjectSpace.dump(-String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "fstring":true, "bytesize":30, "capacity":1000, "value":"...
This commit makes rb_fstring call rb_str_resize, the same as
rb_str_freeze does.
Closes: https://github.com/ruby/ruby/pull/2256
2019-06-25 12:01:57 -04:00
|
|
|
assert_equal(s.length, capa(s))
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_capacity_frozen
|
|
|
|
s = String.new("I am testing", capacity: 1000)
|
2022-02-01 09:25:12 -05:00
|
|
|
s << "a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
|
Resize capacity for fstring
When a string is #frozen, it's capacity is resized to fit (if it is much
larger), since we know it will no longer be mutated.
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "bytesize":30, "capacity":1000, "value":"...
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000).freeze)
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "bytesize":30, "value":"...
(ObjectSpace.dump doesn't show capacity if capacity is equal to bytesize)
Previously, if we dedup into an fstring, using String#-@, capacity would
not be reduced.
> puts ObjectSpace.dump(-String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "fstring":true, "bytesize":30, "capacity":1000, "value":"...
This commit makes rb_fstring call rb_str_resize, the same as
rb_str_freeze does.
Closes: https://github.com/ruby/ruby/pull/2256
2019-06-25 12:01:57 -04:00
|
|
|
s.freeze
|
|
|
|
assert_equal(s.length, capa(s))
|
|
|
|
end
|
|
|
|
|
|
|
|
def test_capacity_fstring
|
2022-02-01 09:25:12 -05:00
|
|
|
s = String.new("a" * max_embed_len, capacity: max_embed_len * 3)
|
Resize capacity for fstring
When a string is #frozen, it's capacity is resized to fit (if it is much
larger), since we know it will no longer be mutated.
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "bytesize":30, "capacity":1000, "value":"...
> puts ObjectSpace.dump(String.new("a"*30, capacity: 1000).freeze)
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "bytesize":30, "value":"...
(ObjectSpace.dump doesn't show capacity if capacity is equal to bytesize)
Previously, if we dedup into an fstring, using String#-@, capacity would
not be reduced.
> puts ObjectSpace.dump(-String.new("a"*30, capacity: 1000))
{"type":"STRING", "class":"0x7feaf00b7bf0", "frozen":true, "fstring":true, "bytesize":30, "capacity":1000, "value":"...
This commit makes rb_fstring call rb_str_resize, the same as
rb_str_freeze does.
Closes: https://github.com/ruby/ruby/pull/2256
2019-06-25 12:01:57 -04:00
|
|
|
s << "fstring capacity"
|
|
|
|
s = -s
|
|
|
|
assert_equal(s.length, capa(s))
|
|
|
|
end
|
2021-08-26 10:06:32 -04:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def capa(str)
|
|
|
|
Bug::String.capacity(str)
|
|
|
|
end
|
|
|
|
|
|
|
|
def embed_header_size
|
|
|
|
if GC.using_rvargc?
|
2022-01-11 15:19:39 -05:00
|
|
|
2 * RbConfig::SIZEOF['void*'] + RbConfig::SIZEOF['long']
|
2021-08-26 10:06:32 -04:00
|
|
|
else
|
|
|
|
2 * RbConfig::SIZEOF['void*']
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def max_embed_len
|
|
|
|
GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE] - embed_header_size - 1
|
|
|
|
end
|
2016-01-27 06:37:02 -05:00
|
|
|
end
|