From 9d019121fdb3d8728bac99ad7061c0cb86e8f120 Mon Sep 17 00:00:00 2001 From: Jonathan del Strother Date: Thu, 29 Feb 2024 13:46:00 +0000 Subject: [PATCH] Fix DRbUnknown error with unserializable Exception causes --- lib/flatware/serialized_exception.rb | 4 +-- .../rspec/marshalable/example_spec.rb | 29 +++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/lib/flatware/serialized_exception.rb b/lib/flatware/serialized_exception.rb index 43e5634..ec0fe29 100644 --- a/lib/flatware/serialized_exception.rb +++ b/lib/flatware/serialized_exception.rb @@ -3,11 +3,11 @@ class SerializedException attr_reader :class, :message, :cause attr_accessor :backtrace - def initialize(klass, message, backtrace, cause = '') + def initialize(klass, message, backtrace, cause = nil) @class = serialized(klass) @message = message @backtrace = backtrace - @cause = cause + @cause = cause && SerializedException.from(cause) end def self.from(exception) diff --git a/spec/flatware/rspec/marshalable/example_spec.rb b/spec/flatware/rspec/marshalable/example_spec.rb index 2bb7764..4b6b0f3 100644 --- a/spec/flatware/rspec/marshalable/example_spec.rb +++ b/spec/flatware/rspec/marshalable/example_spec.rb @@ -12,7 +12,7 @@ def stub_execution_result(exception) ) end - it 'caries what is needed to format a backtrace' do + it 'carries what is needed to format a backtrace' do exception = Exception.new RSpec::Core::Formatters::ExceptionPresenter.new( exception, @@ -29,12 +29,24 @@ def stub_execution_result(exception) ).fully_formatted(nil) end - it 'does not cary constant references in exceptions' do + it 'does not carry constant references in exceptions' do const = stub_const('A::Constant::Not::Likely::Loaded::In::Sink', Class.new(RuntimeError)) + wrapper_const = stub_const('Another::Constant::Not::Likely::Loaded::In::Sink', Class.new(RuntimeError)) + caught_exception = begin + begin + raise const, 'something bad happened' + rescue RuntimeError => e + # raise a second exception so that Exception#cause is set up + raise wrapper_const, e + end + rescue RuntimeError => e + e + end + message = described_class.new( instance_double( RSpec::Core::Example, - execution_result: stub_execution_result(const.new), + execution_result: stub_execution_result(caught_exception), full_description: nil, location: nil, location_rerun_argument: nil, @@ -42,7 +54,14 @@ def stub_execution_result(exception) ) ) - expect(message.execution_result.exception.class.to_s).to eq(const.to_s) - expect(message.execution_result.exception.class).to_not be_an_instance_of(const) + result_exception = message.execution_result.exception + + expect(result_exception).to be_an_instance_of(Flatware::SerializedException) + expect(result_exception.class.to_s).to eq(wrapper_const.to_s) + expect(result_exception.class).to_not be_an_instance_of(wrapper_const) + + expect(result_exception.cause).to be_an_instance_of(Flatware::SerializedException) + expect(result_exception.cause.class.to_s).to eq(const.to_s) + expect(result_exception.cause.class).to_not be_an_instance_of(const) end end