Skip to content

Commit edfa731

Browse files
committed
Bump up the latest version of CoreAssertions
1 parent bea3b8a commit edfa731

File tree

3 files changed

+169
-41
lines changed

3 files changed

+169
-41
lines changed

Rakefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ end
99

1010
task :sync_tool do
1111
require 'fileutils'
12-
FileUtils.cp "../ruby/tool/lib/test/unit/core_assertions.rb", "./test/lib"
12+
FileUtils.cp "../ruby/tool/lib/core_assertions.rb", "./test/lib"
1313
FileUtils.cp "../ruby/tool/lib/envutil.rb", "./test/lib"
1414
FileUtils.cp "../ruby/tool/lib/find_executable.rb", "./test/lib"
1515
end

test/lib/core_assertions.rb

Lines changed: 160 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,8 @@ def message msg = nil, ending = nil, &default
2424
end
2525

2626
module CoreAssertions
27-
if defined?(MiniTest)
28-
require_relative '../../envutil'
29-
# for ruby core testing
30-
include MiniTest::Assertions
31-
32-
# Compatibility hack for assert_raise
33-
Test::Unit::AssertionFailedError = MiniTest::Assertion
34-
else
35-
module MiniTest
36-
class Assertion < Exception; end
37-
class Skip < Assertion; end
38-
end
39-
40-
require 'pp'
41-
require_relative 'envutil'
42-
include Test::Unit::Assertions
43-
end
27+
require_relative 'envutil'
28+
require 'pp'
4429

4530
def mu_pp(obj) #:nodoc:
4631
obj.pretty_inspect.chomp
@@ -115,18 +100,18 @@ def syntax_check(code, fname, line)
115100

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

120-
require_relative '../../memory_status'
121-
raise MiniTest::Skip, "unsupported platform" unless defined?(Memory::Status)
105+
require_relative 'memory_status'
106+
raise Test::Unit::PendedError, "unsupported platform" unless defined?(Memory::Status)
122107

123108
token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m"
124109
token_dump = token.dump
125110
token_re = Regexp.quote(token)
126111
envs = args.shift if Array === args and Hash === args.first
127112
args = [
128113
"--disable=gems",
129-
"-r", File.expand_path("../../../memory_status", __FILE__),
114+
"-r", File.expand_path("../memory_status", __FILE__),
130115
*args,
131116
"-v", "-",
132117
]
@@ -183,11 +168,11 @@ def assert_nothing_raised(*args)
183168
end
184169
begin
185170
line = __LINE__; yield
186-
rescue MiniTest::Skip
171+
rescue Test::Unit::PendedError
187172
raise
188173
rescue Exception => e
189174
bt = e.backtrace
190-
as = e.instance_of?(MiniTest::Assertion)
175+
as = e.instance_of?(Test::Unit::AssertionFailedError)
191176
if as
192177
ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o
193178
bt.reject! {|ln| ans =~ ln}
@@ -199,7 +184,7 @@ def assert_nothing_raised(*args)
199184
"Backtrace:\n" +
200185
e.backtrace.map{|frame| " #{frame}"}.join("\n")
201186
}
202-
raise MiniTest::Assertion, msg.call, bt
187+
raise Test::Unit::AssertionFailedError, msg.call, bt
203188
else
204189
raise
205190
end
@@ -260,11 +245,12 @@ def assert_ruby_status(args, test_stdin="", message=nil, **opt)
260245
ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM")
261246

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

270256
def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt)
@@ -276,14 +262,14 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o
276262
capture_stdout = true
277263
unless /mswin|mingw/ =~ RUBY_PLATFORM
278264
capture_stdout = false
279-
opt[:out] = MiniTest::Unit.output
265+
opt[:out] = Test::Unit::Runner.output if defined?(Test::Unit::Runner)
280266
res_p, res_c = IO.pipe
281-
opt[res_c.fileno] = res_c.fileno
267+
opt[:ios] = [res_c]
282268
end
283269
src = <<eom
284270
# -*- coding: #{line += __LINE__; src.encoding}; -*-
285271
BEGIN {
286-
require "test/unit";include Test::Unit::Assertions;require #{(__dir__ + "/core_assertions").dump};include Test::Unit::CoreAssertions
272+
require "test/unit";include Test::Unit::Assertions;require #{__FILE__.dump};include Test::Unit::CoreAssertions
287273
separated_runner #{res_c&.fileno}
288274
}
289275
#{line -= __LINE__; src}
@@ -330,6 +316,27 @@ def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **o
330316
raise marshal_error if marshal_error
331317
end
332318

319+
# Run Ractor-related test without influencing the main test suite
320+
def assert_ractor(src, args: [], require: nil, require_relative: nil, file: nil, line: nil, ignore_stderr: nil, **opt)
321+
return unless defined?(Ractor)
322+
323+
require = "require #{require.inspect}" if require
324+
if require_relative
325+
dir = File.dirname(caller_locations[0,1][0].absolute_path)
326+
full_path = File.expand_path(require_relative, dir)
327+
require = "#{require}; require #{full_path.inspect}"
328+
end
329+
330+
assert_separately(args, file, line, <<~RUBY, ignore_stderr: ignore_stderr, **opt)
331+
#{require}
332+
previous_verbose = $VERBOSE
333+
$VERBOSE = nil
334+
Ractor.new {} # trigger initial warning
335+
$VERBOSE = previous_verbose
336+
#{src}
337+
RUBY
338+
end
339+
333340
# :call-seq:
334341
# assert_throw( tag, failure_message = nil, &block )
335342
#
@@ -380,8 +387,8 @@ def assert_raise(*exp, &b)
380387

381388
begin
382389
yield
383-
rescue MiniTest::Skip => e
384-
return e if exp.include? MiniTest::Skip
390+
rescue Test::Unit::PendedError => e
391+
return e if exp.include? Test::Unit::PendedError
385392
raise e
386393
rescue Exception => e
387394
expected = exp.any? { |ex|
@@ -456,6 +463,78 @@ def assert_raise_with_message(exception, expected, msg = nil, &block)
456463
ex
457464
end
458465

466+
MINI_DIR = File.join(File.dirname(File.expand_path(__FILE__)), "minitest") #:nodoc:
467+
468+
# :call-seq:
469+
# assert(test, [failure_message])
470+
#
471+
#Tests if +test+ is true.
472+
#
473+
#+msg+ may be a String or a Proc. If +msg+ is a String, it will be used
474+
#as the failure message. Otherwise, the result of calling +msg+ will be
475+
#used as the message if the assertion fails.
476+
#
477+
#If no +msg+ is given, a default message will be used.
478+
#
479+
# assert(false, "This was expected to be true")
480+
def assert(test, *msgs)
481+
case msg = msgs.first
482+
when String, Proc
483+
when nil
484+
msgs.shift
485+
else
486+
bt = caller.reject { |s| s.start_with?(MINI_DIR) }
487+
raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt
488+
end unless msgs.empty?
489+
super
490+
end
491+
492+
# :call-seq:
493+
# assert_respond_to( object, method, failure_message = nil )
494+
#
495+
#Tests if the given Object responds to +method+.
496+
#
497+
#An optional failure message may be provided as the final argument.
498+
#
499+
# assert_respond_to("hello", :reverse) #Succeeds
500+
# assert_respond_to("hello", :does_not_exist) #Fails
501+
def assert_respond_to(obj, (meth, *priv), msg = nil)
502+
unless priv.empty?
503+
msg = message(msg) {
504+
"Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv[0]}"
505+
}
506+
return assert obj.respond_to?(meth, *priv), msg
507+
end
508+
#get rid of overcounting
509+
if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
510+
return if obj.respond_to?(meth)
511+
end
512+
super(obj, meth, msg)
513+
end
514+
515+
# :call-seq:
516+
# assert_not_respond_to( object, method, failure_message = nil )
517+
#
518+
#Tests if the given Object does not respond to +method+.
519+
#
520+
#An optional failure message may be provided as the final argument.
521+
#
522+
# assert_not_respond_to("hello", :reverse) #Fails
523+
# assert_not_respond_to("hello", :does_not_exist) #Succeeds
524+
def assert_not_respond_to(obj, (meth, *priv), msg = nil)
525+
unless priv.empty?
526+
msg = message(msg) {
527+
"Expected #{mu_pp(obj)} (#{obj.class}) to not respond to ##{meth}#{" privately" if priv[0]}"
528+
}
529+
return assert !obj.respond_to?(meth, *priv), msg
530+
end
531+
#get rid of overcounting
532+
if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
533+
return unless obj.respond_to?(meth)
534+
end
535+
refute_respond_to(obj, meth, msg)
536+
end
537+
459538
# pattern_list is an array which contains regexp and :*.
460539
# :* means any sequence.
461540
#
@@ -515,7 +594,22 @@ def assert_warn(*args)
515594
assert_warning(*args) {$VERBOSE = false; yield}
516595
end
517596

597+
def assert_deprecated_warning(mesg = /deprecated/)
598+
assert_warning(mesg) do
599+
Warning[:deprecated] = true
600+
yield
601+
end
602+
end
603+
604+
def assert_deprecated_warn(mesg = /deprecated/)
605+
assert_warn(mesg) do
606+
Warning[:deprecated] = true
607+
yield
608+
end
609+
end
610+
518611
class << (AssertFile = Struct.new(:failure_message).new)
612+
include Assertions
519613
include CoreAssertions
520614
def assert_file_predicate(predicate, *args)
521615
if /\Anot_/ =~ predicate
@@ -606,10 +700,20 @@ def assert_join_threads(threads, message = nil)
606700
if message
607701
msg = "#{message}\n#{msg}"
608702
end
609-
raise MiniTest::Assertion, msg
703+
raise Test::Unit::AssertionFailedError, msg
610704
end
611705
end
612706

707+
def assert_all?(obj, m = nil, &blk)
708+
failed = []
709+
obj.each do |*a, &b|
710+
unless blk.call(*a, &b)
711+
failed << (a.size > 1 ? a : a[0])
712+
end
713+
end
714+
assert(failed.empty?, message(m) {failed.pretty_inspect})
715+
end
716+
613717
def assert_all_assertions(msg = nil)
614718
all = AllFailures.new
615719
yield all
@@ -618,6 +722,14 @@ def assert_all_assertions(msg = nil)
618722
end
619723
alias all_assertions assert_all_assertions
620724

725+
def assert_all_assertions_foreach(msg = nil, *keys, &block)
726+
all = AllFailures.new
727+
all.foreach(*keys, &block)
728+
ensure
729+
assert(all.pass?, message(msg) {all.message.chomp(".")})
730+
end
731+
alias all_assertions_foreach assert_all_assertions_foreach
732+
621733
def message(msg = nil, *args, &default) # :nodoc:
622734
if Proc === msg
623735
super(nil, *args) do
@@ -635,6 +747,22 @@ def message(msg = nil, *args, &default) # :nodoc:
635747
super
636748
end
637749
end
750+
751+
def diff(exp, act)
752+
require 'pp'
753+
q = PP.new(+"")
754+
q.guard_inspect_key do
755+
q.group(2, "expected: ") do
756+
q.pp exp
757+
end
758+
q.text q.newline
759+
q.group(2, "actual: ") do
760+
q.pp act
761+
end
762+
q.flush
763+
end
764+
q.output
765+
end
638766
end
639767
end
640768
end

test/lib/envutil.rb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,13 @@ def rubybin
4747
class << self
4848
attr_accessor :timeout_scale
4949
attr_reader :original_internal_encoding, :original_external_encoding,
50-
:original_verbose
50+
:original_verbose, :original_warning
5151

5252
def capture_global_values
5353
@original_internal_encoding = Encoding.default_internal
5454
@original_external_encoding = Encoding.default_external
5555
@original_verbose = $VERBOSE
56+
@original_warning = defined?(Warning.[]) ? %i[deprecated experimental].to_h {|i| [i, Warning[i]]} : nil
5657
end
5758
end
5859

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

125126
def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr = false,
126127
encoding: nil, timeout: 10, reprieve: 1, timeout_error: Timeout::Error,
127-
stdout_filter: nil, stderr_filter: nil,
128+
stdout_filter: nil, stderr_filter: nil, ios: nil,
128129
signal: :TERM,
129130
rubybin: EnvUtil.rubybin, precommand: nil,
130131
**opt)
@@ -140,6 +141,8 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
140141
out_p.set_encoding(encoding) if out_p
141142
err_p.set_encoding(encoding) if err_p
142143
end
144+
ios.each {|i, o = i|opt[i] = o} if ios
145+
143146
c = "C"
144147
child_env = {}
145148
LANG_ENVS.each {|lc| child_env[lc] = c}
@@ -149,8 +152,9 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
149152
if RUBYLIB and lib = child_env["RUBYLIB"]
150153
child_env["RUBYLIB"] = [lib, RUBYLIB].join(File::PATH_SEPARATOR)
151154
end
155+
child_env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS']
152156
args = [args] if args.kind_of?(String)
153-
pid = spawn(child_env, *precommand, rubybin, *args, **opt)
157+
pid = spawn(child_env, *precommand, rubybin, *args, opt)
154158
in_c.close
155159
out_c&.close
156160
out_c = nil
@@ -197,11 +201,6 @@ def invoke_ruby(args, stdin_data = "", capture_stdout = false, capture_stderr =
197201
end
198202
module_function :invoke_ruby
199203

200-
alias rubyexec invoke_ruby
201-
class << self
202-
alias rubyexec invoke_ruby
203-
end
204-
205204
def verbose_warning
206205
class << (stderr = "".dup)
207206
alias write concat
@@ -214,6 +213,7 @@ def flush; end
214213
ensure
215214
stderr, $stderr = $stderr, stderr
216215
$VERBOSE = EnvUtil.original_verbose
216+
EnvUtil.original_warning&.each {|i, v| Warning[i] = v}
217217
end
218218
module_function :verbose_warning
219219

0 commit comments

Comments
 (0)