diff --git a/error_test.go b/error_test.go index 64dab191c..4bfa370d2 100644 --- a/error_test.go +++ b/error_test.go @@ -95,3 +95,39 @@ func TestErrorsArraysHandleRichErrors(t *testing.T) { require.True(t, ok, "Expected serialized error to be a map, got %T.", serialized) assert.Equal(t, "egad", errMap["error"], "Unexpected standard error string.") } + +func TestErrArrayBrokenEncoder(t *testing.T) { + t.Parallel() + + failWith := errors.New("great sadness") + err := (brokenArrayObjectEncoder{ + Err: failWith, + ObjectEncoder: zapcore.NewMapObjectEncoder(), + }).AddArray("errors", errArray{ + errors.New("foo"), + errors.New("bar"), + }) + require.Error(t, err, "Expected error from broken encoder.") + assert.ErrorIs(t, err, failWith, "Unexpected error.") +} + +// brokenArrayObjectEncoder is an ObjectEncoder +// that builds a broken ArrayEncoder. +type brokenArrayObjectEncoder struct { + zapcore.ObjectEncoder + zapcore.ArrayEncoder + + Err error // error to return +} + +func (enc brokenArrayObjectEncoder) AddArray(key string, marshaler zapcore.ArrayMarshaler) error { + return enc.ObjectEncoder.AddArray(key, + zapcore.ArrayMarshalerFunc(func(ae zapcore.ArrayEncoder) error { + enc.ArrayEncoder = ae + return marshaler.MarshalLogArray(enc) + })) +} + +func (enc brokenArrayObjectEncoder) AppendObject(zapcore.ObjectMarshaler) error { + return enc.Err +} diff --git a/zapcore/error_test.go b/zapcore/error_test.go index d8263abc1..c5d61b040 100644 --- a/zapcore/error_test.go +++ b/zapcore/error_test.go @@ -29,6 +29,7 @@ import ( "github.com/stretchr/testify/assert" "go.uber.org/multierr" + "go.uber.org/zap/zapcore" . "go.uber.org/zap/zapcore" ) @@ -161,3 +162,49 @@ func TestRichErrorSupport(t *testing.T) { f.AddTo(enc) assert.Equal(t, "failed: egad", enc.Fields["k"], "Unexpected basic error message.") } + +func TestErrArrayBrokenEncoder(t *testing.T) { + t.Parallel() + + f := Field{ + Key: "foo", + Type: ErrorType, + Interface: multierr.Combine( + errors.New("foo"), + errors.New("bar"), + ), + } + + failWith := errors.New("great sadness") + enc := NewMapObjectEncoder() + f.AddTo(brokenArrayObjectEncoder{ + Err: failWith, + ObjectEncoder: enc, + }) + + // Failure to add the field to the encoder + // causes the error to be added as a string field. + assert.Equal(t, "great sadness", enc.Fields["fooError"], + "Unexpected error message.") +} + +// brokenArrayObjectEncoder is an ObjectEncoder +// that builds a broken ArrayEncoder. +type brokenArrayObjectEncoder struct { + ObjectEncoder + ArrayEncoder + + Err error // error to return +} + +func (enc brokenArrayObjectEncoder) AddArray(key string, marshaler ArrayMarshaler) error { + return enc.ObjectEncoder.AddArray(key, + ArrayMarshalerFunc(func(ae ArrayEncoder) error { + enc.ArrayEncoder = ae + return marshaler.MarshalLogArray(enc) + })) +} + +func (enc brokenArrayObjectEncoder) AppendObject(zapcore.ObjectMarshaler) error { + return enc.Err +}