mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 08:25:20 +08:00
Use adaptive sampling for memory leak tests
Temporary memory growth caused intermittent failures, while repeated warmups made these tests slow.
This commit is contained in:
1 parent
18ec10c7f8
commit
0302df2e41
18 files changed
+121
-157
Notes:
git
2026-10-19 11:52:31 +00:00
No files matched your search
@@ -1752,7 +1752,7 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_return_out_of_compile_error_no_memory_leak
|
||||
assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
|
||||
assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true, samples: 10..100)
|
||||
class MyRipper < Ripper
|
||||
def initialize(src, &blk)
|
||||
super(src)
|
||||
@@ -1767,14 +1767,14 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
|
||||
# Check that call_parse does return a syntax error
|
||||
raise "call_parse should return a syntax error" unless call_parse
|
||||
begin;
|
||||
100_000.times do
|
||||
1_000.times do
|
||||
call_parse
|
||||
end
|
||||
end;
|
||||
end
|
||||
|
||||
def test_return_out_of_warn_no_memory_leak
|
||||
assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
|
||||
def test_return_out_of_warn_dup_keys_no_memory_leak
|
||||
assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true, samples: 10..100)
|
||||
class MyRipper < Ripper
|
||||
def initialize(src, &blk)
|
||||
super(src)
|
||||
@@ -1789,12 +1789,14 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
|
||||
# Check that call_parse does warn
|
||||
raise "call_parse should warn" unless call_parse
|
||||
begin;
|
||||
500_000.times do
|
||||
1_000.times do
|
||||
call_parse
|
||||
end
|
||||
end;
|
||||
end
|
||||
|
||||
assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
|
||||
def test_return_out_of_warn_token_info_no_memory_leak
|
||||
assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true, samples: 10..100)
|
||||
class MyRipper < Ripper
|
||||
def initialize(src, &blk)
|
||||
super(src)
|
||||
@@ -1810,7 +1812,7 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
|
||||
# Check that call_parse does warn
|
||||
raise "call_parse should warn" unless call_parse
|
||||
begin;
|
||||
1_000_000.times do
|
||||
1_000.times do
|
||||
call_parse
|
||||
end
|
||||
end;
|
||||
|
||||
+27
-16
@@ -167,41 +167,52 @@ end
|
||||
assert_empty(lex)
|
||||
end
|
||||
|
||||
def test_no_memory_leak
|
||||
assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
|
||||
2_000_000.times do
|
||||
def test_empty_no_memory_leak
|
||||
assert_no_memory_leak(%w(-rripper), "", "#{<<-"{#"}\n#{<<-'};'}", rss: true, samples: 2..100)
|
||||
{#
|
||||
1000.times do
|
||||
Ripper.parse("")
|
||||
end
|
||||
end;
|
||||
};
|
||||
end
|
||||
|
||||
def test_unclosed_class_no_memory_leak
|
||||
# [Bug #19835]
|
||||
assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
|
||||
1_000_000.times do
|
||||
assert_no_memory_leak(%w(-rripper), "", "#{<<-"{#"}\n#{<<-'};'}", rss: true, samples: 2..100)
|
||||
{#
|
||||
1000.times do
|
||||
Ripper.parse("class Foo")
|
||||
end
|
||||
end;
|
||||
};
|
||||
end
|
||||
|
||||
def test_unclosed_lambda_no_memory_leak
|
||||
# [Bug #19836]
|
||||
assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
|
||||
1_000_000.times do
|
||||
assert_no_memory_leak(%w(-rripper), "", "#{<<-"{#"}\n#{<<-'};'}", rss: true, samples: 2..100)
|
||||
{#
|
||||
1000.times do
|
||||
Ripper.parse("-> {")
|
||||
end
|
||||
end;
|
||||
};
|
||||
end
|
||||
|
||||
def test_lambda_it_no_memory_leak
|
||||
# [Bug #21004]
|
||||
assert_no_memory_leak(%w(-rripper), "", <<~RUBY, rss: true)
|
||||
1_000_000.times do
|
||||
assert_no_memory_leak(%w(-rripper), "", "#{<<-"{#"}\n#{<<-'};'}", rss: true, samples: 2..100)
|
||||
{#
|
||||
1000.times do
|
||||
Ripper.parse("-> do it end")
|
||||
end
|
||||
RUBY
|
||||
};
|
||||
end
|
||||
|
||||
def test_sexp_no_memory_leak
|
||||
assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
|
||||
1_000_000.times do
|
||||
assert_no_memory_leak(%w(-rripper), "", "#{<<-"{#"}\n#{<<-'};'}", rss: true, samples: 2..100)
|
||||
{#
|
||||
1000.times do
|
||||
Ripper.sexp("")
|
||||
end
|
||||
end;
|
||||
};
|
||||
end
|
||||
|
||||
class TestInput < self
|
||||
|
||||
@@ -2058,11 +2058,10 @@ class TestArray < Test::Unit::TestCase
|
||||
|
||||
def test_short_heap_array_sort_bang_memory_leak
|
||||
bug11332 = '[ruby-dev:49166] [Bug #11332]'
|
||||
assert_no_memory_leak([], <<-PREP, <<-TEST, bug11332, limit: 1.3, timeout: 60)
|
||||
assert_no_memory_leak([], <<-PREP, <<-TEST, bug11332, limit: 1.3, timeout: 60, samples: 2..100)
|
||||
def t; ary = [*1..5]; ary.pop(2); ary.sort!; end
|
||||
1.times {t}
|
||||
PREP
|
||||
500000.times {t}
|
||||
5_000.times {t}
|
||||
TEST
|
||||
end
|
||||
|
||||
|
||||
@@ -346,14 +346,13 @@ class TestAst < Test::Unit::TestCase
|
||||
|
||||
def test_invalid_yield_no_memory_leak
|
||||
# [Bug #21383]
|
||||
assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true)
|
||||
assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true, samples: 2..100)
|
||||
code = proc do
|
||||
eval("class C; yield; end")
|
||||
rescue SyntaxError
|
||||
end
|
||||
1_000.times(&code)
|
||||
begin;
|
||||
100_000.times(&code)
|
||||
200.times(&code)
|
||||
end;
|
||||
end
|
||||
|
||||
|
||||
@@ -928,12 +928,7 @@ class TestClass < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_classext_memory_leak
|
||||
assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
|
||||
code = proc { Class.new }
|
||||
1_000.times(&code)
|
||||
PREP
|
||||
3_000_000.times(&code)
|
||||
CODE
|
||||
assert_no_memory_leak([], "", "30_000.times {Class.new}", rss: true, samples: 2..100)
|
||||
end
|
||||
|
||||
def test_instance_freeze_dont_freeze_the_class_bug_19164
|
||||
|
||||
@@ -614,9 +614,9 @@ class TestEval < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_syntax_error_no_memory_leak
|
||||
assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
|
||||
assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", rss: true, samples: 5)
|
||||
begin;
|
||||
100_000.times do
|
||||
20_000.times do
|
||||
eval("/[/=~s")
|
||||
rescue SyntaxError
|
||||
else
|
||||
|
||||
+11
-15
@@ -179,9 +179,9 @@ class TestHash < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_st_literal_memory_leak
|
||||
assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", rss: true)
|
||||
assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", rss: true, samples: 5)
|
||||
begin;
|
||||
1_000_000.times do
|
||||
200_000.times do
|
||||
# >8 element hashes are ST allocated rather than AR allocated
|
||||
{a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}
|
||||
end
|
||||
@@ -1523,10 +1523,10 @@ class TestHash < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_compare_by_identy_memory_leak
|
||||
assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #20145]", rss: true)
|
||||
assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #20145]", rss: true, samples: 5)
|
||||
begin;
|
||||
h = { 1 => 2 }.compare_by_identity
|
||||
1_000_000.times do
|
||||
200_000.times do
|
||||
h.select { false }
|
||||
end
|
||||
end;
|
||||
@@ -1995,9 +1995,9 @@ class TestHashOnly < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_st_literal_memory_leak
|
||||
assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", rss: true)
|
||||
assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", rss: true, samples: 5)
|
||||
begin;
|
||||
1_000_000.times do
|
||||
200_000.times do
|
||||
# >8 element hashes are ST allocated rather than AR allocated
|
||||
{a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}
|
||||
end
|
||||
@@ -2096,17 +2096,14 @@ class TestHashOnly < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_rehash_memory_leak
|
||||
assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
|
||||
assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true, samples: 2..100)
|
||||
ar_hash = 1.times.map { |i| [i, i] }.to_h
|
||||
st_hash = 10.times.map { |i| [i, i] }.to_h
|
||||
|
||||
code = proc do
|
||||
PREP
|
||||
10_000.times do
|
||||
ar_hash.rehash
|
||||
st_hash.rehash
|
||||
end
|
||||
1_000.times(&code)
|
||||
PREP
|
||||
1_000_000.times(&code)
|
||||
CODE
|
||||
end
|
||||
|
||||
@@ -2172,11 +2169,10 @@ class TestHashOnly < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_replace_memory_leak
|
||||
assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true)
|
||||
assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true, samples: 2..100)
|
||||
h = ("aa".."zz").each_with_index.to_h
|
||||
10_000.times {h.dup}
|
||||
begin;
|
||||
500_000.times {h.dup.replace(h)}
|
||||
5_000.times {h.dup.replace(h)}
|
||||
end;
|
||||
end
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ class TestISeq < Test::Unit::TestCase
|
||||
|
||||
def test_invalid_source_no_memory_leak
|
||||
# [Bug #21394]
|
||||
assert_no_memory_leak(["-rtempfile"], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true)
|
||||
assert_no_memory_leak(["-rtempfile"], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true, samples: 2..100)
|
||||
code = proc do |t|
|
||||
RubyVM::InstructionSequence.new(nil)
|
||||
rescue TypeError
|
||||
@@ -329,9 +329,8 @@ class TestISeq < Test::Unit::TestCase
|
||||
raise "TypeError was not raised during RubyVM::InstructionSequence.new"
|
||||
end
|
||||
|
||||
10.times(&code)
|
||||
begin;
|
||||
1_000_000.times(&code)
|
||||
10_000.times(&code)
|
||||
end;
|
||||
|
||||
# [Bug #21394]
|
||||
@@ -985,10 +984,10 @@ class TestISeq < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_loading_kwargs_memory_leak
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", rss: true)
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", rss: true, samples: 5)
|
||||
a = RubyVM::InstructionSequence.compile("foo(bar: :baz)").to_binary
|
||||
begin;
|
||||
1_000_000.times do
|
||||
200_000.times do
|
||||
RubyVM::InstructionSequence.load_from_binary(a)
|
||||
end
|
||||
end;
|
||||
|
||||
@@ -1812,11 +1812,11 @@ class TestMethod < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_kwarg_eval_memory_leak
|
||||
assert_no_memory_leak([], "", <<~RUBY, rss: true, limit: 1.2)
|
||||
assert_no_memory_leak([], "", <<~RUBY, rss: true, limit: 1.2, samples: 5)
|
||||
obj = Object.new
|
||||
def obj.test(**kwargs) = nil
|
||||
|
||||
100_000.times do
|
||||
20_000.times do
|
||||
eval("obj.test(foo: 123)")
|
||||
end
|
||||
RUBY
|
||||
|
||||
@@ -3429,23 +3429,20 @@ class TestModule < Test::Unit::TestCase
|
||||
|
||||
def test_iclass_memory_leak
|
||||
# [Bug #19550]
|
||||
assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
|
||||
code = proc do
|
||||
assert_no_memory_leak([], "", <<~CODE, rss: true, samples: 2..30)
|
||||
100_000.times do
|
||||
mod = Module.new
|
||||
Class.new do
|
||||
include mod
|
||||
end
|
||||
end
|
||||
1_000.times(&code)
|
||||
PREP
|
||||
3_000_000.times(&code)
|
||||
CODE
|
||||
end
|
||||
|
||||
def test_complemented_method_entry_memory_leak
|
||||
# [Bug #19894] [Bug #19896]
|
||||
assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
|
||||
code = proc do
|
||||
assert_no_memory_leak([], "", <<~CODE, rss: true, samples: 2..30)
|
||||
10_000.times do
|
||||
$c = Class.new do
|
||||
def foo; end
|
||||
end
|
||||
@@ -3465,21 +3462,15 @@ class TestModule < Test::Unit::TestCase
|
||||
end
|
||||
end.new
|
||||
end
|
||||
1_000.times(&code)
|
||||
PREP
|
||||
300_000.times(&code)
|
||||
CODE
|
||||
end
|
||||
|
||||
def test_module_clone_memory_leak
|
||||
# [Bug #19901]
|
||||
assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
|
||||
code = proc do
|
||||
assert_no_memory_leak([], "", <<~CODE, rss: true, samples: 2..100)
|
||||
10_000.times do
|
||||
Module.new.clone
|
||||
end
|
||||
1_000.times(&code)
|
||||
PREP
|
||||
1_000_000.times(&code)
|
||||
CODE
|
||||
end
|
||||
|
||||
|
||||
+13
-16
@@ -1009,39 +1009,36 @@ class TestRegexp < Test::Unit::TestCase
|
||||
# partially parsed branch (parse_subexp freed the alternation list but not
|
||||
# the node parse_branch had built so far). Regexp#to_s reaches this path
|
||||
# for every /(?:a|b)c(d)/-shaped regexp.
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~"end;"}", "[Bug #22384]", rss: true)
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~"end;"}", "[Bug #22384]", rss: true, samples: 2..100)
|
||||
code = proc do
|
||||
Regexp.new("a|b(c") rescue nil
|
||||
/(?:a|b)c(d)/.to_s
|
||||
end
|
||||
|
||||
1_000.times(&code)
|
||||
begin;
|
||||
300_000.times(&code)
|
||||
3_000.times(&code)
|
||||
end;
|
||||
end
|
||||
|
||||
def test_regsub_no_memory_leak
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~"end;"}", rss: true)
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~"end;"}", rss: true, samples: 2..100)
|
||||
code = proc do
|
||||
"aaaaaaaaaaa".gsub(/a/, "")
|
||||
end
|
||||
|
||||
1_000.times(&code)
|
||||
begin;
|
||||
100_000.times(&code)
|
||||
1_000.times(&code)
|
||||
end;
|
||||
end
|
||||
|
||||
def test_regsub_no_memory_leak_many_captures
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~"end;"}", rss: true)
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~"end;"}", rss: true, samples: 2..100)
|
||||
code = proc do
|
||||
"aaaaaaaaaaa".gsub(/(a)(b)?(c)?(d)?(e)?(f)?(g)?(h)?/, "")
|
||||
end
|
||||
|
||||
1_000.times(&code)
|
||||
begin;
|
||||
100_000.times(&code)
|
||||
1_000.times(&code)
|
||||
end;
|
||||
end
|
||||
|
||||
@@ -2107,10 +2104,10 @@ class TestRegexp < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_s_timeout_memory_leak
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~"end;"}", "[Bug #20228]", rss: true)
|
||||
Regexp.timeout = 0.001
|
||||
regex = /^(a*)*$/
|
||||
str = "a" * 1000000 + "x"
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", "[Bug #20228]", rss: true, samples: 100..200)
|
||||
Regexp.timeout = 0.000001
|
||||
regex = Regexp.new("^#{"(a*)" * 10_000}x$")
|
||||
str = "a" * 1_000_000 + "x"
|
||||
|
||||
code = proc do
|
||||
regex =~ str
|
||||
@@ -2119,7 +2116,7 @@ class TestRegexp < Test::Unit::TestCase
|
||||
|
||||
10.times(&code)
|
||||
begin;
|
||||
1_000.times(&code)
|
||||
100.times(&code)
|
||||
end;
|
||||
end
|
||||
|
||||
@@ -2196,7 +2193,7 @@ class TestRegexp < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_timeout_memory_leak
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", "[Bug #20650]", timeout: 100, rss: true)
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", "[Bug #20650]", rss: true, samples: 100..200)
|
||||
regex = Regexp.new("^#{"(a*)" * 10_000}x$", timeout: 0.000001)
|
||||
str = "a" * 1_000_000 + "x"
|
||||
|
||||
@@ -2207,7 +2204,7 @@ class TestRegexp < Test::Unit::TestCase
|
||||
|
||||
10.times(&code)
|
||||
begin;
|
||||
1_000.times(&code)
|
||||
100.times(&code)
|
||||
end;
|
||||
end
|
||||
|
||||
|
||||
@@ -652,12 +652,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
|
||||
|
||||
# Bug #18264
|
||||
def test_tracepoint_memory_leak
|
||||
assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
|
||||
code = proc { TracePoint.new(:line) { } }
|
||||
1_000.times(&code)
|
||||
PREP
|
||||
1_000_000.times(&code)
|
||||
CODE
|
||||
assert_no_memory_leak([], "", "10_000.times {TracePoint.new(:line) { }}", rss: true, samples: 2..100)
|
||||
end
|
||||
|
||||
def test_tracepoint_bmethod_memory_leak
|
||||
|
||||
@@ -570,21 +570,19 @@ class TestShapes < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_evacuate_generic_ivar_memory_leak
|
||||
assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
|
||||
assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", rss: true, samples: 5)
|
||||
o = []
|
||||
o.instance_variable_set(:@a, 1)
|
||||
|
||||
RubyVM::Shape.exhaust_shapes
|
||||
|
||||
ary = 1_000_000.times.map { [] }
|
||||
begin;
|
||||
ary = Array.new(200_000) { [] }
|
||||
ary.each do |o|
|
||||
o.instance_variable_set(:@a, 1)
|
||||
o.instance_variable_set(:@b, 1)
|
||||
end
|
||||
ary.clear
|
||||
ary = nil
|
||||
GC.start
|
||||
end;
|
||||
end
|
||||
|
||||
@@ -1180,13 +1178,13 @@ class TestShapes < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_duplicating_complex_objects_memory_leak
|
||||
assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", "[Bug #20162]", rss: true)
|
||||
assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", "[Bug #20162]", rss: true, samples: 5)
|
||||
RubyVM::Shape.exhaust_shapes
|
||||
|
||||
o = Object.new
|
||||
o.instance_variable_set(:@a, 0)
|
||||
begin;
|
||||
1_000_000.times do
|
||||
200_000.times do
|
||||
o.dup
|
||||
end
|
||||
end;
|
||||
|
||||
+26
-37
@@ -104,24 +104,18 @@ class TestString < Test::Unit::TestCase
|
||||
def test_initialize_memory_leak
|
||||
return unless @cls == String
|
||||
|
||||
assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
|
||||
code = proc {('x'*100_000).__send__(:initialize, '')}
|
||||
1_000.times(&code)
|
||||
PREP
|
||||
100_000.times(&code)
|
||||
CODE
|
||||
assert_no_memory_leak([], '', <<-CODE, rss: true, samples: 2..100)
|
||||
1_000.times {('x'*100_000).__send__(:initialize, '')}
|
||||
CODE
|
||||
end
|
||||
|
||||
# Bug #18154
|
||||
def test_initialize_nofree_memory_leak
|
||||
return unless @cls == String
|
||||
|
||||
assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
|
||||
code = proc {0.to_s.__send__(:initialize, capacity: 100_000)}
|
||||
1_000.times(&code)
|
||||
PREP
|
||||
100_000.times(&code)
|
||||
CODE
|
||||
assert_no_memory_leak([], '', <<-CODE, rss: true, samples: 2..100)
|
||||
1_000.times {0.to_s.__send__(:initialize, capacity: 100_000)}
|
||||
CODE
|
||||
end
|
||||
|
||||
def test_AREF # '[]'
|
||||
@@ -765,12 +759,14 @@ CODE
|
||||
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;
|
||||
if @cls == String
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", samples: 2..100)
|
||||
s = ''
|
||||
salt = -""#{(crypt_supports_des_crypt? ? '..' : good_salt).dump}
|
||||
begin;
|
||||
10.times { s.crypt(salt).clear }
|
||||
end;
|
||||
end
|
||||
end
|
||||
|
||||
def test_delete
|
||||
@@ -2489,18 +2485,14 @@ CODE
|
||||
end
|
||||
|
||||
def test_start_with_timeout_memory_leak
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", "[Bug #20653]", rss: true)
|
||||
assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", "[Bug #20653]", rss: true, samples: 2..100)
|
||||
regex = Regexp.new("^#{"(a*)" * 10_000}x$", timeout: 0.000001)
|
||||
str = "a" * 1_000_000 + "x"
|
||||
|
||||
code = proc do
|
||||
begin;
|
||||
10.times do
|
||||
str.start_with?(regex)
|
||||
rescue
|
||||
end
|
||||
|
||||
10.times(&code)
|
||||
begin;
|
||||
1_000.times(&code)
|
||||
end;
|
||||
end
|
||||
|
||||
@@ -4520,12 +4512,11 @@ CODE
|
||||
def fallback.[](_str) = raise MyError
|
||||
RUBY
|
||||
}.each do |type, code|
|
||||
assert_no_memory_leak([], '', <<~RUBY, "fallback type is #{type}", rss: true)
|
||||
assert_no_memory_leak([], <<~PREPARE, <<~RUBY, "fallback type is #{type}", rss: true, samples: 2..100)
|
||||
class MyError < StandardError; end
|
||||
|
||||
#{code}
|
||||
|
||||
100_000.times do |i|
|
||||
PREPARE
|
||||
1000.times do |i|
|
||||
"\\ufffd".encode(Encoding::US_ASCII, fallback:)
|
||||
rescue MyError
|
||||
end
|
||||
@@ -4550,12 +4541,11 @@ CODE
|
||||
def fallback.[](_str) = "\\uffee"
|
||||
RUBY
|
||||
}.each do |type, code|
|
||||
assert_no_memory_leak([], '', <<~RUBY, "fallback type is #{type}", rss: true)
|
||||
assert_no_memory_leak([], <<~PREPARE, <<~RUBY, "fallback type is #{type}", rss: true, samples: 2..100)
|
||||
class MyError < StandardError; end
|
||||
|
||||
#{code}
|
||||
|
||||
100_000.times do |i|
|
||||
PREPARE
|
||||
1000.times do |i|
|
||||
"\\ufffd".encode(Encoding::US_ASCII, fallback:)
|
||||
rescue ArgumentError
|
||||
end
|
||||
@@ -4580,12 +4570,11 @@ CODE
|
||||
def fallback.[](_str) = Object.new
|
||||
RUBY
|
||||
}.each do |type, code|
|
||||
assert_no_memory_leak([], '', <<~RUBY, "fallback type is #{type}", rss: true)
|
||||
assert_no_memory_leak([], <<~PREPARE, <<~RUBY, "fallback type is #{type}", rss: true, samples: 2..100)
|
||||
class MyError < StandardError; end
|
||||
|
||||
#{code}
|
||||
|
||||
100_000.times do |i|
|
||||
PREPARE
|
||||
1000.times do |i|
|
||||
"\\ufffd".encode(Encoding::US_ASCII, fallback:)
|
||||
rescue TypeError
|
||||
end
|
||||
|
||||
@@ -548,15 +548,13 @@ module TestStruct
|
||||
omit 'skip on riscv64-linux CI machine. See https://github.com/ruby/ruby/pull/13422' if ENV['RUBY_DEBUG'] == 'ci' && /riscv64-linux/ =~ RUBY_DESCRIPTION
|
||||
|
||||
# [Bug #20311]
|
||||
assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true, limit: 2.2)
|
||||
assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true, limit: 2.2, samples: 2..50)
|
||||
code = proc do
|
||||
Struct.new("A")
|
||||
Struct.send(:remove_const, :A)
|
||||
end
|
||||
|
||||
10_000.times(&code)
|
||||
PREP
|
||||
50_000.times(&code)
|
||||
1_000.times(&code)
|
||||
CODE
|
||||
end
|
||||
|
||||
|
||||
@@ -1533,17 +1533,14 @@ eom
|
||||
end
|
||||
|
||||
def test_invalid_symbol_in_hash_memory_leak
|
||||
assert_no_memory_leak([], "#{<<-'begin;'}", "#{<<-'end;'}", rss: true)
|
||||
assert_no_memory_leak([], "#{<<-'begin;'}", "#{<<-'end;'}", rss: true, samples: 2..1_000)
|
||||
str = '{"\xC3": 1}'.force_encoding("UTF-8")
|
||||
code = proc do
|
||||
begin;
|
||||
1_000.times do
|
||||
eval(str)
|
||||
raise "unreachable"
|
||||
rescue SyntaxError
|
||||
end
|
||||
|
||||
1_000.times(&code)
|
||||
begin;
|
||||
1_000_000.times(&code)
|
||||
end;
|
||||
end
|
||||
|
||||
@@ -2471,16 +2468,15 @@ eom
|
||||
end
|
||||
|
||||
def test_argument_forwarding_with_super_memory_leak
|
||||
assert_no_memory_leak([], "#{<<-'begin;'}", "#{<<-'end;'}", rss: true)
|
||||
assert_no_memory_leak([], "#{<<-'begin;'}", "#{<<-'end;'}", rss: true, samples: 2..100)
|
||||
code = proc do
|
||||
eval("def foo(...) super(...) {}; end")
|
||||
raise "unreachable"
|
||||
rescue SyntaxError
|
||||
end
|
||||
|
||||
1_000.times(&code)
|
||||
begin;
|
||||
100_000.times(&code)
|
||||
1_000.times(&code)
|
||||
end;
|
||||
end
|
||||
|
||||
|
||||
@@ -204,9 +204,9 @@ class TestWeakMap < Test::Unit::TestCase
|
||||
end
|
||||
|
||||
def test_no_memory_leak
|
||||
assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #19398]", rss: true, limit: 1.5, timeout: 60)
|
||||
assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #19398]", rss: true, limit: 1.5, timeout: 60, samples: 5)
|
||||
begin;
|
||||
1_000_000.times do
|
||||
200_000.times do
|
||||
ObjectSpace::WeakMap.new
|
||||
end
|
||||
end;
|
||||
|
||||
@@ -522,12 +522,11 @@ class TestSocketAddrinfo < Test::Unit::TestCase
|
||||
|
||||
def test_marshal_memory_leak
|
||||
bug11051 = '[ruby-dev:48923] [Bug #11051]'
|
||||
assert_no_memory_leak(%w[-rsocket], <<-PREP, <<-CODE, bug11051, rss: true)
|
||||
assert_no_memory_leak(%w[-rsocket], <<-PREP, <<-CODE, bug11051, rss: true, samples: 2..20)
|
||||
d = Marshal.dump(Addrinfo.tcp("127.0.0.1", 80))
|
||||
1000.times {Marshal.load(d)}
|
||||
PREP
|
||||
GC.start
|
||||
20_000.times {Marshal.load(d)}
|
||||
1_000.times {Marshal.load(d)}
|
||||
CODE
|
||||
end
|
||||
|
||||
|
||||
Reference in new issue
Block a user