Ensure core exceptions get raised with $! as cause#9409
Ensure core exceptions get raised with $! as cause#9409headius wants to merge 5 commits intojruby:masterfrom
Conversation
1855854 to
9804bb8
Compare
|
@eregon There are some modifications to mspec's |
|
Failures appear to be GHA issues or bad timing in specs, unrelated to these changes. |
|
Thank you for adding more My initial thought here is whether making -> { 1 / 0 }.should raise_error(ZeroDivisionError, cause:)
# vs
-> { 1 / 0 }.should raise_error(ZeroDivisionError) { |e| e.cause.should == cause }It looks nice and it's expressive but OTOH it's not used in that many files. The main concern is MSpec tries to be as simple as possible so it can be used by early Ruby implementations. If you want to modify |
I think it will be used in many more as we continue to specify language-level exceptions that should have causes. I've only added a few cases here. And even without those additional cases, there were many places doing the block form of |
This adds a cause kwarg to raise_error for matching the cause of a captured exception. The error output for failed cases is also modified to show both message and cause if they are being matched.
9804bb8 to
7ae3e91
Compare
|
@eregon I cleaned up the commit that adds the |
eregon
left a comment
There was a problem hiding this comment.
Thank you, looks good, just needs a few more tweaks and it's good to go
| -> { raise RuntimeError, "the consequence" } | ||
| .should raise_error(RuntimeError, "the consequence", cause:) |
There was a problem hiding this comment.
| -> { raise RuntimeError, "the consequence" } | |
| .should raise_error(RuntimeError, "the consequence", cause:) | |
| -> { | |
| raise RuntimeError, "the consequence" | |
| }.should raise_error(RuntimeError, "the consequence", cause:) |
This is more consistent with ruby/spec style
| "#{exception_class} (#{message})" | ||
| else | ||
| "#{exception_class}" | ||
| string << "#{prefix.()}message: #{message.inspect}" |
There was a problem hiding this comment.
| string << "#{prefix.()}message: #{message.inspect}" | |
| string << "#{prefix.()}#{message.inspect}" |
A message: prefix every time seems quite noisy, and it's a clear a String is the message and not the cause, so let's omit that.
The #{message.inspect} sounds fine.
| attr_writer :block | ||
|
|
||
| def initialize(exception, message, &block) | ||
| def initialize(exception, message = nil, options = { }, &block) |
There was a problem hiding this comment.
| def initialize(exception, message = nil, options = { }, &block) | |
| def initialize(exception, message = nil, options = nil, &block) |
This is consistent with what raise_error below passes.
Also it avoids allocating an extra Hash when it's not used in most cases.
Below it becomes
@cause = options ? options.fetch(:cause, UNDEF_CAUSE) : UNDEF_CAUSEwhich seems simple enough to avoid the extra Hash allocation.
| matcher = RaiseErrorMatcher.new(RuntimeError, "foo", cause:) | ||
| begin | ||
| matcher.matches?(proc) | ||
| rescue RuntimeError | ||
| expect(matcher.failure_message).to eq( | ||
| ["Expected RuntimeError(message: \"foo\", cause: #<RuntimeError: bar>)", "but got: RuntimeError(message: \"foo\", cause: nil)"] | ||
| ) | ||
| end |
There was a problem hiding this comment.
It would be good to test the case with cause but not message too
| rescue UnexpectedException => e | ||
| expect(matcher.failure_message).to eq( | ||
| ["Expected ExpectedException (message)", "but got: UnexpectedException (message)"] | ||
| ["Expected ExpectedException(message: \"message\")", "but got: UnexpectedException(message: \"message\")"] |
There was a problem hiding this comment.
Minor: these would read nicer (and close to what gets printed) if using single-quote string now that we have " inside.
Many places where we raise exceptions from JRuby core code, we do not attach $! as a cause. This leads to several issues, including part of the issue reported in #9398. This PR adds specs and fixes known cases.