summaryrefslogtreecommitdiff
path: root/test/-ext-
diff options
context:
space:
mode:
Diffstat (limited to 'test/-ext-')
-rw-r--r--test/-ext-/box/test_load_ext.rb97
-rw-r--r--test/-ext-/bug_reporter/test_bug_reporter.rb12
-rw-r--r--test/-ext-/debug/test_debug.rb67
-rw-r--r--test/-ext-/debug/test_profile_frames.rb3
-rw-r--r--test/-ext-/gvl/test_last_thread.rb3
-rw-r--r--test/-ext-/integer/test_my_integer.rb34
-rw-r--r--test/-ext-/marshal/test_internal_ivar.rb10
-rw-r--r--test/-ext-/postponed_job/test_postponed_job.rb35
-rw-r--r--test/-ext-/required.rb10
-rw-r--r--test/-ext-/scheduler/test_interrupt_with_scheduler.rb54
-rw-r--r--test/-ext-/stack/test_stack_overflow.rb55
-rw-r--r--test/-ext-/string/test_capacity.rb15
-rw-r--r--test/-ext-/string/test_interned_str.rb5
-rw-r--r--test/-ext-/string/test_set_len.rb20
-rw-r--r--test/-ext-/symbol/test_type.rb16
-rw-r--r--test/-ext-/test_abi.rb12
-rw-r--r--test/-ext-/test_ensure_and_callcc.rb40
-rw-r--r--test/-ext-/thread/test_instrumentation_api.rb6
-rw-r--r--test/-ext-/thread/test_lock_native_thread.rb4
-rw-r--r--test/-ext-/thread_fd/test_thread_fd_close.rb24
-rw-r--r--test/-ext-/tracepoint/test_tracepoint.rb20
21 files changed, 419 insertions, 123 deletions
diff --git a/test/-ext-/box/test_load_ext.rb b/test/-ext-/box/test_load_ext.rb
new file mode 100644
index 0000000000..ea3744375e
--- /dev/null
+++ b/test/-ext-/box/test_load_ext.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class Test_Load_Extensions < Test::Unit::TestCase
+ ENV_ENABLE_BOX = {'RUBY_BOX' => '1'}
+
+ def test_load_extension
+ pend
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ require '-test-/box/yay1'
+ assert_equal "1.0.0", Yay.version
+ assert_equal "yay", Yay.yay
+ end;
+ end
+
+ def test_extension_contamination_in_global
+ pend
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}", ignore_stderr: true)
+ begin;
+ require '-test-/box/yay1'
+ yay1 = Yay
+ assert_equal "1.0.0", Yay.version
+ assert_equal "yay", Yay.yay
+
+ require '-test-/box/yay2'
+ assert_equal "2.0.0", Yay.version
+ v = Yay.yay
+ assert(v == "yay" || v == "yaaay") # "yay" on Linux, "yaaay" on macOS, Win32
+ end;
+ end
+
+ def test_load_extension_in_box
+ pend
+ assert_separately([ENV_ENABLE_BOX], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ ns = Ruby::Box.new
+ ns.require '-test-/box/yay1'
+ assert_equal "1.0.0", ns::Yay.version
+ assert_raise(NameError) { Yay }
+ end;
+ end
+
+ def test_different_version_extensions
+ pend
+ assert_separately([ENV_ENABLE_BOX], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ ns1 = Ruby::Box.new
+ ns2 = Ruby::Box.new
+ ns1.require('-test-/box/yay1')
+ ns2.require('-test-/box/yay2')
+
+ assert_raise(NameError) { Yay }
+ assert_not_nil ns1::Yay
+ assert_not_nil ns2::Yay
+ assert_equal "1.0.0", ns1::Yay::VERSION
+ assert_equal "2.0.0", ns2::Yay::VERSION
+ assert_equal "1.0.0", ns1::Yay.version
+ assert_equal "2.0.0", ns2::Yay.version
+ end;
+ end
+
+ def test_loading_extensions_from_global_to_local
+ pend
+ assert_separately([ENV_ENABLE_BOX], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ require '-test-/box/yay1'
+ assert_equal "1.0.0", Yay.version
+ assert_equal "yay", Yay.yay
+
+ ns = Ruby::Box.new
+ ns.require '-test-/box/yay2'
+ assert_equal "2.0.0", ns::Yay.version
+ assert_equal "yaaay", ns::Yay.yay
+
+ assert_equal "yay", Yay.yay
+ end;
+ end
+
+ def test_loading_extensions_from_local_to_global
+ pend
+ assert_separately([ENV_ENABLE_BOX], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ ns = Ruby::Box.new
+ ns.require '-test-/box/yay1'
+ assert_equal "1.0.0", ns::Yay.version
+ assert_equal "yay", ns::Yay.yay
+
+
+ require '-test-/box/yay2'
+ assert_equal "2.0.0", Yay.version
+ assert_equal "yaaay", Yay.yay
+
+ assert_equal "yay", ns::Yay.yay
+ end;
+ end
+end
diff --git a/test/-ext-/bug_reporter/test_bug_reporter.rb b/test/-ext-/bug_reporter/test_bug_reporter.rb
index 76f913c275..83fdba2282 100644
--- a/test/-ext-/bug_reporter/test_bug_reporter.rb
+++ b/test/-ext-/bug_reporter/test_bug_reporter.rb
@@ -2,12 +2,12 @@
require 'test/unit'
require 'tmpdir'
require_relative '../../lib/jit_support'
+require_relative '../../lib/parser_support'
class TestBugReporter < Test::Unit::TestCase
def test_bug_reporter_add
- omit "flaky with RJIT" if JITSupport.rjit_enabled?
- description = RUBY_DESCRIPTION.sub(/\+PRISM /, '')
- description = description.sub(/\+RJIT /, '') unless JITSupport.rjit_force_enabled?
+ description = RUBY_DESCRIPTION
+ description = description.sub(/\+PRISM /, '') unless ParserSupport.prism_enabled_in_subprocess?
expected_stderr = [
:*,
/\[BUG\]\sSegmentation\sfault.*\n/,
@@ -20,8 +20,10 @@ class TestBugReporter < Test::Unit::TestCase
no_core = "Process.setrlimit(Process::RLIMIT_CORE, 0); " if defined?(Process.setrlimit) && defined?(Process::RLIMIT_CORE)
args = ["-r-test-/bug_reporter", "-C", tmpdir]
- args.push("--yjit") if JITSupport.yjit_enabled? # We want the printed description to match this process's RUBY_DESCRIPTION
- args.unshift({"RUBY_ON_BUG" => nil})
+ # We want the printed description to match this process's RUBY_DESCRIPTION
+ args.push("--yjit") if JITSupport.yjit_enabled?
+ args.push("--zjit") if JITSupport.zjit_enabled?
+ args.unshift({"RUBY_ON_BUG" => nil, "RUBY_CRASH_REPORT" => nil})
stdin = "#{no_core}register_sample_bug_reporter(12345); Process.kill :SEGV, $$"
assert_in_out_err(args, stdin, [], expected_stderr, encoding: "ASCII-8BIT")
ensure
diff --git a/test/-ext-/debug/test_debug.rb b/test/-ext-/debug/test_debug.rb
index b244eb41ea..c9263d76fa 100644
--- a/test/-ext-/debug/test_debug.rb
+++ b/test/-ext-/debug/test_debug.rb
@@ -26,11 +26,14 @@ class TestDebug < Test::Unit::TestCase
count[:iseq] += 1
assert_instance_of(RubyVM::InstructionSequence, iseq, msg)
- # check same location
- assert_equal(loc.path, iseq.path, msg)
- assert_equal(loc.absolute_path, iseq.absolute_path, msg)
- #assert_equal(loc.label, iseq.label, msg)
- assert_operator(loc.lineno, :>=, iseq.first_lineno, msg)
+ # Backtraces and source locations don't match for :c_trace methods
+ unless iseq.disasm.include?('C_TRACE')
+ # check same location
+ assert_equal(loc.path, iseq.path, msg)
+ assert_equal(loc.absolute_path, iseq.absolute_path, msg)
+ #assert_equal(loc.label, iseq.label, msg)
+ assert_operator(loc.lineno, :>=, iseq.first_lineno, msg)
+ end
end
assert_instance_of(Thread::Backtrace::Location, loc, msg)
@@ -73,3 +76,57 @@ class TestDebug < Test::Unit::TestCase
assert_equal true, x, '[Bug #15105]'
end
end
+
+# This is a YJIT test, but we can't test this without a C extension that calls
+# rb_debug_inspector_open(), so we're testing it using "-test-/debug" here.
+class TestDebugWithYJIT < Test::Unit::TestCase
+ class LocalSetArray
+ def to_a
+ Bug::Debug.inspector.each do |_, binding,|
+ binding.local_variable_set(:local, :ok) if binding
+ end
+ [:ok]
+ end
+ end
+
+ class DebugArray
+ def to_a
+ Bug::Debug.inspector
+ [:ok]
+ end
+ end
+
+ def test_yjit_invalidates_getlocal_after_splatarray
+ val = getlocal_after_splatarray(LocalSetArray.new)
+ assert_equal [:ok, :ok], val
+ end
+
+ def test_yjit_invalidates_setlocal_after_splatarray
+ val = setlocal_after_splatarray(DebugArray.new)
+ assert_equal [:ok], val
+ end
+
+ def test_yjit_invalidates_setlocal_after_proc_call
+ val = setlocal_after_proc_call(proc { Bug::Debug.inspector; :ok })
+ assert_equal :ok, val
+ end
+
+ private
+
+ def getlocal_after_splatarray(array)
+ local = 1
+ [*array, local]
+ end
+
+ def setlocal_after_splatarray(array)
+ local = *array # setlocal followed by splatarray
+ itself # split a block using a C call
+ local # getlocal
+ end
+
+ def setlocal_after_proc_call(block)
+ local = block.call # setlocal followed by OPTIMIZED_METHOD_TYPE_CALL
+ itself # split a block using a C call
+ local # getlocal
+ end
+end if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
diff --git a/test/-ext-/debug/test_profile_frames.rb b/test/-ext-/debug/test_profile_frames.rb
index bd819266df..d79c94c468 100644
--- a/test/-ext-/debug/test_profile_frames.rb
+++ b/test/-ext-/debug/test_profile_frames.rb
@@ -209,8 +209,9 @@ class TestProfileFrames < Test::Unit::TestCase
profile_frames.shift
# The rest of the stack is expected to look the same...
- backtrace_locations.zip(profile_frames).each.with_index do |(location, (path, absolute_path, _, base_label, _, _, _, _, _, _, lineno)), i|
+ backtrace_locations.zip(profile_frames).each.with_index do |(location, (path, absolute_path, _, base_label, label, _, _, _, _, _, lineno)), i|
next if absolute_path == "<cfunc>" # ...except for cfunc frames
+ next if label in "Array#each" | "Array#map" # ...except for :c_trace method frames
err_msg = "#{i}th frame"
assert_equal(location.absolute_path, absolute_path, err_msg)
diff --git a/test/-ext-/gvl/test_last_thread.rb b/test/-ext-/gvl/test_last_thread.rb
index f1bebafeea..bcda0e3385 100644
--- a/test/-ext-/gvl/test_last_thread.rb
+++ b/test/-ext-/gvl/test_last_thread.rb
@@ -15,8 +15,7 @@ class TestLastThread < Test::Unit::TestCase
t1 = Time.now
t = t1 - t0
- assert_in_delta(1.0, t, 0.16)
+ assert_in_delta(1.0, t, 0.8)
end;
end
end
-
diff --git a/test/-ext-/integer/test_my_integer.rb b/test/-ext-/integer/test_my_integer.rb
index 1b6f8489f8..0dfa234921 100644
--- a/test/-ext-/integer/test_my_integer.rb
+++ b/test/-ext-/integer/test_my_integer.rb
@@ -8,19 +8,13 @@ class Test_MyInteger < Test::Unit::TestCase
Bug::Integer::MyInteger.new.to_f
end
- begin
- Bug::Integer::MyInteger.class_eval do
- def to_f
- end
+ int = Class.new(Bug::Integer::MyInteger) do
+ def to_f
end
+ end
- assert_nothing_raised do
- Bug::Integer::MyInteger.new.to_f
- end
- ensure
- Bug::Integer::MyInteger.class_eval do
- remove_method :to_f
- end
+ assert_nothing_raised do
+ int.new.to_f
end
end
@@ -29,20 +23,14 @@ class Test_MyInteger < Test::Unit::TestCase
Bug::Integer::MyInteger.new <=> 0
end
- begin
- Bug::Integer::MyInteger.class_eval do
- def <=>(other)
- 0
- end
+ int = Class.new(Bug::Integer::MyInteger) do
+ def <=>(other)
+ 0
end
+ end
- assert_nothing_raised do
- Bug::Integer::MyInteger.new <=> 0
- end
- ensure
- Bug::Integer::MyInteger.class_eval do
- remove_method :<=>
- end
+ assert_nothing_raised do
+ int.new <=> 0
end
end
end
diff --git a/test/-ext-/marshal/test_internal_ivar.rb b/test/-ext-/marshal/test_internal_ivar.rb
index faabe14ab2..8b4667fdf9 100644
--- a/test/-ext-/marshal/test_internal_ivar.rb
+++ b/test/-ext-/marshal/test_internal_ivar.rb
@@ -7,11 +7,16 @@ module Bug end
module Bug::Marshal
class TestInternalIVar < Test::Unit::TestCase
def test_marshal
- v = InternalIVar.new("hello", "world", "bye")
+ v = InternalIVar.new("hello", "world", "bye", "hi")
assert_equal("hello", v.normal)
assert_equal("world", v.internal)
assert_equal("bye", v.encoding_short)
- dump = assert_warn(/instance variable 'E' on class \S+ is not dumped/) {
+ assert_equal("hi", v.encoding_long)
+ warnings = ->(s) {
+ w = s.scan(/instance variable '(.+?)' on class \S+ is not dumped/)
+ assert_equal(%w[E K encoding], w.flatten.sort)
+ }
+ dump = assert_warn(warnings) {
::Marshal.dump(v)
}
v = assert_nothing_raised {break ::Marshal.load(dump)}
@@ -19,6 +24,7 @@ module Bug::Marshal
assert_equal("hello", v.normal)
assert_nil(v.internal)
assert_nil(v.encoding_short)
+ assert_nil(v.encoding_long)
end
end
end
diff --git a/test/-ext-/postponed_job/test_postponed_job.rb b/test/-ext-/postponed_job/test_postponed_job.rb
index 8c2b3e95d1..01d6015de1 100644
--- a/test/-ext-/postponed_job/test_postponed_job.rb
+++ b/test/-ext-/postponed_job/test_postponed_job.rb
@@ -33,39 +33,4 @@ class TestPostponed_job < Test::Unit::TestCase
assert_equal [3, 4], values
RUBY
end
-
- def test_legacy_register
- assert_separately([], __FILE__, __LINE__, <<-'RUBY')
- require '-test-/postponed_job'
- direct, registered = [], []
-
- Bug.postponed_job_call_direct(direct)
- Bug.postponed_job_register(registered)
-
- assert_equal([0], direct)
- assert_equal([3], registered)
-
- Bug.postponed_job_register_one(ary = [])
- assert_equal [1], ary
- RUBY
- end
-
- def test_legacy_register_one_same
- assert_separately([], __FILE__, __LINE__, <<-'RUBY')
- require '-test-/postponed_job'
- # Registering the same job three times should result in three of the same handle
- handles = Bug.postponed_job_register_one_same
- assert_equal [handles[0]], handles.uniq
- RUBY
- end
-
- if Bug.respond_to?(:postponed_job_register_in_c_thread)
- def test_legacy_register_in_c_thread
- assert_separately([], __FILE__, __LINE__, <<-'RUBY')
- require '-test-/postponed_job'
- assert Bug.postponed_job_register_in_c_thread(ary = [])
- assert_equal [1], ary
- RUBY
- end
- end
end
diff --git a/test/-ext-/required.rb b/test/-ext-/required.rb
new file mode 100644
index 0000000000..70514355ff
--- /dev/null
+++ b/test/-ext-/required.rb
@@ -0,0 +1,10 @@
+require 'continuation'
+cont = nil
+a = [*1..10].reject do |i|
+ callcc {|c| cont = c} if !cont and i == 10
+ false
+end
+if a.size < 1000
+ a.unshift(:x)
+ cont.call
+end
diff --git a/test/-ext-/scheduler/test_interrupt_with_scheduler.rb b/test/-ext-/scheduler/test_interrupt_with_scheduler.rb
new file mode 100644
index 0000000000..eb7a0647e5
--- /dev/null
+++ b/test/-ext-/scheduler/test_interrupt_with_scheduler.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+require 'test/unit'
+require 'timeout'
+require_relative '../../fiber/scheduler'
+
+class TestSchedulerInterruptHandling < Test::Unit::TestCase
+ def setup
+ pend("No fork support") unless Process.respond_to?(:fork)
+ require '-test-/scheduler'
+ end
+
+ # Test without Thread.handle_interrupt - should work regardless of fix
+ def test_without_handle_interrupt_signal_works
+ IO.pipe do |input, output|
+ pid = fork do
+ STDERR.reopen(output)
+
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Signal.trap(:INT) do
+ ::Thread.current.raise(Interrupt)
+ end
+
+ Fiber.schedule do
+ # Yield to the scheduler:
+ sleep(0)
+
+ Bug::Scheduler.blocking_loop(output)
+ end
+ end
+
+ output.close
+ assert_equal "x", input.read(1)
+
+ Process.kill(:INT, pid)
+
+ reaper = Thread.new do
+ Process.waitpid2(pid)
+ end
+
+ unless reaper.join(10)
+ Process.kill(:KILL, pid)
+ end
+
+ _, status = reaper.value
+
+ # It should be interrupted (not killed):
+ assert_not_equal 0, status.exitstatus
+ assert_equal true, status.signaled?
+ assert_equal Signal.list["INT"], status.termsig
+ end
+ end
+end
diff --git a/test/-ext-/stack/test_stack_overflow.rb b/test/-ext-/stack/test_stack_overflow.rb
new file mode 100644
index 0000000000..3d7f00331d
--- /dev/null
+++ b/test/-ext-/stack/test_stack_overflow.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class Test_StackOverflow < Test::Unit::TestCase
+ def setup
+ omit "Stack overflow tests are not supported on this platform: #{RUBY_PLATFORM.inspect}" unless RUBY_PLATFORM =~ /x86_64-linux|darwin/
+
+ require '-test-/stack'
+
+ omit "Stack overflow tests are not supported with ASAN" if Thread.asan?
+ end
+
+ def test_overflow
+ assert_separately([], <<~RUBY)
+ # GC may try to scan the top of the stack and cause a SEGV.
+ GC.disable
+ require '-test-/stack'
+
+ assert_raise(SystemStackError) do
+ Thread.stack_overflow
+ end
+ RUBY
+ end
+
+ def test_thread_stack_overflow
+ assert_separately([], <<~RUBY)
+ require '-test-/stack'
+ GC.disable
+
+ thread = Thread.new do
+ Thread.current.report_on_exception = false
+ Thread.stack_overflow
+ end
+
+ assert_raise(SystemStackError) do
+ thread.join
+ end
+ RUBY
+ end
+
+ def test_fiber_stack_overflow
+ assert_separately([], <<~RUBY)
+ require '-test-/stack'
+ GC.disable
+
+ fiber = Fiber.new do
+ Thread.stack_overflow
+ end
+
+ assert_raise(SystemStackError) do
+ fiber.resume
+ end
+ RUBY
+ end
+end
diff --git a/test/-ext-/string/test_capacity.rb b/test/-ext-/string/test_capacity.rb
index 2c6c51fdda..a23892142a 100644
--- a/test/-ext-/string/test_capacity.rb
+++ b/test/-ext-/string/test_capacity.rb
@@ -2,16 +2,17 @@
require 'test/unit'
require '-test-/string'
require 'rbconfig/sizeof'
+require 'objspace'
class Test_StringCapacity < Test::Unit::TestCase
def test_capacity_embedded
- assert_equal GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] - embed_header_size - 1, capa('foo')
+ assert_equal pool_slot_size(0) - 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
- sym = ("a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).to_sym
+ sym = ("a" * pool_slot_size(0)).to_sym
assert_equal 0, capa(sym.to_s)
end
@@ -23,7 +24,7 @@ class Test_StringCapacity < Test::Unit::TestCase
def test_s_new_capacity
assert_equal("", String.new(capacity: 1000))
assert_equal(String, String.new(capacity: 1000).class)
- assert_equal(10_000 - 1, capa(String.new(capacity: 10_000))) # Real capa doesn't account for termlen
+ assert_equal(10_000, capa(String.new(capacity: 10_000)))
assert_equal("", String.new(capacity: -1000))
assert_equal(capa(String.new(capacity: -10000)), capa(String.new(capacity: -1000)))
@@ -47,7 +48,7 @@ class Test_StringCapacity < Test::Unit::TestCase
def test_capacity_frozen
s = String.new("I am testing", capacity: 1000)
- s << "a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
+ s << "a" * pool_slot_size(0)
s.freeze
assert_equal(s.length, capa(s))
end
@@ -66,7 +67,11 @@ class Test_StringCapacity < Test::Unit::TestCase
end
def embed_header_size
- 3 * RbConfig::SIZEOF['void*']
+ GC::INTERNAL_CONSTANTS[:RBASIC_SIZE] + RbConfig::SIZEOF['void*']
+ end
+
+ def pool_slot_size(_idx = 0)
+ Integer(ObjectSpace.dump("")[/"slot_size":(\d+)/, 1])
end
def max_embed_len
diff --git a/test/-ext-/string/test_interned_str.rb b/test/-ext-/string/test_interned_str.rb
index 340dba41e8..a81cb59aa5 100644
--- a/test/-ext-/string/test_interned_str.rb
+++ b/test/-ext-/string/test_interned_str.rb
@@ -9,4 +9,9 @@ class Test_RbInternedStr < Test::Unit::TestCase
src << "b" * 20
assert_equal "a" * 20, interned_str
end
+
+ def test_interned_str_encoding
+ src = :ascii.name
+ assert_equal Encoding::US_ASCII, Bug::String.rb_interned_str_dup(src).encoding
+ end
end
diff --git a/test/-ext-/string/test_set_len.rb b/test/-ext-/string/test_set_len.rb
index e3eff75d9b..41e14a293a 100644
--- a/test/-ext-/string/test_set_len.rb
+++ b/test/-ext-/string/test_set_len.rb
@@ -5,7 +5,7 @@ require "-test-/string"
class Test_StrSetLen < Test::Unit::TestCase
def setup
# Make string long enough so that it is not embedded
- @range_end = ("0".ord + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).chr
+ @range_end = ("0".ord + GC.stat_heap(0, :slot_size)).chr
@s0 = [*"0"..@range_end].join("").freeze
@s1 = Bug::String.new(@s0)
end
@@ -63,4 +63,22 @@ class Test_StrSetLen < Test::Unit::TestCase
assert_not_predicate str, :ascii_only?
assert_equal u, str
end
+
+ def test_valid_encoding_after_resized
+ s = "\0\0".force_encoding(Encoding::UTF_16BE)
+ str = Bug::String.new(s)
+ assert_predicate str, :valid_encoding?
+ str.resize(1)
+ assert_not_predicate str, :valid_encoding?
+ str.resize(2)
+ assert_predicate str, :valid_encoding?
+ str.resize(3)
+ assert_not_predicate str, :valid_encoding?
+
+ s = "\xDB\x00\xDC\x00".force_encoding(Encoding::UTF_16BE)
+ str = Bug::String.new(s)
+ assert_predicate str, :valid_encoding?
+ str.resize(2)
+ assert_not_predicate str, :valid_encoding?
+ end
end
diff --git a/test/-ext-/symbol/test_type.rb b/test/-ext-/symbol/test_type.rb
index 2b0fbe5b79..ed019062fa 100644
--- a/test/-ext-/symbol/test_type.rb
+++ b/test/-ext-/symbol/test_type.rb
@@ -123,16 +123,20 @@ module Test_Symbol
def test_check_id_invalid_type
cx = EnvUtil.labeled_class("X\u{1f431}")
- assert_raise_with_message(TypeError, /X\u{1F431}/) {
- Bug::Symbol.pinneddown?(cx)
- }
+ EnvUtil.with_default_internal(Encoding::UTF_8) do
+ assert_raise_with_message(TypeError, /X\u{1F431}/) {
+ Bug::Symbol.pinneddown?(cx)
+ }
+ end
end
def test_check_symbol_invalid_type
cx = EnvUtil.labeled_class("X\u{1f431}")
- assert_raise_with_message(TypeError, /X\u{1F431}/) {
- Bug::Symbol.find(cx)
- }
+ EnvUtil.with_default_internal(Encoding::UTF_8) do
+ assert_raise_with_message(TypeError, /X\u{1F431}/) {
+ Bug::Symbol.find(cx)
+ }
+ end
end
def test_const_name_type
diff --git a/test/-ext-/test_abi.rb b/test/-ext-/test_abi.rb
index d3ea6bb9b1..7f30feb944 100644
--- a/test/-ext-/test_abi.rb
+++ b/test/-ext-/test_abi.rb
@@ -9,7 +9,11 @@ class TestABI < Test::Unit::TestCase
assert_separately [], <<~RUBY
err = assert_raise(LoadError) { require "-test-/abi" }
assert_match(/incompatible ABI version/, err.message)
- assert_include err.message, "/-test-/abi."
+ if Ruby::Box.enabled?
+ assert_include err.message, "_-test-+abi."
+ else
+ assert_include err.message, "/-test-/abi."
+ end
RUBY
end
@@ -27,7 +31,11 @@ class TestABI < Test::Unit::TestCase
assert_separately [{ "RUBY_ABI_CHECK" => "1" }], <<~RUBY
err = assert_raise(LoadError) { require "-test-/abi" }
assert_match(/incompatible ABI version/, err.message)
- assert_include err.message, "/-test-/abi."
+ if Ruby::Box.enabled?
+ assert_include err.message, "_-test-+abi."
+ else
+ assert_include err.message, "/-test-/abi."
+ end
RUBY
end
diff --git a/test/-ext-/test_ensure_and_callcc.rb b/test/-ext-/test_ensure_and_callcc.rb
new file mode 100644
index 0000000000..9303a094ea
--- /dev/null
+++ b/test/-ext-/test_ensure_and_callcc.rb
@@ -0,0 +1,40 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: false
+require 'test/unit'
+
+class TestEnsureAndCallcc < Test::Unit::TestCase
+ def test_bug20655_dir_chdir_using_rb_ensure
+ require 'tmpdir'
+ need_continuation
+ called = 0
+ tmp = nil
+ Dir.mktmpdir do |tmpdir|
+ Dir.chdir(tmpdir) do
+ tmp = Dir.pwd
+ cont = nil
+ callcc{|c| cont = c}
+ assert_equal(tmp, Dir.pwd, "BUG #20655: ensure called and pwd was changed unexpectedly")
+ called += 1
+ cont.call if called < 10
+ end
+ end
+ end
+
+ def test_bug20655_extension_using_rb_ensure
+ need_continuation
+ require '-test-/ensure_and_callcc'
+ EnsureAndCallcc.reset
+ assert_equal(0, EnsureAndCallcc.ensure_called)
+ EnsureAndCallcc.require_with_ensure(File.join(__dir__, 'required'))
+ assert_equal(1, EnsureAndCallcc.ensure_called,
+ "BUG #20655: ensure called unexpectedly in the required script even without exceptions")
+ end
+
+ private
+ def need_continuation
+ unless respond_to?(:callcc, true)
+ EnvUtil.suppress_warning {require 'continuation'}
+ end
+ omit 'requires callcc support' unless respond_to?(:callcc, true)
+ end
+end
diff --git a/test/-ext-/thread/test_instrumentation_api.rb b/test/-ext-/thread/test_instrumentation_api.rb
index 663e41be53..ba41069304 100644
--- a/test/-ext-/thread/test_instrumentation_api.rb
+++ b/test/-ext-/thread/test_instrumentation_api.rb
@@ -151,7 +151,7 @@ class TestThreadInstrumentation < Test::Unit::TestCase
end
full_timeline = record do
- ractor.take
+ ractor.value
end
timeline = timeline_for(Thread.current, full_timeline)
@@ -161,6 +161,8 @@ class TestThreadInstrumentation < Test::Unit::TestCase
end
def test_sleeping_inside_ractor
+ omit "This test is flaky and intermittently failing now on ModGC workflow" if ENV['GITHUB_WORKFLOW'] == 'ModGC'
+
assert_ractor(<<-"RUBY", require_relative: "helper", require: "-test-/thread/instrumentation")
include ThreadInstrumentation::TestHelper
@@ -170,7 +172,7 @@ class TestThreadInstrumentation < Test::Unit::TestCase
thread = Ractor.new{
sleep 0.1
Thread.current
- }.take
+ }.value
sleep 0.1
end
diff --git a/test/-ext-/thread/test_lock_native_thread.rb b/test/-ext-/thread/test_lock_native_thread.rb
index 8a5ba78838..b4044b2b93 100644
--- a/test/-ext-/thread/test_lock_native_thread.rb
+++ b/test/-ext-/thread/test_lock_native_thread.rb
@@ -15,6 +15,8 @@ end
class TestThreadLockNativeThread < Test::Unit::TestCase
def test_lock_native_thread
+ omit "LSAN reports memory leak because NT is not freed for MN thread" if Test::Sanitizers.lsan_enabled?
+
assert_separately([{'RUBY_MN_THREADS' => '1'}], <<-RUBY)
require '-test-/thread/lock_native_thread'
@@ -28,6 +30,8 @@ class TestThreadLockNativeThread < Test::Unit::TestCase
end
def test_lock_native_thread_tls
+ omit "LSAN reports memory leak because NT is not freed for MN thread" if Test::Sanitizers.lsan_enabled?
+
assert_separately([{'RUBY_MN_THREADS' => '1'}], <<-RUBY)
require '-test-/thread/lock_native_thread'
tn = 10
diff --git a/test/-ext-/thread_fd/test_thread_fd_close.rb b/test/-ext-/thread_fd/test_thread_fd_close.rb
deleted file mode 100644
index 1d2ef63635..0000000000
--- a/test/-ext-/thread_fd/test_thread_fd_close.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require '-test-/thread_fd'
-
-class TestThreadFdClose < Test::Unit::TestCase
-
- def test_thread_fd_close
- IO.pipe do |r, w|
- th = Thread.new do
- begin
- assert_raise(IOError) {
- r.read(4)
- }
- ensure
- w.syswrite('done')
- end
- end
- Thread.pass until th.stop?
- IO.thread_fd_close(r.fileno)
- assert_equal 'done', r.read(4)
- th.join
- end
- end
-end
diff --git a/test/-ext-/tracepoint/test_tracepoint.rb b/test/-ext-/tracepoint/test_tracepoint.rb
index 48ffe2605c..603fd01fd5 100644
--- a/test/-ext-/tracepoint/test_tracepoint.rb
+++ b/test/-ext-/tracepoint/test_tracepoint.rb
@@ -66,15 +66,15 @@ class TestTracepointObj < Test::Unit::TestCase
count = 0
hook = proc {count += 1}
def run(hook)
- stress, GC.stress = GC.stress, false
- Bug.after_gc_start_hook = hook
- begin
- GC.stress = true
- 3.times {Object.new}
- ensure
- GC.stress = stress
- Bug.after_gc_start_hook = nil
- end
+ stress, GC.stress = GC.stress, false
+ Bug.after_gc_start_hook = hook
+ begin
+ GC.stress = true
+ 3.times {Object.new}
+ ensure
+ GC.stress = stress
+ Bug.after_gc_start_hook = nil
+ end
end
run(hook)
puts count
@@ -83,7 +83,7 @@ class TestTracepointObj < Test::Unit::TestCase
end
def test_teardown_with_active_GC_end_hook
- assert_separately([], 'require("-test-/tracepoint"); Bug.after_gc_exit_hook = proc {}')
+ assert_ruby_status([], 'require("-test-/tracepoint"); Bug.after_gc_exit_hook = proc {}; GC.start')
end
end