Skip to content

Commit

Permalink
Bump up the latest version of CoreAssertions
Browse files Browse the repository at this point in the history
  • Loading branch information
hsbt committed Sep 11, 2021
1 parent d7b5a78 commit 5ba0d59
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ end

task :sync_tool do
require 'fileutils'
FileUtils.cp "../ruby/tool/lib/test/unit/core_assertions.rb", "./test/lib"
FileUtils.cp "../ruby/tool/lib/core_assertions.rb", "./test/lib"
FileUtils.cp "../ruby/tool/lib/envutil.rb", "./test/lib"
FileUtils.cp "../ruby/tool/lib/find_executable.rb", "./test/lib"
end
Expand Down
176 changes: 144 additions & 32 deletions test/lib/core_assertions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,8 @@ def message msg = nil, ending = nil, &default
end

module CoreAssertions
if defined?(MiniTest)
require_relative '../../envutil'
# for ruby core testing
include MiniTest::Assertions

# Compatibility hack for assert_raise
Test::Unit::AssertionFailedError = MiniTest::Assertion
else
module MiniTest
class Assertion < Exception; end
class Skip < Assertion; end
end

require 'pp'
require_relative 'envutil'
include Test::Unit::Assertions
end
require_relative 'envutil'
require 'pp'

def mu_pp(obj) #:nodoc:
obj.pretty_inspect.chomp
Expand Down Expand Up @@ -115,18 +100,18 @@ def syntax_check(code, fname, line)

def assert_no_memory_leak(args, prepare, code, message=nil, limit: 2.0, rss: false, **opt)
# TODO: consider choosing some appropriate limit for MJIT and stop skipping this once it does not randomly fail
pend 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
pend 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?

require_relative '../../memory_status'
raise MiniTest::Skip, "unsupported platform" unless defined?(Memory::Status)
require_relative 'memory_status'
raise Test::Unit::PendedError, "unsupported platform" unless defined?(Memory::Status)

token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m"
token_dump = token.dump
token_re = Regexp.quote(token)
envs = args.shift if Array === args and Hash === args.first
args = [
"--disable=gems",
"-r", File.expand_path("../../../memory_status", __FILE__),
"-r", File.expand_path("../memory_status", __FILE__),
*args,
"-v", "-",
]
Expand Down Expand Up @@ -183,11 +168,11 @@ def assert_nothing_raised(*args)
end
begin
line = __LINE__; yield
rescue MiniTest::Skip
rescue Test::Unit::PendedError
raise
rescue Exception => e
bt = e.backtrace
as = e.instance_of?(MiniTest::Assertion)
as = e.instance_of?(Test::Unit::AssertionFailedError)
if as
ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o
bt.reject! {|ln| ans =~ ln}
Expand All @@ -199,7 +184,7 @@ def assert_nothing_raised(*args)
"Backtrace:\n" +
e.backtrace.map{|frame| " #{frame}"}.join("\n")
}
raise MiniTest::Assertion, msg.call, bt
raise Test::Unit::AssertionFailedError, msg.call, bt
else
raise
end
Expand Down Expand Up @@ -260,11 +245,12 @@ def assert_ruby_status(args, test_stdin="", message=nil, **opt)
ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM")

def separated_runner(out = nil)
include(*Test::Unit::TestCase.ancestors.select {|c| !c.is_a?(Class) })
out = out ? IO.new(out, 'w') : STDOUT
at_exit {
out.puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}"
out.puts [Marshal.dump($!)].pack('m'), "assertions=#{self._assertions}"
}
Test::Unit::Runner.class_variable_set(:@@stop_auto_run, true)
Test::Unit::Runner.class_variable_set(:@@stop_auto_run, true) if defined?(Test::Unit::Runner)
end

def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt)
Expand All @@ -276,14 +262,14 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o
capture_stdout = true
unless /mswin|mingw/ =~ RUBY_PLATFORM
capture_stdout = false
opt[:out] = MiniTest::Unit.output
opt[:out] = Test::Unit::Runner.output if defined?(Test::Unit::Runner)
res_p, res_c = IO.pipe
opt[res_c.fileno] = res_c.fileno
opt[:ios] = [res_c]
end
src = <<eom
# -*- coding: #{line += __LINE__; src.encoding}; -*-
BEGIN {
require "test/unit";include Test::Unit::Assertions;require #{(__dir__ + "/core_assertions").dump};include Test::Unit::CoreAssertions
require "test/unit";include Test::Unit::Assertions;require #{__FILE__.dump};include Test::Unit::CoreAssertions
separated_runner #{res_c&.fileno}
}
#{line -= __LINE__; src}
Expand Down Expand Up @@ -330,6 +316,27 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o
raise marshal_error if marshal_error
end

# Run Ractor-related test without influencing the main test suite
def assert_ractor(src, args: [], require: nil, require_relative: nil, file: nil, line: nil, ignore_stderr: nil, **opt)
return unless defined?(Ractor)

require = "require #{require.inspect}" if require
if require_relative
dir = File.dirname(caller_locations[0,1][0].absolute_path)
full_path = File.expand_path(require_relative, dir)
require = "#{require}; require #{full_path.inspect}"
end

assert_separately(args, file, line, <<~RUBY, ignore_stderr: ignore_stderr, **opt)
#{require}
previous_verbose = $VERBOSE
$VERBOSE = nil
Ractor.new {} # trigger initial warning
$VERBOSE = previous_verbose
#{src}
RUBY
end

# :call-seq:
# assert_throw( tag, failure_message = nil, &block )
#
Expand Down Expand Up @@ -380,8 +387,8 @@ def assert_raise(*exp, &b)

begin
yield
rescue MiniTest::Skip => e
return e if exp.include? MiniTest::Skip
rescue Test::Unit::PendedError => e
return e if exp.include? Test::Unit::PendedError
raise e
rescue Exception => e
expected = exp.any? { |ex|
Expand Down Expand Up @@ -456,6 +463,78 @@ def assert_raise_with_message(exception, expected, msg = nil, &block)
ex
end

MINI_DIR = File.join(File.dirname(File.expand_path(__FILE__)), "minitest") #:nodoc:

# :call-seq:
# assert(test, [failure_message])
#
#Tests if +test+ is true.
#
#+msg+ may be a String or a Proc. If +msg+ is a String, it will be used
#as the failure message. Otherwise, the result of calling +msg+ will be
#used as the message if the assertion fails.
#
#If no +msg+ is given, a default message will be used.
#
# assert(false, "This was expected to be true")
def assert(test, *msgs)
case msg = msgs.first
when String, Proc
when nil
msgs.shift
else
bt = caller.reject { |s| s.start_with?(MINI_DIR) }
raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt
end unless msgs.empty?
super
end

# :call-seq:
# assert_respond_to( object, method, failure_message = nil )
#
#Tests if the given Object responds to +method+.
#
#An optional failure message may be provided as the final argument.
#
# assert_respond_to("hello", :reverse) #Succeeds
# assert_respond_to("hello", :does_not_exist) #Fails
def assert_respond_to(obj, (meth, *priv), msg = nil)
unless priv.empty?
msg = message(msg) {
"Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv[0]}"
}
return assert obj.respond_to?(meth, *priv), msg
end
#get rid of overcounting
if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
return if obj.respond_to?(meth)
end
super(obj, meth, msg)
end

# :call-seq:
# assert_not_respond_to( object, method, failure_message = nil )
#
#Tests if the given Object does not respond to +method+.
#
#An optional failure message may be provided as the final argument.
#
# assert_not_respond_to("hello", :reverse) #Fails
# assert_not_respond_to("hello", :does_not_exist) #Succeeds
def assert_not_respond_to(obj, (meth, *priv), msg = nil)
unless priv.empty?
msg = message(msg) {
"Expected #{mu_pp(obj)} (#{obj.class}) to not respond to ##{meth}#{" privately" if priv[0]}"
}
return assert !obj.respond_to?(meth, *priv), msg
end
#get rid of overcounting
if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
return unless obj.respond_to?(meth)
end
refute_respond_to(obj, meth, msg)
end

# pattern_list is an array which contains regexp and :*.
# :* means any sequence.
#
Expand Down Expand Up @@ -515,7 +594,22 @@ def assert_warn(*args)
assert_warning(*args) {$VERBOSE = false; yield}
end

def assert_deprecated_warning(mesg = /deprecated/)
assert_warning(mesg) do
Warning[:deprecated] = true
yield
end
end

def assert_deprecated_warn(mesg = /deprecated/)
assert_warn(mesg) do
Warning[:deprecated] = true
yield
end
end

class << (AssertFile = Struct.new(:failure_message).new)
include Assertions
include CoreAssertions
def assert_file_predicate(predicate, *args)
if /\Anot_/ =~ predicate
Expand Down Expand Up @@ -606,8 +700,18 @@ def assert_join_threads(threads, message = nil)
if message
msg = "#{message}\n#{msg}"
end
raise MiniTest::Assertion, msg
raise Test::Unit::AssertionFailedError, msg
end
end

def assert_all?(obj, m = nil, &blk)
failed = []
obj.each do |*a, &b|
unless blk.call(*a, &b)
failed << (a.size > 1 ? a : a[0])
end
end
assert(failed.empty?, message(m) {failed.pretty_inspect})
end

def assert_all_assertions(msg = nil)
Expand All @@ -618,6 +722,14 @@ def assert_all_assertions(msg = nil)
end
alias all_assertions assert_all_assertions

def assert_all_assertions_foreach(msg = nil, *keys, &block)
all = AllFailures.new
all.foreach(*keys, &block)
ensure
assert(all.pass?, message(msg) {all.message.chomp(".")})
end
alias all_assertions_foreach assert_all_assertions_foreach

def message(msg = nil, *args, &default) # :nodoc:
if Proc === msg
super(nil, *args) do
Expand Down
16 changes: 8 additions & 8 deletions test/lib/envutil.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ def rubybin
class << self
attr_accessor :timeout_scale
attr_reader :original_internal_encoding, :original_external_encoding,
:original_verbose
:original_verbose, :original_warning

def capture_global_values
@original_internal_encoding = Encoding.default_internal
@original_external_encoding = Encoding.default_external
@original_verbose = $VERBOSE
@original_warning = defined?(Warning.[]) ? %i[deprecated experimental].to_h {|i| [i, Warning[i]]} : nil
end
end

Expand Down Expand Up @@ -124,7 +125,7 @@ def terminate(pid, signal = :TERM, pgroup = nil, reprieve = 1)

def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = false,
encoding: nil, timeout: 10, reprieve: 1, timeout_error: Timeout::Error,
stdout_filter: nil, stderr_filter: nil,
stdout_filter: nil, stderr_filter: nil, ios: nil,
signal: :TERM,
rubybin: EnvUtil.rubybin, precommand: nil,
**opt)
Expand All @@ -140,6 +141,8 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
out_p.set_encoding(encoding) if out_p
err_p.set_encoding(encoding) if err_p
end
ios.each {|i, o = i|opt[i] = o} if ios

c = "C"
child_env = {}
LANG_ENVS.each {|lc| child_env[lc] = c}
Expand All @@ -149,8 +152,9 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
if RUBYLIB and lib = child_env["RUBYLIB"]
child_env["RUBYLIB"] = [lib, RUBYLIB].join(File::PATH_SEPARATOR)
end
child_env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS']
args = [args] if args.kind_of?(String)
pid = spawn(child_env, *precommand, rubybin, *args, **opt)
pid = spawn(child_env, *precommand, rubybin, *args, opt)
in_c.close
out_c&.close
out_c = nil
Expand Down Expand Up @@ -197,11 +201,6 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
end
module_function :invoke_ruby

alias rubyexec invoke_ruby
class << self
alias rubyexec invoke_ruby
end

def verbose_warning
class << (stderr = "".dup)
alias write concat
Expand All @@ -214,6 +213,7 @@ def flush; end
ensure
stderr, $stderr = $stderr, stderr
$VERBOSE = EnvUtil.original_verbose
EnvUtil.original_warning&.each {|i, v| Warning[i] = v}
end
module_function :verbose_warning

Expand Down

0 comments on commit 5ba0d59

Please sign in to comment.