summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/mspec/lib/mspec/helpers/numeric.rb8
-rw-r--r--spec/mspec/lib/mspec/matchers/raise_error.rb35
-rw-r--r--spec/mspec/lib/mspec/runner/actions/leakchecker.rb9
-rw-r--r--spec/mspec/lib/mspec/runner/actions/timeout.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/exception.rb20
-rw-r--r--spec/mspec/lib/mspec/utils/format.rb6
-rw-r--r--spec/mspec/spec/matchers/raise_error_spec.rb53
-rw-r--r--spec/mspec/spec/runner/exception_spec.rb2
8 files changed, 97 insertions, 38 deletions
diff --git a/spec/mspec/lib/mspec/helpers/numeric.rb b/spec/mspec/lib/mspec/helpers/numeric.rb
index c6c2e82722..db1fde64d8 100644
--- a/spec/mspec/lib/mspec/helpers/numeric.rb
+++ b/spec/mspec/lib/mspec/helpers/numeric.rb
@@ -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
diff --git a/spec/mspec/lib/mspec/matchers/raise_error.rb b/spec/mspec/lib/mspec/matchers/raise_error.rb
index 0e57c1b863..878428d43a 100644
--- a/spec/mspec/lib/mspec/matchers/raise_error.rb
+++ b/spec/mspec/lib/mspec/matchers/raise_error.rb
@@ -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
diff --git a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
index f70799d904..9efabc79b4 100644
--- a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
+++ b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
@@ -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"
diff --git a/spec/mspec/lib/mspec/runner/actions/timeout.rb b/spec/mspec/lib/mspec/runner/actions/timeout.rb
index 03fe14811f..c85bf49ad3 100644
--- a/spec/mspec/lib/mspec/runner/actions/timeout.rb
+++ b/spec/mspec/lib/mspec/runner/actions/timeout.rb
@@ -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
diff --git a/spec/mspec/lib/mspec/runner/exception.rb b/spec/mspec/lib/mspec/runner/exception.rb
index 0d9bb43105..aea6610cd3 100644
--- a/spec/mspec/lib/mspec/runner/exception.rb
+++ b/spec/mspec/lib/mspec/runner/exception.rb
@@ -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
diff --git a/spec/mspec/lib/mspec/utils/format.rb b/spec/mspec/lib/mspec/utils/format.rb
index bb75e131de..425dd4d11c 100644
--- a/spec/mspec/lib/mspec/utils/format.rb
+++ b/spec/mspec/lib/mspec/utils/format.rb
@@ -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
diff --git a/spec/mspec/spec/matchers/raise_error_spec.rb b/spec/mspec/spec/matchers/raise_error_spec.rb
index 1ed794e0a9..a40acc0ea0 100644
--- a/spec/mspec/spec/matchers/raise_error_spec.rb
+++ b/spec/mspec/spec/matchers/raise_error_spec.rb
@@ -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
diff --git a/spec/mspec/spec/runner/exception_spec.rb b/spec/mspec/spec/runner/exception_spec.rb
index 309442435c..0e0a819992 100644
--- a/spec/mspec/spec/runner/exception_spec.rb
+++ b/spec/mspec/spec/runner/exception_spec.rb
@@ -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