From b02ead2f56b1437e625ade5f6068a45d447978eb Mon Sep 17 00:00:00 2001 From: Sergey Zagursky Date: Thu, 7 Nov 2024 21:45:18 +0000 Subject: [PATCH] Respect TypeModifierOmitStackTrace in Builder Previous implementation of `WithCause` method didn't respect the `TypeModifierOmitStackTrace` modifier. A stack trace was erroneously collected if the error that was passed to `WithCause` didn't have stack trace. --- builder.go | 4 ++-- builder_test.go | 30 ++++++++++++++++++++++++++++++ error_test.go | 17 +++++++++-------- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/builder.go b/builder.go index 1cc7a25..060451c 100644 --- a/builder.go +++ b/builder.go @@ -33,12 +33,12 @@ func NewErrorBuilder(t *Type) ErrorBuilder { } // WithCause provides an original cause for error. -// For non-errorx errors, a stack trace is collected. +// For non-errorx errors, a stack trace is collected unless Type tells otherwise. // Otherwise, it is inherited by default, as error wrapping is typically performed 'en passe'. // Note that even if an original error explicitly omitted the stack trace, it could be added on wrap. func (eb ErrorBuilder) WithCause(err error) ErrorBuilder { eb.cause = err - if Cast(err) != nil { + if eb.errorType.modifiers.CollectStackTrace() && Cast(err) != nil { eb.mode = stackTraceBorrow } diff --git a/builder_test.go b/builder_test.go index d623bd3..51f158f 100644 --- a/builder_test.go +++ b/builder_test.go @@ -20,3 +20,33 @@ func TestBuilderTransparency(t *testing.T) { require.NotEqual(t, testType, err.Type()) }) } + +func TestBuilderRespectsNoStackTrace(t *testing.T) { + wrapperErrorTypes := []*Type{testTypeSilent, testTypeSilentTransparent} + + for _, et := range wrapperErrorTypes { + t.Run(et.String(), func(t *testing.T) { + t.Run("Naked", func(t *testing.T) { + err := NewErrorBuilder(et). + WithCause(errors.New("naked error")). + Create() + require.Nil(t, err.stackTrace) + }) + + t.Run("WithoutStacktrace", func(t *testing.T) { + err := NewErrorBuilder(et). + WithCause(testTypeSilent.NewWithNoMessage()). + Create() + require.Nil(t, err.stackTrace) + }) + + t.Run("WithStacktrace", func(t *testing.T) { + err := NewErrorBuilder(et). + WithCause(testType.NewWithNoMessage()). + Create() + require.Nil(t, err.stackTrace) + }) + }) + } + +} diff --git a/error_test.go b/error_test.go index a8f6262..406dc23 100644 --- a/error_test.go +++ b/error_test.go @@ -9,14 +9,15 @@ import ( ) var ( - testNamespace = NewNamespace("foo") - testType = testNamespace.NewType("bar") - testTypeSilent = testType.NewSubtype("silent").ApplyModifiers(TypeModifierOmitStackTrace) - testTypeTransparent = testType.NewSubtype("transparent").ApplyModifiers(TypeModifierTransparent) - testSubtype0 = testType.NewSubtype("internal") - testSubtype1 = testSubtype0.NewSubtype("wat") - testTypeBar1 = testNamespace.NewType("bar1") - testTypeBar2 = testNamespace.NewType("bar2") + testNamespace = NewNamespace("foo") + testType = testNamespace.NewType("bar") + testTypeSilent = testType.NewSubtype("silent").ApplyModifiers(TypeModifierOmitStackTrace) + testTypeTransparent = testType.NewSubtype("transparent").ApplyModifiers(TypeModifierTransparent) + testTypeSilentTransparent = testType.NewSubtype("silent_transparent").ApplyModifiers(TypeModifierTransparent, TypeModifierOmitStackTrace) + testSubtype0 = testType.NewSubtype("internal") + testSubtype1 = testSubtype0.NewSubtype("wat") + testTypeBar1 = testNamespace.NewType("bar1") + testTypeBar2 = testNamespace.NewType("bar2") ) func TestError(t *testing.T) {