This commit is contained in:
Benoit Daloze 2020-05-31 18:22:47 +02:00
Родитель 5a79d8e050
Коммит f4502b001a
8 изменённых файлов: 97 добавлений и 38 удалений

Просмотреть файл

@ -12,6 +12,14 @@ def bignum_value(plus = 0)
0x8000_0000_0000_0000 + plus
end
def max_long
2**(0.size * 8 - 1) - 1
end
def min_long
-(2**(0.size * 8 - 1))
end
# This is a bit hairy, but we need to be able to write specs that cover the
# boundary between Fixnum and Bignum for operations like Fixnum#<<. Since
# this boundary is implementation-dependent, we use these helpers to write

Просмотреть файл

@ -6,34 +6,43 @@ class RaiseErrorMatcher
@actual = nil
end
# This #matches? method is unusual because it doesn't always return a boolean but instead
# re-raises the original exception if proc.call raises an exception and #matching_exception? is false.
# The reasoning is the original exception class matters and we don't want to change it by raising another exception,
# so instead we attach the #failure_message and extract it in ExceptionState#message.
def matches?(proc)
@result = proc.call
return false
rescue Exception => actual
@actual = actual
if matching_exception?(actual)
# The block has its own expectations and will throw an exception if it fails
@block[actual] if @block
return true
else
actual.instance_variable_set(:@mspec_raise_error_message, failure_message)
raise actual
end
end
def matching_exception?(exc)
return false unless @exception === exc
def matching_class?(exc)
@exception === exc
end
if @message then
case @message
when String
return false if @message != exc.message
when Regexp
return false if @message !~ exc.message
end
def matching_message?(exc)
case @message
when String
@message == exc.message
when Regexp
@message =~ exc.message
else
true
end
end
return true
def matching_exception?(exc)
matching_class?(exc) and matching_message?(exc)
end
def exception_class_and_message(exception_class, message)
@ -56,7 +65,7 @@ class RaiseErrorMatcher
message = ["Expected #{format_expected_exception}"]
if @actual
message << "but got #{format_exception(@actual)}"
message << "but got: #{format_exception(@actual)}"
else
message << "but no exception was raised (#{MSpec.format(@result)} was returned)"
end
@ -67,7 +76,7 @@ class RaiseErrorMatcher
def negative_failure_message
message = ["Expected to not get #{format_expected_exception}", ""]
unless @actual.class == @exception
message[1] = "but got #{format_exception(@actual)}"
message[1] = "but got: #{format_exception(@actual)}"
end
message
end

Просмотреть файл

@ -49,6 +49,7 @@ class LeakChecker
check_env
check_argv
check_encodings
check_tracepoints
GC.start if !@leaks.empty?
@leaks.empty?
end
@ -259,6 +260,14 @@ class LeakChecker
@encoding_info = [new_internal, new_external]
end
def check_tracepoints
ObjectSpace.each_object(TracePoint) do |tp|
if tp.enabled?
leak "TracePoint is still enabled: #{tp.inspect}"
end
end
end
def leak(message)
if @leaks.empty?
$stderr.puts "\n"

Просмотреть файл

@ -37,7 +37,7 @@ class TimeoutAction
if elapsed > @timeout
STDERR.puts "\n#{@current_state.description}"
STDERR.flush
abort "Example took #{now - @started}s, which is longer than the timeout of #{@timeout}s"
abort "Example took longer than the configured timeout of #{@timeout}s"
end
end
end

Просмотреть файл

@ -6,6 +6,7 @@ class ExceptionState
def initialize(state, location, exception)
@exception = exception
@failure = exception.class == SpecExpectationNotMetError || exception.class == SpecExpectationNotFoundError
@description = location ? "An exception occurred during: #{location}" : ""
if state
@ -19,25 +20,26 @@ class ExceptionState
end
def failure?
[SpecExpectationNotMetError, SpecExpectationNotFoundError].any? { |e| @exception.is_a? e }
@failure
end
def message
if @exception.message.empty?
"<No message>"
elsif @exception.class == SpecExpectationNotMetError ||
@exception.class == SpecExpectationNotFoundError
@exception.message
message = @exception.message
message = "<No message>" if message.empty?
if @failure
message
elsif raise_error_message = @exception.instance_variable_get(:@mspec_raise_error_message)
raise_error_message.join("\n")
else
"#{@exception.class}: #{@exception.message}"
"#{@exception.class}: #{message}"
end
end
def backtrace
@backtrace_filter ||= MSpecScript.config[:backtrace_filter]
@backtrace_filter ||= MSpecScript.config[:backtrace_filter] || %r{(?:/bin/mspec|/lib/mspec/)}
bt = @exception.backtrace || []
bt.select { |line| $MSPEC_DEBUG or @backtrace_filter !~ line }.join("\n")
end
end

Просмотреть файл

@ -13,7 +13,11 @@ end
module MSpec
def self.format(obj)
obj.pretty_inspect.chomp
if String === obj and obj.include?("\n")
"\n#{obj.inspect.gsub('\n', "\n")}"
else
obj.pretty_inspect.chomp
end
rescue => e
"#<#{obj.class}>(#pretty_inspect raised #{e.inspect})"
end

Просмотреть файл

@ -12,7 +12,7 @@ describe RaiseErrorMatcher do
matcher.matches?(proc).should == true
end
it "executes it's optional block if matched" do
it "executes its optional block if matched" do
run = false
proc = Proc.new { raise ExpectedException }
matcher = RaiseErrorMatcher.new(ExpectedException, nil) { |error|
@ -62,16 +62,21 @@ describe RaiseErrorMatcher do
matcher.matches?(proc).should == false
end
it "provides a useful failure message" do
exc = UnexpectedException.new("unexpected")
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
it "provides a useful failure message when the exception class differs" do
exc = UnexpectedException.new("message")
matcher = RaiseErrorMatcher.new(ExpectedException, "message")
matcher.matching_exception?(exc).should == false
lambda {
begin
matcher.matches?(Proc.new { raise exc })
}.should raise_error(UnexpectedException)
matcher.failure_message.should ==
["Expected ExpectedException (expected)", "but got UnexpectedException (unexpected)"]
rescue UnexpectedException => e
matcher.failure_message.should ==
["Expected ExpectedException (message)", "but got: UnexpectedException (message)"]
ExceptionState.new(nil, nil, e).message.should ==
"Expected ExpectedException (message)\nbut got: UnexpectedException (message)"
else
raise "no exception"
end
end
it "provides a useful failure message when the proc raises the expected exception with an unexpected message" do
@ -79,11 +84,33 @@ describe RaiseErrorMatcher do
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
matcher.matching_exception?(exc).should == false
lambda {
begin
matcher.matches?(Proc.new { raise exc })
}.should raise_error(ExpectedException)
matcher.failure_message.should ==
["Expected ExpectedException (expected)", "but got ExpectedException (unexpected)"]
rescue ExpectedException => e
matcher.failure_message.should ==
["Expected ExpectedException (expected)", "but got: ExpectedException (unexpected)"]
ExceptionState.new(nil, nil, e).message.should ==
"Expected ExpectedException (expected)\nbut got: ExpectedException (unexpected)"
else
raise "no exception"
end
end
it "provides a useful failure message when both the exception class and message differ" do
exc = UnexpectedException.new("unexpected")
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
matcher.matching_exception?(exc).should == false
begin
matcher.matches?(Proc.new { raise exc })
rescue UnexpectedException => e
matcher.failure_message.should ==
["Expected ExpectedException (expected)", "but got: UnexpectedException (unexpected)"]
ExceptionState.new(nil, nil, e).message.should ==
"Expected ExpectedException (expected)\nbut got: UnexpectedException (unexpected)"
else
raise "no exception"
end
end
it "provides a useful failure message when no exception is raised" do
@ -127,6 +154,6 @@ describe RaiseErrorMatcher do
matcher = RaiseErrorMatcher.new(Exception, nil)
matcher.matches?(proc)
matcher.negative_failure_message.should ==
["Expected to not get Exception", "but got UnexpectedException (unexpected)"]
["Expected to not get Exception", "but got: UnexpectedException (unexpected)"]
end
end

Просмотреть файл

@ -93,7 +93,7 @@ describe ExceptionState, "#message" do
it "returns <No message> if the exception message is empty" do
exc = ExceptionState.new @state, "", Exception.new("")
exc.message.should == "<No message>"
exc.message.should == "Exception: <No message>"
end
it "returns the message without exception class when the exception is an SpecExpectationNotMetError" do