Skip to content

Commit 41b1d8b

Browse files
committed
Update the latest CoreAssetion for assert_normal_exit
1 parent f033bb4 commit 41b1d8b

File tree

1 file changed

+144
-14
lines changed

1 file changed

+144
-14
lines changed

test/lib/core_assertions.rb

Lines changed: 144 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@ module CoreAssertions
2828
require_relative '../../envutil'
2929
# for ruby core testing
3030
include MiniTest::Assertions
31+
32+
# Compatibility hack for assert_raise
33+
Test::Unit::AssertionFailedError = MiniTest::Assertion
3134
else
3235
module MiniTest
33-
class Skip; end
36+
class Assertion < Exception; end
37+
class Skip < Assertion; end
3438
end
3539

3640
require 'pp'
@@ -90,6 +94,112 @@ def assert_in_out_err(args, test_stdin = "", test_stdout = [], test_stderr = [],
9094
end
9195
end
9296

97+
if defined?(RubyVM::InstructionSequence)
98+
def syntax_check(code, fname, line)
99+
code = code.dup.force_encoding(Encoding::UTF_8)
100+
RubyVM::InstructionSequence.compile(code, fname, fname, line)
101+
:ok
102+
ensure
103+
raise if SyntaxError === $!
104+
end
105+
else
106+
def syntax_check(code, fname, line)
107+
code = code.b
108+
code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) {
109+
"#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ok}\n"
110+
}
111+
code = code.force_encoding(Encoding::UTF_8)
112+
catch {|tag| eval(code, binding, fname, line - 1)}
113+
end
114+
end
115+
116+
# :call-seq:
117+
# assert_nothing_raised( *args, &block )
118+
#
119+
#If any exceptions are given as arguments, the assertion will
120+
#fail if one of those exceptions are raised. Otherwise, the test fails
121+
#if any exceptions are raised.
122+
#
123+
#The final argument may be a failure message.
124+
#
125+
# assert_nothing_raised RuntimeError do
126+
# raise Exception #Assertion passes, Exception is not a RuntimeError
127+
# end
128+
#
129+
# assert_nothing_raised do
130+
# raise Exception #Assertion fails
131+
# end
132+
def assert_nothing_raised(*args)
133+
self._assertions += 1
134+
if Module === args.last
135+
msg = nil
136+
else
137+
msg = args.pop
138+
end
139+
begin
140+
line = __LINE__; yield
141+
rescue MiniTest::Skip
142+
raise
143+
rescue Exception => e
144+
bt = e.backtrace
145+
as = e.instance_of?(MiniTest::Assertion)
146+
if as
147+
ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o
148+
bt.reject! {|ln| ans =~ ln}
149+
end
150+
if ((args.empty? && !as) ||
151+
args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a })
152+
msg = message(msg) { "Exception raised:\n<#{mu_pp(e)}>" }
153+
raise MiniTest::Assertion, msg.call, bt
154+
else
155+
raise
156+
end
157+
end
158+
end
159+
160+
def prepare_syntax_check(code, fname = nil, mesg = nil, verbose: nil)
161+
fname ||= caller_locations(2, 1)[0]
162+
mesg ||= fname.to_s
163+
verbose, $VERBOSE = $VERBOSE, verbose
164+
case
165+
when Array === fname
166+
fname, line = *fname
167+
when defined?(fname.path) && defined?(fname.lineno)
168+
fname, line = fname.path, fname.lineno
169+
else
170+
line = 1
171+
end
172+
yield(code, fname, line, message(mesg) {
173+
if code.end_with?("\n")
174+
"```\n#{code}```\n"
175+
else
176+
"```\n#{code}\n```\n""no-newline"
177+
end
178+
})
179+
ensure
180+
$VERBOSE = verbose
181+
end
182+
183+
def assert_valid_syntax(code, *args, **opt)
184+
prepare_syntax_check(code, *args, **opt) do |src, fname, line, mesg|
185+
yield if defined?(yield)
186+
assert_nothing_raised(SyntaxError, mesg) do
187+
assert_equal(:ok, syntax_check(src, fname, line), mesg)
188+
end
189+
end
190+
end
191+
192+
def assert_normal_exit(testsrc, message = '', child_env: nil, **opt)
193+
assert_valid_syntax(testsrc, caller_locations(1, 1)[0])
194+
if child_env
195+
child_env = [child_env]
196+
else
197+
child_env = []
198+
end
199+
out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, **opt)
200+
assert !status.signaled?, FailDesc[status, message, out]
201+
end
202+
93203
def assert_ruby_status(args, test_stdin="", message=nil, **opt)
94204
out, _, status = EnvUtil.invoke_ruby(args, test_stdin, true, :merge_to_stdout, **opt)
95205
desc = FailDesc[status, message, out]
@@ -100,35 +210,55 @@ def assert_ruby_status(args, test_stdin="", message=nil, **opt)
100210

101211
ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM")
102212

213+
def separated_runner(out = nil)
214+
out = out ? IO.new(out, 'w') : STDOUT
215+
at_exit {
216+
out.puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}"
217+
}
218+
Test::Unit::Runner.class_variable_set(:@@stop_auto_run, true)
219+
end
220+
103221
def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt)
104222
unless file and line
105223
loc, = caller_locations(1,1)
106224
file ||= loc.path
107225
line ||= loc.lineno
108226
end
227+
capture_stdout = true
228+
unless /mswin|mingw/ =~ RUBY_PLATFORM
229+
capture_stdout = false
230+
opt[:out] = MiniTest::Unit.output
231+
res_p, res_c = IO.pipe
232+
opt[res_c.fileno] = res_c.fileno
233+
end
109234
src = <<eom
110235
# -*- coding: #{line += __LINE__; src.encoding}; -*-
236+
BEGIN {
111237
require "test/unit";include Test::Unit::Assertions;require #{(__dir__ + "/core_assertions").dump};include Test::Unit::CoreAssertions
112-
END {
113-
puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}"
114-
}
238+
separated_runner #{res_c&.fileno}
239+
}
115240
#{line -= __LINE__; src}
116-
class Test::Unit::Runner
117-
@@stop_auto_run = true
118-
end
119241
eom
120242
args = args.dup
121243
args.insert((Hash === args.first ? 1 : 0), "-w", "--disable=gems", *$:.map {|l| "-I#{l}"})
122-
stdout, stderr, status = EnvUtil.invoke_ruby(args, src, true, true, **opt)
244+
stdout, stderr, status = EnvUtil.invoke_ruby(args, src, capture_stdout, true, **opt)
245+
if res_c
246+
res_c.close
247+
res = res_p.read
248+
res_p.close
249+
else
250+
res = stdout
251+
end
123252
abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig))
124253
assert(!abort, FailDesc[status, nil, stderr])
125-
self._assertions += stdout[/^assertions=(\d+)/, 1].to_i
254+
self._assertions += res[/^assertions=(\d+)/, 1].to_i
126255
begin
127-
res = Marshal.load(stdout.unpack("m")[0])
256+
res = Marshal.load(res.unpack1("m"))
128257
rescue => marshal_error
129258
ignore_stderr = nil
259+
res = nil
130260
end
131-
if res
261+
if res and !(SystemExit === res)
132262
if bt = res.backtrace
133263
bt.each do |l|
134264
l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"}
@@ -137,7 +267,7 @@ class Test::Unit::Runner
137267
else
138268
res.set_backtrace(caller)
139269
end
140-
raise res unless SystemExit === res
270+
raise res
141271
end
142272

143273
# really is it succeed?
@@ -212,7 +342,7 @@ def assert_raise(*exp, &b)
212342
}
213343

214344
assert expected, proc {
215-
exception_details(e, message(msg) {"#{mu_pp(exp)} exception expected, not"}.call)
345+
flunk(message(msg) {"#{mu_pp(exp)} exception expected, not #{mu_pp(e)}"})
216346
}
217347

218348
return e
@@ -377,7 +507,7 @@ def assert_join_threads(threads, message = nil)
377507
msg = "exceptions on #{errs.length} threads:\n" +
378508
errs.map {|t, err|
379509
"#{t.inspect}:\n" +
380-
err.full_message(highlight: false, order: :top)
510+
RUBY_VERSION >= "2.5.0" ? err.full_message(highlight: false, order: :top) : err.message
381511
}.join("\n---\n")
382512
if message
383513
msg = "#{message}\n#{msg}"

0 commit comments

Comments
 (0)