Skip to content
Merged
2 changes: 1 addition & 1 deletion doc/contributing/building_ruby.md
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ The compiled Ruby will now automatically crash with a report and a backtrace
if ASAN detects a memory safety issue. To run Ruby's test suite under ASAN,
issue the following command. Note that this will take quite a long time (over
two hours on my laptop); the `RUBY_TEST_TIMEOUT_SCALE` and
`SYNTAX_SUGEST_TIMEOUT` variables are required to make sure tests don't
`SYNTAX_SUGGEST_TIMEOUT` variables are required to make sure tests don't
spuriously fail with timeouts when in fact they're just slow.

```sh
Expand Down
2 changes: 1 addition & 1 deletion doc/contributing/documentation_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ Alternatives:
- Example {source}[https://github.com/ruby/ruby/blob/34d802f32f00df1ac0220b62f72605827c16bad8/file.c#L6570-L6596].
- Corresponding {output}[rdoc-ref:File@ReadWrite+Mode].

- (Markdown format only): A {Github Flavored Markdown (GFM) table}[https://github.github.com/gfm/#tables-extension-],
- (Markdown format only): A {GitHub Flavored Markdown (GFM) table}[https://github.github.com/gfm/#tables-extension-],
using special formatting for the text:

- Example {source}[https://github.com/ruby/ruby/blob/34d802f32f00df1ac0220b62f72605827c16bad8/doc/contributing/glossary.md?plain=1].
Expand Down
2 changes: 1 addition & 1 deletion doc/contributing/making_changes_to_ruby.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ Use the following style for commit messages:

## CI

GitHub actions will run on each pull request.
GitHub Actions will run on each pull request.

There is [a CI that runs on master](https://rubyci.org/). It has broad coverage of different systems and architectures, such as Solaris SPARC and macOS.
6 changes: 5 additions & 1 deletion spec/bundled_gems_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,11 @@ def script(code, options = {})
it "Show warning when bundle exec with -r option" do
create_file("stub.rb", stub_code)
create_file("Gemfile", "source 'https://rubygems.org'")
bundle "exec ruby -r./stub -ropenssl -e ''"
# Command-line -r features are required before RUBYOPT's -rbundler/setup,
# and gem_prelude no longer consumes BUNDLER_SETUP in the main box, so
# bundler/setup must be requested explicitly ahead of the bundled gem to
# exercise the warning for requires without a Ruby caller frame.
bundle "exec ruby -rbundler/setup -r./stub -ropenssl -e ''"

expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
end
Expand Down
2 changes: 1 addition & 1 deletion test/ruby/test_argf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def test_inplace_suffix_encoding
end

def test_inplace_bug_17117
assert_in_out_err(["-", @t1.path], "#{<<~"{#"}#{<<~'};'}")
assert_in_out_err(["-", @t1.path], "#{<<~"{#"}#{<<~'};'}", timeout: 60)
{#
#!/usr/bin/ruby -pi.bak
BEGIN {
Expand Down
38 changes: 20 additions & 18 deletions tool/lib/core_assertions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ def filter bt

unless $DEBUG then
bt.each do |line|
break if pattern.match?(line)
break if pattern =~ line
new_bt << line
end

new_bt = bt.reject { |line| pattern.match?(line) } if new_bt.empty?
new_bt = bt.reject { |line| pattern =~ line } if new_bt.empty?
new_bt = bt.dup if new_bt.empty?
else
new_bt = bt.dup
Expand Down Expand Up @@ -327,8 +327,8 @@ def separated_runner(token, out = nil)
at_exit {
assertions = assertions_ivar_get.call(:@_assertions)
out_write.call <<~OUT
<error id="#{token}" assertions=#{integer_to_s.bind_call(assertions)}>
#{array_pack.bind_call([marshal_dump.call($!)], 'm0')}
<error id="#{token}" assertions=#{integer_to_s.bind(assertions).call}>
#{array_pack.bind([marshal_dump.call($!)]).call('m0')}
</error id="#{token}">
OUT
}
Expand Down Expand Up @@ -365,7 +365,7 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o
args.insert((Hash === args.first ? 1 : 0), "-w", "--disable=gems", *$:.map {|l| "-I#{l}"})
args << "--debug" if RUBY_ENGINE == 'jruby' # warning: tracing (e.g. set_trace_func) will not capture all events without --debug flag
# power_assert 3 requires ruby 3.1 or later
args << "-W:no-experimental" if RUBY_VERSION < "3.1."
args << "-W:no-experimental" if ("2.7."..."3.1.").cover?(RUBY_VERSION)
stdout, stderr, status = EnvUtil.invoke_ruby(args, src, capture_stdout, true, **opt)

if sanitizers&.lsan_enabled?
Expand All @@ -388,21 +388,23 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o
assert(!abort, FailDesc[status, nil, stderr])
res.scan(/^<error id="#{token_re}" assertions=(\d+)>\n(.*?)\n(?=<\/error id="#{token_re}">$)/m) do
self._assertions += $1.to_i
res = Marshal.load($2.unpack1("m")) or next
rescue => marshal_error
ignore_stderr = nil
res = nil
else
next if SystemExit === res
if bt = res.backtrace
bt.each do |l|
l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"}
end
bt.concat(caller)
begin
res = Marshal.load($2.unpack1("m")) or next
rescue => marshal_error
ignore_stderr = nil
res = nil
else
res.set_backtrace(caller)
next if SystemExit === res
if bt = res.backtrace
bt.each do |l|
l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"}
end
bt.concat(caller)
else
res.set_backtrace(caller)
end
raise res
end
raise res
end

# really did it succeed?
Expand Down
4 changes: 4 additions & 0 deletions tool/sync_default_gems.rb
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ def lib((upstream, branch), gemspec_in_subdir: false)
["test/zlib", "test/zlib"],
["zlib.gemspec", "ext/zlib/zlib.gemspec"],
]),
"test-unit-ruby-core":repo("ruby/test-unit-ruby-core", [
["lib", "tool/lib"],
["test", "tool/test"],
]),
}.transform_keys(&:to_s)

def REPOSITORIES.[](gem)
Expand Down
46 changes: 46 additions & 0 deletions tool/test/test_core_assertions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

require "test/unit"
require "core_assertions"

class TestCoreAssertions < Test::Unit::TestCase
include Test::Unit::CoreAssertions

def test_backtrace_filter_handles_missing_backtrace
assert_equal(["No backtrace"], Test.filter_backtrace(nil))
end

def test_backtrace_filter_removes_internal_entries
backtrace = [
"/tmp/example.rb:1:in `run'",
"/tmp/lib/test/unit.rb:2:in `assert'",
]

assert_equal([backtrace.first], Test.filter_backtrace(backtrace))
end

def test_message_adds_sentence_endings
object = Object.new
object.extend(Test::Unit::Assertions)

message = object.message("details") { "default" }

assert_equal("details.\ndefault.", message.call)
end

def test_assert_separately_runs_assertions_in_child_ruby
assert_separately([], <<~RUBY)
assert_equal(4, 2 + 2)
RUBY
end

def test_assert_separately_propagates_child_failure
error = assert_raise(Test::Unit::AssertionFailedError) do
assert_separately([], <<~RUBY)
assert_equal(:expected, :actual)
RUBY
end

assert_match(/expected/, error.message)
end
end
30 changes: 30 additions & 0 deletions tool/test/test_envutil.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

require "test/unit"
require "envutil"

class TestEnvUtil < Test::Unit::TestCase
def test_rubybin_points_to_a_ruby_executable
assert(File.executable?(EnvUtil.rubybin))
end

def test_apply_timeout_scale
original_scale = EnvUtil.timeout_scale
EnvUtil.timeout_scale = 2.5

assert_equal(5.0, EnvUtil.apply_timeout_scale(2))
ensure
EnvUtil.timeout_scale = original_scale
end

def test_invoke_ruby_captures_output_and_status
stdout, stderr, status = EnvUtil.invoke_ruby(
["-e", "STDOUT.print('out'); STDERR.print('err')"],
"", true, true
)

assert_equal("out", stdout)
assert_equal("err", stderr)
assert_predicate(status, :success?)
end
end
26 changes: 26 additions & 0 deletions tool/test/test_find_executable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require "test/unit"
require "rbconfig"
require "find_executable"

class TestFindExecutable < Test::Unit::TestCase
def test_find_executable_returns_command_and_arguments
ruby = RbConfig.ruby
command = File.basename(ruby, RbConfig::CONFIG["EXEEXT"])
original_path = ENV["PATH"]
ENV["PATH"] = File.dirname(ruby) + File::PATH_SEPARATOR + original_path

found = EnvUtil.find_executable(command, "--version") do |output|
output.start_with?("ruby ")
end

assert_equal([ruby, "--version"], found)
ensure
ENV["PATH"] = original_path
end

def test_find_executable_returns_nil_for_unknown_command
assert_nil(EnvUtil.find_executable("test-unit-ruby-core-missing") { true })
end
end
23 changes: 23 additions & 0 deletions tool/test/test_memory_status.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

require "test/unit"
require "memory_status"

class TestMemoryStatus < Test::Unit::TestCase
def setup
omit("memory status is unsupported") unless defined?(Memory::Status)
end

def test_status_reports_numeric_values
status = Memory::Status.new

assert(status.members.any? { |member| status[member].to_i > 0 })
assert_match(/\A\{[^}]+:\d+(?:,[^}]+:\d+)*\}\z/, status.to_s)
end

def test_parse_round_trips_status
status = Memory::Status.new

assert_equal(status, Memory::Status.parse(status.to_s))
end
end