mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update to ruby/mspec@e3abf6b
This commit is contained in:
parent
5a79d8e050
commit
f4502b001a
8 changed files with 97 additions and 38 deletions
|
@ -12,6 +12,14 @@ def bignum_value(plus = 0)
|
||||||
0x8000_0000_0000_0000 + plus
|
0x8000_0000_0000_0000 + plus
|
||||||
end
|
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
|
# 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
|
# boundary between Fixnum and Bignum for operations like Fixnum#<<. Since
|
||||||
# this boundary is implementation-dependent, we use these helpers to write
|
# this boundary is implementation-dependent, we use these helpers to write
|
||||||
|
|
|
@ -6,34 +6,43 @@ class RaiseErrorMatcher
|
||||||
@actual = nil
|
@actual = nil
|
||||||
end
|
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)
|
def matches?(proc)
|
||||||
@result = proc.call
|
@result = proc.call
|
||||||
return false
|
return false
|
||||||
rescue Exception => actual
|
rescue Exception => actual
|
||||||
@actual = actual
|
@actual = actual
|
||||||
|
|
||||||
if matching_exception?(actual)
|
if matching_exception?(actual)
|
||||||
# The block has its own expectations and will throw an exception if it fails
|
# The block has its own expectations and will throw an exception if it fails
|
||||||
@block[actual] if @block
|
@block[actual] if @block
|
||||||
|
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
|
actual.instance_variable_set(:@mspec_raise_error_message, failure_message)
|
||||||
raise actual
|
raise actual
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def matching_exception?(exc)
|
def matching_class?(exc)
|
||||||
return false unless @exception === exc
|
@exception === exc
|
||||||
|
end
|
||||||
|
|
||||||
if @message then
|
def matching_message?(exc)
|
||||||
case @message
|
case @message
|
||||||
when String
|
when String
|
||||||
return false if @message != exc.message
|
@message == exc.message
|
||||||
when Regexp
|
when Regexp
|
||||||
return false if @message !~ exc.message
|
@message =~ exc.message
|
||||||
end
|
else
|
||||||
|
true
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return true
|
def matching_exception?(exc)
|
||||||
|
matching_class?(exc) and matching_message?(exc)
|
||||||
end
|
end
|
||||||
|
|
||||||
def exception_class_and_message(exception_class, message)
|
def exception_class_and_message(exception_class, message)
|
||||||
|
@ -56,7 +65,7 @@ class RaiseErrorMatcher
|
||||||
message = ["Expected #{format_expected_exception}"]
|
message = ["Expected #{format_expected_exception}"]
|
||||||
|
|
||||||
if @actual
|
if @actual
|
||||||
message << "but got #{format_exception(@actual)}"
|
message << "but got: #{format_exception(@actual)}"
|
||||||
else
|
else
|
||||||
message << "but no exception was raised (#{MSpec.format(@result)} was returned)"
|
message << "but no exception was raised (#{MSpec.format(@result)} was returned)"
|
||||||
end
|
end
|
||||||
|
@ -67,7 +76,7 @@ class RaiseErrorMatcher
|
||||||
def negative_failure_message
|
def negative_failure_message
|
||||||
message = ["Expected to not get #{format_expected_exception}", ""]
|
message = ["Expected to not get #{format_expected_exception}", ""]
|
||||||
unless @actual.class == @exception
|
unless @actual.class == @exception
|
||||||
message[1] = "but got #{format_exception(@actual)}"
|
message[1] = "but got: #{format_exception(@actual)}"
|
||||||
end
|
end
|
||||||
message
|
message
|
||||||
end
|
end
|
||||||
|
|
|
@ -49,6 +49,7 @@ class LeakChecker
|
||||||
check_env
|
check_env
|
||||||
check_argv
|
check_argv
|
||||||
check_encodings
|
check_encodings
|
||||||
|
check_tracepoints
|
||||||
GC.start if !@leaks.empty?
|
GC.start if !@leaks.empty?
|
||||||
@leaks.empty?
|
@leaks.empty?
|
||||||
end
|
end
|
||||||
|
@ -259,6 +260,14 @@ class LeakChecker
|
||||||
@encoding_info = [new_internal, new_external]
|
@encoding_info = [new_internal, new_external]
|
||||||
end
|
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)
|
def leak(message)
|
||||||
if @leaks.empty?
|
if @leaks.empty?
|
||||||
$stderr.puts "\n"
|
$stderr.puts "\n"
|
||||||
|
|
|
@ -37,7 +37,7 @@ class TimeoutAction
|
||||||
if elapsed > @timeout
|
if elapsed > @timeout
|
||||||
STDERR.puts "\n#{@current_state.description}"
|
STDERR.puts "\n#{@current_state.description}"
|
||||||
STDERR.flush
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ class ExceptionState
|
||||||
|
|
||||||
def initialize(state, location, exception)
|
def initialize(state, location, exception)
|
||||||
@exception = exception
|
@exception = exception
|
||||||
|
@failure = exception.class == SpecExpectationNotMetError || exception.class == SpecExpectationNotFoundError
|
||||||
|
|
||||||
@description = location ? "An exception occurred during: #{location}" : ""
|
@description = location ? "An exception occurred during: #{location}" : ""
|
||||||
if state
|
if state
|
||||||
|
@ -19,25 +20,26 @@ class ExceptionState
|
||||||
end
|
end
|
||||||
|
|
||||||
def failure?
|
def failure?
|
||||||
[SpecExpectationNotMetError, SpecExpectationNotFoundError].any? { |e| @exception.is_a? e }
|
@failure
|
||||||
end
|
end
|
||||||
|
|
||||||
def message
|
def message
|
||||||
if @exception.message.empty?
|
message = @exception.message
|
||||||
"<No message>"
|
message = "<No message>" if message.empty?
|
||||||
elsif @exception.class == SpecExpectationNotMetError ||
|
|
||||||
@exception.class == SpecExpectationNotFoundError
|
if @failure
|
||||||
@exception.message
|
message
|
||||||
|
elsif raise_error_message = @exception.instance_variable_get(:@mspec_raise_error_message)
|
||||||
|
raise_error_message.join("\n")
|
||||||
else
|
else
|
||||||
"#{@exception.class}: #{@exception.message}"
|
"#{@exception.class}: #{message}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def backtrace
|
def backtrace
|
||||||
@backtrace_filter ||= MSpecScript.config[:backtrace_filter]
|
@backtrace_filter ||= MSpecScript.config[:backtrace_filter] || %r{(?:/bin/mspec|/lib/mspec/)}
|
||||||
|
|
||||||
bt = @exception.backtrace || []
|
bt = @exception.backtrace || []
|
||||||
|
|
||||||
bt.select { |line| $MSPEC_DEBUG or @backtrace_filter !~ line }.join("\n")
|
bt.select { |line| $MSPEC_DEBUG or @backtrace_filter !~ line }.join("\n")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,11 @@ end
|
||||||
|
|
||||||
module MSpec
|
module MSpec
|
||||||
def self.format(obj)
|
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
|
rescue => e
|
||||||
"#<#{obj.class}>(#pretty_inspect raised #{e.inspect})"
|
"#<#{obj.class}>(#pretty_inspect raised #{e.inspect})"
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ describe RaiseErrorMatcher do
|
||||||
matcher.matches?(proc).should == true
|
matcher.matches?(proc).should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "executes it's optional block if matched" do
|
it "executes its optional block if matched" do
|
||||||
run = false
|
run = false
|
||||||
proc = Proc.new { raise ExpectedException }
|
proc = Proc.new { raise ExpectedException }
|
||||||
matcher = RaiseErrorMatcher.new(ExpectedException, nil) { |error|
|
matcher = RaiseErrorMatcher.new(ExpectedException, nil) { |error|
|
||||||
|
@ -62,16 +62,21 @@ describe RaiseErrorMatcher do
|
||||||
matcher.matches?(proc).should == false
|
matcher.matches?(proc).should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
it "provides a useful failure message" do
|
it "provides a useful failure message when the exception class differs" do
|
||||||
exc = UnexpectedException.new("unexpected")
|
exc = UnexpectedException.new("message")
|
||||||
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
|
matcher = RaiseErrorMatcher.new(ExpectedException, "message")
|
||||||
|
|
||||||
matcher.matching_exception?(exc).should == false
|
matcher.matching_exception?(exc).should == false
|
||||||
lambda {
|
begin
|
||||||
matcher.matches?(Proc.new { raise exc })
|
matcher.matches?(Proc.new { raise exc })
|
||||||
}.should raise_error(UnexpectedException)
|
rescue UnexpectedException => e
|
||||||
matcher.failure_message.should ==
|
matcher.failure_message.should ==
|
||||||
["Expected ExpectedException (expected)", "but got UnexpectedException (unexpected)"]
|
["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
|
end
|
||||||
|
|
||||||
it "provides a useful failure message when the proc raises the expected exception with an unexpected message" do
|
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 = RaiseErrorMatcher.new(ExpectedException, "expected")
|
||||||
|
|
||||||
matcher.matching_exception?(exc).should == false
|
matcher.matching_exception?(exc).should == false
|
||||||
lambda {
|
begin
|
||||||
matcher.matches?(Proc.new { raise exc })
|
matcher.matches?(Proc.new { raise exc })
|
||||||
}.should raise_error(ExpectedException)
|
rescue ExpectedException => e
|
||||||
matcher.failure_message.should ==
|
matcher.failure_message.should ==
|
||||||
["Expected ExpectedException (expected)", "but got ExpectedException (unexpected)"]
|
["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
|
end
|
||||||
|
|
||||||
it "provides a useful failure message when no exception is raised" do
|
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 = RaiseErrorMatcher.new(Exception, nil)
|
||||||
matcher.matches?(proc)
|
matcher.matches?(proc)
|
||||||
matcher.negative_failure_message.should ==
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -93,7 +93,7 @@ describe ExceptionState, "#message" do
|
||||||
|
|
||||||
it "returns <No message> if the exception message is empty" do
|
it "returns <No message> if the exception message is empty" do
|
||||||
exc = ExceptionState.new @state, "", Exception.new("")
|
exc = ExceptionState.new @state, "", Exception.new("")
|
||||||
exc.message.should == "<No message>"
|
exc.message.should == "Exception: <No message>"
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns the message without exception class when the exception is an SpecExpectationNotMetError" do
|
it "returns the message without exception class when the exception is an SpecExpectationNotMetError" do
|
||||||
|
|
Loading…
Reference in a new issue