spec/standalone/ucblit/logging/loggers_spec.rb in berkeley_library-logging-0.2.0 vs spec/standalone/ucblit/logging/loggers_spec.rb in berkeley_library-logging-0.2.1
- old
+ new
@@ -7,19 +7,42 @@
attr_reader :out
# rubocop:disable Lint/ConstantDefinitionInBlock
before(:each) do
@out = StringIO.new
- class ::TestError < StandardError; end
+ class ::TestError < StandardError
+ attr_writer :cause
+
+ def cause
+ @cause || super
+ end
+ end
end
# rubocop:enable Lint/ConstantDefinitionInBlock
after(:each) do
Object.send(:remove_const, :TestError)
end
describe :new_json_logger do
+
+ # TODO: rewrite this as a matcher
+ # rubocop:disable Metrics/AbcSize
+ def assert_serialized_error(err_json, err)
+ expect(err_json).to be_a(Hash)
+ expect(err_json['name']).to eq(TestError.name)
+ expect(err_json['message']).to eq(err.message)
+
+ err_stack = err_json['stack']
+ backtrace = err.backtrace
+ expect(backtrace).not_to be_nil # just to be sure
+ backtrace.each do |line|
+ expect(err_stack).to include(line)
+ end
+ end
+ # rubocop:enable Metrics/AbcSize
+
it 'supports tagged logging' do
logger = Loggers.new_json_logger(out)
logger = ActiveSupport::TaggedLogging.new(logger)
expected_tag = 'hello'
@@ -36,29 +59,66 @@
msg = 'Help I am trapped in a unit test'
begin
raise TestError, msg
rescue TestError => e
- ex = e
Loggers.new_json_logger(out).error(e)
end
logged_json = JSON.parse(out.string)
- expect(logged_json['msg']).to eq(msg)
+ expect(logged_json['msg']).to eq(e.message)
+ assert_serialized_error(logged_json['err'], e)
+ end
+
+ # rubocop:disable Naming/RescuedExceptionsVariableName
+ it 'includes the error cause' do
+ msg_outer = 'Help I am trapped in the outer part of a unit test'
+ msg_inner = 'Help I am trapped in the inner part of a unit test'
+
+ begin
+ raise TestError, msg_inner
+ rescue TestError => ex_inner
+ begin
+ raise TestError, msg_outer
+ rescue TestError => ex_outer
+ Loggers.new_json_logger(out).error(ex_outer)
+ end
+ end
+
+ expect(ex_outer.cause).to eq(ex_inner) # just to be sure
+
+ logged_json = JSON.parse(out.string)
+ expect(logged_json['msg']).to eq(ex_outer.message)
+
err_json = logged_json['err']
- expect(err_json).to be_a(Hash)
- expect(err_json['name']).to eq(TestError.name)
- expect(err_json['message']).to eq(msg)
+ assert_serialized_error(err_json, ex_outer)
- err_stack = err_json['stack']
- backtrace = ex.backtrace
- expect(backtrace).not_to be_nil # just to be sure
- backtrace.each do |line|
- expect(err_stack).to include(line)
+ cause_json = err_json['cause']
+ expect(cause_json).not_to be_nil
+ assert_serialized_error(cause_json, ex_inner)
+ end
+ end
+ # rubocop:enable Naming/RescuedExceptionsVariableName
+
+ # rubocop:disable Naming/RescuedExceptionsVariableName
+ it 'handles pathological circular references' do
+ msg_outer = 'Help I am trapped in the outer part of a unit test'
+ msg_inner = 'Help I am trapped in the inner part of a unit test'
+
+ begin
+ raise TestError, msg_inner
+ rescue TestError => ex_inner
+ begin
+ raise TestError, msg_outer
+ rescue TestError => ex_outer
+ ex_inner.cause = ex_outer
end
end
+
+ expect { Loggers.new_json_logger(out).error(ex_outer) }.not_to raise_error(SystemStackError)
end
+ # rubocop:enable Naming/RescuedExceptionsVariableName
describe :default_logger do
it 'returns a readable $stdout logger' do
logger = Loggers.default_logger
expect(logger).to be_a(Logger)
@@ -130,11 +190,11 @@
expect(logged_txt).to include(k.inspect)
expect(logged_txt).to include(v.inspect)
end
end
- it 'logs an error with cause and backtrace' do
+ it 'logs an error with backtrace' do
msg_txt = 'message text'
ex_msg = 'Help I am trapped in a unit test'
begin
raise TestError, ex_msg
@@ -152,10 +212,41 @@
backtrace.each do |line|
expect(logged_txt).to include(line)
end
end
+ # rubocop:disable Naming/RescuedExceptionsVariableName
+ it 'includes the error cause' do
+ msg_outer = 'Help I am trapped in the outer part of a unit test'
+ msg_inner = 'Help I am trapped in the inner part of a unit test'
+
+ begin
+ raise TestError, msg_inner
+ rescue TestError => ex_inner
+ begin
+ raise TestError, msg_outer
+ rescue TestError => ex_outer
+ Loggers.new_readable_logger(out).error(ex_outer)
+ end
+ end
+
+ expect(ex_outer.cause).to eq(ex_inner) # just to be sure
+
+ logged_txt = out.string
+ [ex_inner, ex_outer].each do |ex|
+ msg = ex.message
+ expect(logged_txt).to include(msg)
+
+ backtrace = ex.backtrace
+ expect(backtrace).not_to be_nil # just to be sure
+ backtrace.each do |line|
+ expect(logged_txt).to include(line)
+ end
+ end
+ end
+ # rubocop:enable Naming/RescuedExceptionsVariableName
+
end
describe 'messages with data and no text' do
it 'logs an arbitrary hash in a reasonable way' do
out = StringIO.new
@@ -272,7 +363,8 @@
BerkeleyLibrary::Logging.env = 'some-unsupported-environment'
expect { Loggers.new_default_logger(config) }.to raise_error(ArgumentError)
end
end
end
+
end
end