From aa7eb97d062e260f0d704b78e93c470ac8444129 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 8 Jan 2026 19:09:59 -0500 Subject: [PATCH 1/8] [ruby/mmtk] Add MMTK_ASSERT https://github.com/ruby/mmtk/commit/e34d5cf32f --- gc/mmtk/mmtk.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c index 38e730a3761e4d..7b70ddff5e61f6 100644 --- a/gc/mmtk/mmtk.c +++ b/gc/mmtk/mmtk.c @@ -83,6 +83,12 @@ RB_THREAD_LOCAL_SPECIFIER VALUE marking_parent_object; # error We currently need language-supported TLS #endif +#ifdef MMTK_DEBUG +# define MMTK_ASSERT(expr, ...) RUBY_ASSERT_ALWAYS(expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__)) +#else +# define MMTK_ASSERT(expr, ...) ((void)0) +#endif + #include static void From e89db8567c20692eabea70a4997a6ba325a347f8 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Thu, 8 Jan 2026 19:10:08 -0500 Subject: [PATCH 2/8] [ruby/mmtk] Assert that objects are not T_NONE in the write barrier https://github.com/ruby/mmtk/commit/59d27203e2 --- gc/mmtk/mmtk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c index 7b70ddff5e61f6..03210536131a09 100644 --- a/gc/mmtk/mmtk.c +++ b/gc/mmtk/mmtk.c @@ -981,6 +981,9 @@ rb_gc_impl_writebarrier(void *objspace_ptr, VALUE a, VALUE b) } #endif + MMTK_ASSERT(BUILTIN_TYPE(a) != T_NONE); + MMTK_ASSERT(BUILTIN_TYPE(b) != T_NONE); + mmtk_object_reference_write_post(cache->mutator, (MMTk_ObjectReference)a); } From b61e18d76b939d7e5e18f61a426b14a110f95b7c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 8 Jan 2026 19:40:56 +0900 Subject: [PATCH 3/8] Win32: configure without an intermediate makefile This batch file used `nmake` on the old `command.com` to extract the parent directory name of this file and to get around the command line argument length limit. However, Windows 9X support as a build host ended over a decade ago, and this file now utilizes the functionality of `cmd.exe` already. --- win32/configure.bat | 32 +++++++++++++++----------------- win32/setup.mak | 8 +++++--- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/win32/configure.bat b/win32/configure.bat index 181813f4ad1581..9355caa4d852da 100755 --- a/win32/configure.bat +++ b/win32/configure.bat @@ -3,15 +3,24 @@ set PROMPT=$E[94m+$E[m$S set witharg= -for %%I in (%0) do if /%%~dpI/ == /%CD%\/ ( +if "%~dp0" == "%CD%\" ( echo don't run in win32 directory. exit /b 999 +) else if "%0" == "%~nx0" ( + set "WIN32DIR=%~$PATH:0" +) else if "%0" == "%~n0" ( + set "WIN32DIR=%~$PATH:0" +) else ( + set "WIN32DIR=%0" ) +set "WIN32DIR=%WIN32DIR:\=/%:/:" +call set "WIN32DIR=%%WIN32DIR:%~x0:/:=:/:%%" +call set "WIN32DIR=%%WIN32DIR:/%~n0:/:=:/:%%" +set "WIN32DIR=%WIN32DIR:~0,-3%" + set XINCFLAGS= set XLDFLAGS= - -set conf=%0 set pathlist= set config_make=confargs~%RANDOM%.mak set confargs=%config_make:.mak=.c% @@ -305,19 +314,8 @@ goto :exit ) >> %config_make% del %confargs% > nul -set setup_make=%config_make:confargs=setup% -( - echo #### -*- makefile -*- - echo conf = %conf% - echo $^(conf^): nul - echo @del %setup_make% - echo @$^(MAKE^) -l$^(MAKEFLAGS^) -f $^(@D^)/setup.mak \ - echo WIN32DIR=$^(@D:\=/^) config_make=%config_make% - echo -@move /y Makefile Makefile.old ^> nul 2^> nul - echo @ren Makefile.new Makefile -) > %setup_make% -nmake -alf %setup_make% MAKEFILE=Makefile.new - -exit /b %ERRORLEVEL% +nmake -al -f %WIN32DIR%/setup.mak "WIN32DIR=%WIN32DIR%" ^ + config_make=%config_make% ^ + MAKEFILE=Makefile.new MAKEFILE_BACK=Makefile.old MAKEFILE_NEW=Makefile :exit @endlocal diff --git a/win32/setup.mak b/win32/setup.mak index de8db870ba69eb..77b7d2f406a1dc 100644 --- a/win32/setup.mak +++ b/win32/setup.mak @@ -40,7 +40,7 @@ x64-mswin64: -prologue- -x64- -epilogue- -generic-: -osname- -basic-vars-: nul - @type << > $(MAKEFILE) + @rem <<$(MAKEFILE) ### Makefile for ruby $(TARGET_OS) ### MAKE = nmake srcdir = $(srcdir:\=/) @@ -146,8 +146,8 @@ main(void) << @( \ $(CC) -O2 $@.c && .\$@ || \ - set bug=%ERRORLEVEL% \ - echo This compiler has an optimization bug \ + (set bug=%ERRORLEVEL% & \ + echo This compiler has an optimization bug) \ ) & $(WIN32DIR:/=\)\rm.bat $@.* & exit /b %bug% -version-: nul verconf.mk @@ -272,4 +272,6 @@ AS = $(AS) -nologo $(BANG)include $$(srcdir)/win32/Makefile.sub << @$(COMSPEC) /C $(srcdir:/=\)\win32\rm.bat config.h config.status + -@move /y $(MAKEFILE_NEW) $(MAKEFILE_BACK) > nul 2> nul + @ren $(MAKEFILE) $(MAKEFILE_NEW) @echo type 'nmake' to make ruby. From 3185786874315ab4f1cfcc73c3d1b14613452905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rmungandrk?= Date: Fri, 9 Jan 2026 10:22:01 +0700 Subject: [PATCH 4/8] Fix integer overflow checks in enumerator --- enumerator.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/enumerator.c b/enumerator.c index 8580c605dffc16..292ddb0419fb8a 100644 --- a/enumerator.c +++ b/enumerator.c @@ -18,6 +18,7 @@ #include #endif +#include #include "id.h" #include "internal.h" #include "internal/class.h" @@ -4008,7 +4009,7 @@ arith_seq_take(VALUE self, VALUE num) ary = rb_ary_new_capa((n < len) ? n : len); while (n > 0 && i < end) { rb_ary_push(ary, LONG2FIX(i)); - if (i + unit < i) break; + if (i > LONG_MAX - unit) break; i += unit; --n; } @@ -4021,7 +4022,7 @@ arith_seq_take(VALUE self, VALUE num) ary = rb_ary_new_capa((n < len) ? n : len); while (n > 0 && i > end) { rb_ary_push(ary, LONG2FIX(i)); - if (i + unit > i) break; + if (i < LONG_MIN - unit) break; i += unit; --n; } From 364e25b1c3b7771c84b27e572796165c9b11b969 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 2 Jan 2026 09:37:59 +0900 Subject: [PATCH 5/8] Make `assert_separately` tolerant to core method redefinitions And split `TestRubyOptimization#test_objtostring` for each target class. --- test/ruby/test_optimization.rb | 8 +++++++- tool/lib/core_assertions.rb | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 089c5fbd1d0dc6..cfa90b8b8a0f25 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -1080,7 +1080,7 @@ def test_optimized_rescue class Objtostring end - def test_objtostring + def test_objtostring_immediate assert_raise(NoMethodError){"#{BasicObject.new}"} assert_redefine_method('Symbol', 'to_s', <<-'end') assert_match %r{\A#\z}, "#{:foo}" @@ -1094,11 +1094,17 @@ def test_objtostring assert_redefine_method('FalseClass', 'to_s', <<-'end') assert_match %r{\A#\z}, "#{false}" end + end + + def test_objtostring_fixnum assert_redefine_method('Integer', 'to_s', <<-'end') (-1..10).each { |i| assert_match %r{\A#\z}, "#{i}" } end + end + + def test_objtostring assert_equal "TestRubyOptimization::Objtostring", "#{Objtostring}" assert_match %r{\A#\z}, "#{Class.new}" assert_match %r{\A#\z}, "#{Module.new}" diff --git a/tool/lib/core_assertions.rb b/tool/lib/core_assertions.rb index ed38a34f225346..8aafd8882e6b98 100644 --- a/tool/lib/core_assertions.rb +++ b/tool/lib/core_assertions.rb @@ -303,9 +303,35 @@ def assert_ruby_status(args, test_stdin="", message=nil, **opt) def separated_runner(token, out = nil) include(*Test::Unit::TestCase.ancestors.select {|c| !c.is_a?(Class) }) + out = out ? IO.new(out, 'w') : STDOUT + + # avoid method redefinitions + out_write = out.method(:write) + integer_to_s = Integer.instance_method(:to_s) + array_pack = Array.instance_method(:pack) + marshal_dump = Marshal.method(:dump) + assertions_ivar_set = Test::Unit::Assertions.method(:instance_variable_set) + assertions_ivar_get = Test::Unit::Assertions.method(:instance_variable_get) + Test::Unit::Assertions.module_eval do + @_assertions = 0 + + undef _assertions= + define_method(:_assertions=, ->(n) {assertions_ivar_set.call(:@_assertions, n)}) + + undef _assertions + define_method(:_assertions, -> {assertions_ivar_get.call(:@_assertions)}) + end + # assume Method#call and UnboundMethod#bind_call need to work as the original + at_exit { - out.puts "#{token}", [Marshal.dump($!)].pack('m'), "#{token}", "#{token}assertions=#{self._assertions}" + assertions = assertions_ivar_get.call(:@_assertions) + out_write.call <<~OUT + #{token} + #{array_pack.bind_call([marshal_dump.call($!)], 'm')} + #{token} + #{token}assertions=#{integer_to_s.bind_call(assertions)} + OUT } if defined?(Test::Unit::Runner) Test::Unit::Runner.class_variable_set(:@@stop_auto_run, true) @@ -360,7 +386,9 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o raise if $! abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig)) assert(!abort, FailDesc[status, nil, stderr]) - self._assertions += res[/^#{token_re}assertions=(\d+)/, 1].to_i + if (assertions = res[/^#{token_re}assertions=(\d+)/, 1].to_i) > 0 + self._assertions += assertions + end begin res = Marshal.load(res[/^#{token_re}\n\K.*\n(?=#{token_re}<\/error>$)/m].unpack1("m")) rescue => marshal_error From fc0c67deb2195c51661b6c35eb41cfb2cb92e3f8 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 3 Jan 2026 12:20:35 +0900 Subject: [PATCH 6/8] Make `assert_separately` to count assertions in forked processes --- tool/lib/core_assertions.rb | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/tool/lib/core_assertions.rb b/tool/lib/core_assertions.rb index 8aafd8882e6b98..419704448ba2fa 100644 --- a/tool/lib/core_assertions.rb +++ b/tool/lib/core_assertions.rb @@ -327,10 +327,9 @@ def separated_runner(token, out = nil) at_exit { assertions = assertions_ivar_get.call(:@_assertions) out_write.call <<~OUT - #{token} - #{array_pack.bind_call([marshal_dump.call($!)], 'm')} - #{token} - #{token}assertions=#{integer_to_s.bind_call(assertions)} + + #{array_pack.bind_call([marshal_dump.call($!)], 'm0')} + OUT } if defined?(Test::Unit::Runner) @@ -385,17 +384,17 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o end raise if $! abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig)) + assertions = 0 + marshal_error = nil assert(!abort, FailDesc[status, nil, stderr]) - if (assertions = res[/^#{token_re}assertions=(\d+)/, 1].to_i) > 0 - self._assertions += assertions - end - begin - res = Marshal.load(res[/^#{token_re}\n\K.*\n(?=#{token_re}<\/error>$)/m].unpack1("m")) + res.scan(/^\n(.*?)\n(?=<\/error id="#{token_re}">$)/m) do + assertions += $1.to_i + res = Marshal.load($2.unpack1("m")) or next rescue => marshal_error ignore_stderr = nil res = nil - end - if res and !(SystemExit === res) + else + next if SystemExit === res if bt = res.backtrace bt.each do |l| l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"} @@ -407,7 +406,7 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o raise res end - # really is it succeed? + # really did it succeed? unless ignore_stderr # the body of assert_separately must not output anything to detect error assert(stderr.empty?, FailDesc[status, "assert_separately failed with error message", stderr]) From e01e13c23999f0e43d8a0874003c73a1cdd68f1e Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 2 Jan 2026 11:05:07 +0900 Subject: [PATCH 7/8] Use `assert_ruby_status` if no assertion --- test/-ext-/tracepoint/test_tracepoint.rb | 2 +- test/objspace/test_objspace.rb | 4 ++-- test/openssl/test_fips.rb | 2 +- test/ripper/assert_parse_files.rb | 1 + test/ruby/test_autoload.rb | 8 ++++++-- test/ruby/test_gc_compact.rb | 2 +- test/ruby/test_lambda.rb | 2 +- test/ruby/test_module.rb | 4 ++-- test/ruby/test_optimization.rb | 4 ++-- test/ruby/test_process.rb | 4 ++-- test/ruby/test_require.rb | 4 ++-- test/ruby/test_shapes.rb | 6 +++--- test/ruby/test_signal.rb | 2 +- test/ruby/test_syntax.rb | 4 ++-- test/ruby/test_thread.rb | 7 ++++--- test/ruby/test_weakmap.rb | 4 ++-- test/ruby/test_yield.rb | 2 +- test/ruby/test_yjit.rb | 2 +- 18 files changed, 35 insertions(+), 29 deletions(-) diff --git a/test/-ext-/tracepoint/test_tracepoint.rb b/test/-ext-/tracepoint/test_tracepoint.rb index debddd83d043fe..603fd01fd5c7e6 100644 --- a/test/-ext-/tracepoint/test_tracepoint.rb +++ b/test/-ext-/tracepoint/test_tracepoint.rb @@ -83,7 +83,7 @@ def run(hook) end def test_teardown_with_active_GC_end_hook - assert_separately([], 'require("-test-/tracepoint"); Bug.after_gc_exit_hook = proc {}; GC.start') + assert_ruby_status([], 'require("-test-/tracepoint"); Bug.after_gc_exit_hook = proc {}; GC.start') end end diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb index 3d5b2a4d2ae559..2c0c6195e6ba46 100644 --- a/test/objspace/test_objspace.rb +++ b/test/objspace/test_objspace.rb @@ -143,7 +143,7 @@ def test_reachable_objects_from def test_reachable_objects_during_iteration omit 'flaky on Visual Studio with: [BUG] Unnormalized Fixnum value' if /mswin/ =~ RUBY_PLATFORM opts = %w[--disable-gem --disable=frozen-string-literal -robjspace] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + assert_ruby_status opts, "#{<<-"begin;"}\n#{<<-'end;'}" begin; ObjectSpace.each_object{|o| o.inspect @@ -179,7 +179,7 @@ def test_reachable_objects_size end def test_trace_object_allocations_stop_first - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; require "objspace" # Make sure stopping before the tracepoints are initialized doesn't raise. See [Bug #17020] diff --git a/test/openssl/test_fips.rb b/test/openssl/test_fips.rb index efc2655e25bf54..683e0011e8d7fc 100644 --- a/test/openssl/test_fips.rb +++ b/test/openssl/test_fips.rb @@ -30,7 +30,7 @@ def test_fips_mode_get_is_false_on_fips_mode_disabled def test_fips_mode_is_reentrant return if aws_lc? # AWS-LC's FIPS mode is decided at compile time. - assert_separately(["-ropenssl"], <<~"end;") + assert_ruby_status(["-ropenssl"], <<~"end;") OpenSSL.fips_mode = false OpenSSL.fips_mode = false end; diff --git a/test/ripper/assert_parse_files.rb b/test/ripper/assert_parse_files.rb index 0d583a99e3e3cd..4f08589e41064b 100644 --- a/test/ripper/assert_parse_files.rb +++ b/test/ripper/assert_parse_files.rb @@ -40,6 +40,7 @@ class Parser < Ripper end } end + assert(true) if scripts.empty? end; end end diff --git a/test/ruby/test_autoload.rb b/test/ruby/test_autoload.rb index 50949274a362f8..82bf2d9d2c0992 100644 --- a/test/ruby/test_autoload.rb +++ b/test/ruby/test_autoload.rb @@ -574,7 +574,7 @@ def test_autoload_parallel_race autoload_path = File.join(tmpdir, "autoload_parallel_race.rb") File.write(autoload_path, 'module Foo; end; module Bar; end') - assert_separately([], <<-RUBY, timeout: 100) + assert_ruby_status([], <<-RUBY, timeout: 100) autoload_path = #{File.realpath(autoload_path).inspect} # This should work with no errors or failures. @@ -617,6 +617,10 @@ module SomeNamespace private def assert_separately(*args, **kwargs) - super(*args, **{ timeout: 60 }.merge(kwargs)) + super(*args, timeout: 60, **kwargs) + end + + def assert_ruby_status(*args, **kwargs) + super(*args, timeout: 60, **kwargs) end end diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb index bc7692d644fba9..84828d498543aa 100644 --- a/test/ruby/test_gc_compact.rb +++ b/test/ruby/test_gc_compact.rb @@ -364,7 +364,7 @@ def add_ivars def test_compact_objects_of_varying_sizes omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1 - assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10) + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10) begin; $objects = [] 160.times do |n| diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb index 6a0dd9915e32a6..c1858a36ddecdd 100644 --- a/test/ruby/test_lambda.rb +++ b/test/ruby/test_lambda.rb @@ -163,7 +163,7 @@ def self.b end def test_proc_inside_lambda_toplevel - assert_separately [], <<~RUBY + assert_ruby_status [], <<~RUBY lambda{ $g = proc{ return :pr } }.call diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb index 3db60dec8f3b43..9ed6c1e321a670 100644 --- a/test/ruby/test_module.rb +++ b/test/ruby/test_module.rb @@ -583,7 +583,7 @@ def b; 2 end end def test_gc_prepend_chain - assert_separately([], <<-EOS) + assert_ruby_status([], <<-EOS) 10000.times { |i| m1 = Module.new do def foo; end @@ -3073,7 +3073,7 @@ def test_return_value_of_define_singleton_method end def test_prepend_gc - assert_separately [], %{ + assert_ruby_status [], %{ module Foo end class Object diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index cfa90b8b8a0f25..5d16984eeff883 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -946,14 +946,14 @@ def foo &b end def test_peephole_optimization_without_trace - assert_separately [], <<-END + assert_ruby_status [], <<-END RubyVM::InstructionSequence.compile_option = {trace_instruction: false} eval "def foo; 1.times{|(a), &b| nil && a}; end" END end def test_clear_unreachable_keyword_args - assert_separately [], <<-END, timeout: 60 + assert_ruby_status [], <<-END, timeout: 60 script = <<-EOS if true else diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 857ceab6762fda..b3a88b664cc09d 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -1996,7 +1996,7 @@ def test_popen_exit end def test_popen_reopen - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; io = File.open(IO::NULL) io2 = io.dup @@ -2387,7 +2387,7 @@ def test_clock_getres_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC end def test_deadlock_by_signal_at_forking - assert_separately(%W(- #{RUBY}), <<-INPUT, timeout: 100) + assert_ruby_status(%W(- #{RUBY}), <<-INPUT, timeout: 100) ruby = ARGV.shift GC.start # reduce garbage GC.disable # avoid triggering CoW after forks diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb index bbec9a5f954f93..0067a497006199 100644 --- a/test/ruby/test_require.rb +++ b/test/ruby/test_require.rb @@ -842,7 +842,7 @@ def test_require_with_loaded_features_pop } # [Bug #21567] - assert_separately(%w[-rtempfile], "#{<<~"begin;"}\n#{<<~"end;"}") + assert_ruby_status(%w[-rtempfile], "#{<<~"begin;"}\n#{<<~"end;"}") begin; class MyString def initialize(path) @@ -1029,7 +1029,7 @@ def test_resolve_feature_path_with_missing_feature def test_require_with_public_method_missing # [Bug #19793] - assert_separately(["-W0", "-rtempfile"], __FILE__, __LINE__, <<~RUBY, timeout: 60) + assert_ruby_status(["-W0", "-rtempfile"], <<~RUBY, timeout: 60) GC.stress = true class Object diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb index 453ca8f6a72dd0..67e2c543a3f1a3 100644 --- a/test/ruby/test_shapes.rb +++ b/test/ruby/test_shapes.rb @@ -228,7 +228,7 @@ class Hi; end end def test_run_out_of_shape_for_object - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; class A def initialize @@ -339,7 +339,7 @@ def test_evacuate_object_ivar_and_compaction end def test_gc_stress_during_evacuate_generic_ivar - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; [].instance_variable_set(:@a, 1) @@ -507,7 +507,7 @@ def initialize end def test_run_out_of_shape_rb_obj_copy_ivar - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; class A def initialize diff --git a/test/ruby/test_signal.rb b/test/ruby/test_signal.rb index 661ba031413ba8..091a66d5da9021 100644 --- a/test/ruby/test_signal.rb +++ b/test/ruby/test_signal.rb @@ -333,7 +333,7 @@ def test_self_stop def test_sigwait_fd_unused t = EnvUtil.apply_timeout_scale(0.1) - assert_separately([], <<-End) + assert_ruby_status([], <<-End) tgt = $$ trap(:TERM) { exit(0) } e = "Process.daemon; sleep #{t * 2}; Process.kill(:TERM,\#{tgt})" diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 585e691765c66a..b355128a7344a6 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -2296,13 +2296,13 @@ def test_argument_forwarding_with_super_memory_leak end def test_class_module_Object_ancestors - assert_separately([], <<-RUBY) + assert_ruby_status([], <<-RUBY) m = Module.new m::Bug18832 = 1 include m class Bug18832; end RUBY - assert_separately([], <<-RUBY) + assert_ruby_status([], <<-RUBY) m = Module.new m::Bug18832 = 1 include m diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb index 8edebfb5c219da..2a61fc3450bbcc 100644 --- a/test/ruby/test_thread.rb +++ b/test/ruby/test_thread.rb @@ -1594,7 +1594,8 @@ def frame_for_deadlock_test_2 # [Bug #21342] def test_unlock_locked_mutex_with_collected_fiber - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + bug21127 = '[ruby-core:120930] [Bug #21127]' + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; 5.times do m = Mutex.new @@ -1611,7 +1612,7 @@ def test_unlock_locked_mutex_with_collected_fiber end def test_unlock_locked_mutex_with_collected_fiber2 - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; MUTEXES = [] 5.times do @@ -1630,7 +1631,7 @@ def test_unlock_locked_mutex_with_collected_fiber2 end def test_mutexes_locked_in_fiber_dont_have_aba_issue_with_new_fibers - assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}") begin; mutexes = 1000.times.map do Mutex.new diff --git a/test/ruby/test_weakmap.rb b/test/ruby/test_weakmap.rb index 1050c74b3dc4cd..4f5823ecf4350c 100644 --- a/test/ruby/test_weakmap.rb +++ b/test/ruby/test_weakmap.rb @@ -203,7 +203,7 @@ def test_compaction @wm[i] = obj end - assert_separately([], <<-'end;') + assert_ruby_status([], <<-'end;') wm = ObjectSpace::WeakMap.new obj = Object.new 100.times do @@ -224,7 +224,7 @@ def test_compaction assert_equal(val, wm[key]) end; - assert_separately(["-W0"], <<-'end;') + assert_ruby_status(["-W0"], <<-'end;') wm = ObjectSpace::WeakMap.new ary = 10_000.times.map do diff --git a/test/ruby/test_yield.rb b/test/ruby/test_yield.rb index 9b2b2f37e06e04..e7e65fce9e0f0f 100644 --- a/test/ruby/test_yield.rb +++ b/test/ruby/test_yield.rb @@ -401,7 +401,7 @@ def m.method_missing(*a) def test_block_cached_argc # [Bug #11451] - assert_separately([], <<-"end;") + assert_ruby_status([], <<-"end;") class Yielder def each yield :x, :y, :z diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb index 2096585451c324..6488661c2d3a6c 100644 --- a/test/ruby/test_yjit.rb +++ b/test/ruby/test_yjit.rb @@ -133,7 +133,7 @@ def compiled_counts = RubyVM::YJIT.runtime_stats&.dig(:compiled_iseq_count) end def test_yjit_enable_with_monkey_patch - assert_separately(%w[--yjit-disable], <<~RUBY) + assert_ruby_status(%w[--yjit-disable], <<~RUBY) # This lets rb_method_entry_at(rb_mKernel, ...) return NULL Kernel.prepend(Module.new) From c794a97940a36269cffcb6ad35ef7ff209fe2720 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 9 Jan 2026 14:24:38 +0900 Subject: [PATCH 8/8] Rename `alloca_overflow` to `stack_overflow` `alloca` is an implementation detail to raise a stack overflow. --- ext/-test-/stack/stack.c | 4 ++-- test/-ext-/stack/test_stack_overflow.rb | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/-test-/stack/stack.c b/ext/-test-/stack/stack.c index 8ff32f9737b218..f0e65e74b2e40e 100644 --- a/ext/-test-/stack/stack.c +++ b/ext/-test-/stack/stack.c @@ -2,7 +2,7 @@ #include "internal/string.h" static VALUE -stack_alloca_overflow(VALUE self) +stack_overflow(VALUE self) { size_t i = 0; @@ -30,6 +30,6 @@ asan_p(VALUE klass) void Init_stack(VALUE klass) { - rb_define_singleton_method(rb_cThread, "alloca_overflow", stack_alloca_overflow, 0); + rb_define_singleton_method(rb_cThread, "stack_overflow", stack_overflow, 0); rb_define_singleton_method(rb_cThread, "asan?", asan_p, 0); } diff --git a/test/-ext-/stack/test_stack_overflow.rb b/test/-ext-/stack/test_stack_overflow.rb index 8eddec6ab5b089..3d7f00331dc711 100644 --- a/test/-ext-/stack/test_stack_overflow.rb +++ b/test/-ext-/stack/test_stack_overflow.rb @@ -17,7 +17,7 @@ def test_overflow require '-test-/stack' assert_raise(SystemStackError) do - Thread.alloca_overflow + Thread.stack_overflow end RUBY end @@ -29,7 +29,7 @@ def test_thread_stack_overflow thread = Thread.new do Thread.current.report_on_exception = false - Thread.alloca_overflow + Thread.stack_overflow end assert_raise(SystemStackError) do @@ -44,7 +44,7 @@ def test_fiber_stack_overflow GC.disable fiber = Fiber.new do - Thread.alloca_overflow + Thread.stack_overflow end assert_raise(SystemStackError) do