From 73461ba9c169539a6e69e06a57f8508b602f3104 Mon Sep 17 00:00:00 2001 From: Keepers Date: Thu, 31 Oct 2024 13:15:20 -0600 Subject: [PATCH] merge err and errWC constructors back at the beginning of clues, I wanted errors and context to be completely separate missions. Ie: orgs could pick one or the other and be okay. So at the time I only added clues context with a builder: clues.New("err").WithClues(ctx). We ended up using that so much that I made some QoL funcs: clues.NewWC(ctx, "err"). That helped, but it has also produced a _lot_ of confusion about when it is correct to provide a ctx or not. For the longest time I've kept this current design because I didn't want to demand a context if the erroring function didn't already call for one. But the complaints about complexity and misunderstanding have a point. So I'm removing the *WC funcs and moving ctx into the regular error generators. Callers are allowed to provide a nil context if they don't have one. The goal here is simplification: don't ask developers to make decisions, just provide a context when you have one. --- err.go | 121 +++----------- err_benchmark_test.go | 76 ++++----- err_fmt_test.go | 159 +++++++----------- err_test.go | 371 +++++++++++++++++++++--------------------- 4 files changed, 299 insertions(+), 428 deletions(-) diff --git a/err.go b/err.go index 5159974..fc1cb43 100644 --- a/err.go +++ b/err.go @@ -641,35 +641,25 @@ func Unwrap(err error) error { // constructors // ------------------------------------------------------------ -// New creates an *Err with the provided Msg. -// -// If you have a `ctx` containing other clues data, it is recommended -// that you call `NewWC(ctx, msg)` to ensure that data gets added to -// the error. +// New creates an *Err with the provided Msg. Ctx can be nil. // // The returned *Err is an error-compliant builder that can aggregate // additional data using funcs like With(...) or Label(...). -func New(msg string) *Err { - return newErr(nil, msg, nil, 1) +func New(ctx context.Context, msg string) *Err { + return newErr(nil, msg, nil, 1).WithClues(ctx) } -// NewWC creates an *Err with the provided Msg, and additionally -// extracts all of the clues data in the context into the error. -// -// NewWC is equivalent to clues.New("msg").WithClues(ctx). -// -// The returned *Err is an error-compliant builder that can aggregate -// additional data using funcs like With(...) or Label(...). -func NewWC(ctx context.Context, msg string) *Err { - return newErr(nil, msg, nil, 1).WithClues(ctx) +// Sentinel creates an *Err with the provided Msg. This func is a +// shorthand for clues.New(nil, "msg").NoTrace(). It is purely a QoL +// helper for globally declared error variables, in case you want to +// minimize the extra chaff in your declarations. +func Sentinel(msg string) *Err { + return newErr(nil, msg, nil, 1) } // Wrap extends an error with the provided message. It is a replacement // for `errors.Wrap`, and complies with all golang unwrapping behavior. -// -// If you have a `ctx` containing other clues data, it is recommended -// that you call `WrapWC(ctx, err, msg)` to ensure that data gets added to -// the error. +// Ctx can be nil. // // The returned *Err is an error-compliant builder that can aggregate // additional data using funcs like With(...) or Label(...). There is @@ -680,33 +670,7 @@ func NewWC(ctx context.Context, msg string) *Err { // To avoid golang footguns when returning nil structs as interfaces // (such as error), callers should always return Wrap().OrNil() in cases // where the input error could be nil. -func Wrap(err error, msg string) *Err { - if isNilErrIface(err) { - return nil - } - - return newErr(err, msg, nil, 1) -} - -// WrapWC extends an error with the provided message. It is a replacement -// for `errors.Wrap`, and complies with all golang unwrapping behavior. -// -// WrapWC is equivalent to clues.Wrap(err, "msg").WithClues(ctx). -// -// If you have a `ctx` containing other clues data, it is recommended -// that you call `WrapWC(ctx, err, msg)` to ensure that data gets added to -// the error. -// -// The returned *Err is an error-compliant builder that can aggregate -// additional data using funcs like With(...) or Label(...). There is -// no WrapWCf func in clues; we prefer that callers use WrapWC().With() -// instead. -// -// Wrap can be given a `nil` error value, and will return a nil *Err. -// To avoid golang footguns when returning nil structs as interfaces -// (such as error), callers should always return WrapWC().OrNil() in cases -// where the input error could be nil. -func WrapWC(ctx context.Context, err error, msg string) *Err { +func Wrap(ctx context.Context, err error, msg string) *Err { if isNilErrIface(err) { return nil } @@ -717,7 +681,7 @@ func WrapWC(ctx context.Context, err error, msg string) *Err { // Stack composes a stack of one or more errors. The first message in the // parameters is considered the "most recent". Ex: a construction like // clues.Stack(errFoo, io.EOF, errSmarf), the resulting Error message would -// be "foo: end-of-file: smarf". +// be "foo: end-of-file: smarf". Ctx can be nil. // // Unwrapping a Stack follows the same order. This allows callers to inject // sentinel errors into error chains (ex: clues.Stack(io.EOF, myErr)) without @@ -738,37 +702,7 @@ func WrapWC(ctx context.Context, err error, msg string) *Err { // footguns when returning nil structs as interfaces (such as error), callers // should always return Stack().OrNil() in cases where the input error could // be nil. -func Stack(errs ...error) *Err { - return makeStack(1, errs...) -} - -// StackWC composes a stack of one or more errors. The first message in the -// parameters is considered the "most recent". Ex: a construction like -// clues.StackWC(errFoo, io.EOF, errSmarf), the resulting Error message would -// be "foo: end-of-file: smarf". -// -// Unwrapping a Stack follows the same order. This allows callers to inject -// sentinel errors into error chains (ex: clues.StackWC(io.EOF, myErr)) without -// losing errors.Is or errors.As checks on lower errors. -// -// If given a single error, Stack acts as a thin wrapper around the error to -// provide an *Err, giving the caller access to all the builder funcs and error -// tracing. It is always recommended that callers `return clues.StackWC(err)` -// instead of the plain `return err`. -// -// StackWC is equivalent to clues.Stack(errs...).WithClues(ctx) -// -// The returned *Err is an error-compliant builder that can aggregate -// additional data using funcs like With(...) or Label(...). -// -// Stack can be given one or more `nil` error values. Nil errors will be -// automatically filtered from the retained stack of errors. Ex: -// clues.StackWC(ctx, errFoo, nil, errSmarf) == clues.StackWC(ctx, errFoo, errSmarf). -// If all input errors are nil, stack will return nil. To avoid golang -// footguns when returning nil structs as interfaces (such as error), callers -// should always return StackWC().OrNil() in cases where the input error could -// be nil. -func StackWC(ctx context.Context, errs ...error) *Err { +func Stack(ctx context.Context, errs ...error) *Err { err := makeStack(1, errs...) if isNilErrIface(err) { @@ -780,7 +714,7 @@ func StackWC(ctx context.Context, errs ...error) *Err { // StackWrap is a quality-of-life shorthand for a common usage of clues errors: // clues.Stack(sentinel, clues.Wrap(myErr, "my message")). The result follows -// all standard behavior of stacked and wrapped errors. +// all standard behavior of stacked and wrapped errors. Ctx can be nil. // // The returned *Err is an error-compliant builder that can aggregate // additional data using funcs like With(...) or Label(...). @@ -792,25 +726,7 @@ func StackWC(ctx context.Context, errs ...error) *Err { // footguns when returning nil structs as interfaces (such as error), callers // should always return StackWrap().OrNil() in cases where the input errors // could be nil. -func StackWrap(sentinel, wrapped error, msg string) *Err { - return makeStackWrap(1, sentinel, wrapped, msg) -} - -// StackWrapWC is a quality-of-life shorthand for a common usage of clues errors: -// clues.Stack(sentinel, clues.Wrap(myErr, "my message")).WithClues(ctx). -// The result follows all standard behavior of stacked and wrapped errors. -// -// The returned *Err is an error-compliant builder that can aggregate -// additional data using funcs like With(...) or Label(...). -// -// StackWrapWC can be given one or more `nil` error values. Nil errors will be -// automatically filtered from the retained stack of errors. Ex: -// clues.StackWrapWC(ctx, errFoo, nil, "msg") == clues.WrapWC(ctx, errFoo, "msg"). -// If both input errors are nil, StackWrap will return nil. To avoid golang -// footguns when returning nil structs as interfaces (such as error), callers -// should always return StackWrap().OrNil() in cases where the input errors -// could be nil. -func StackWrapWC( +func StackWrap( ctx context.Context, sentinel, wrapped error, msg string, @@ -830,6 +746,9 @@ func StackWrapWC( // your wrapped or stacked error values could also possibly be // nil. // +// It's also often used for QoL removal of boilerplate error +// checks at the end of a function. +// // ie: // ``` // return clues.Stack(maybeNilErrValue).OrNil() @@ -864,6 +783,10 @@ func (err *Err) WithClues(ctx context.Context) *Err { return nil } + if ctx == nil { + return err + } + dn := In(ctx) e := err.WithMap(dn.Map()) e.data.labelCounter = dn.labelCounter diff --git a/err_benchmark_test.go b/err_benchmark_test.go index 1837e77..7cc9c2e 100644 --- a/err_benchmark_test.go +++ b/err_benchmark_test.go @@ -9,84 +9,84 @@ import ( ) func BenchmarkWith_singleConstKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With("foo", "bar") } } func BenchmarkWith_singleStaticKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(benchSize-i, i) } } func BenchmarkWith_singleConstKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With("foo", i) } } func BenchmarkWith_singleStaticKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(i, "bar") } } func BenchmarkWith_singleConstKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With("foo", benchVals[i%benchSize]) } } func BenchmarkWith_singleRandKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(benchVals[i%benchSize], "bar") } } func BenchmarkWith_singleRandKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(benchVals[i%benchSize], benchVals[i%benchSize]) } } func BenchmarkWith_multConstKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With("foo", "bar", "baz", "qux") } } func BenchmarkWith_multStaticKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(benchSize-i, i, i-benchSize, i) } } func BenchmarkWith_multConstKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With("foo", i, "baz", -i) } } func BenchmarkWith_multStaticKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(i, "bar", -i, "qux") } } func BenchmarkWith_multConstKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With( "foo", benchVals[i%benchSize], @@ -95,7 +95,7 @@ func BenchmarkWith_multConstKRandV(b *testing.B) { } func BenchmarkWith_multRandKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With( benchVals[i%benchSize], "bar", @@ -104,7 +104,7 @@ func BenchmarkWith_multRandKConstV(b *testing.B) { } func BenchmarkWith_multRandKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With( benchVals[i%benchSize], benchVals[i%benchSize], @@ -113,7 +113,7 @@ func BenchmarkWith_multRandKRandV(b *testing.B) { } func BenchmarkWith_chainConstKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With("foo", "bar"). With("baz", "qux") @@ -121,7 +121,7 @@ func BenchmarkWith_chainConstKConstV(b *testing.B) { } func BenchmarkWith_chainStaticKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(benchSize-i, i). With(i-benchSize, i) @@ -129,7 +129,7 @@ func BenchmarkWith_chainStaticKStaticV(b *testing.B) { } func BenchmarkWith_chainConstKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With("foo", i). With("baz", -i) @@ -137,7 +137,7 @@ func BenchmarkWith_chainConstKStaticV(b *testing.B) { } func BenchmarkWith_chainStaticKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(i, "bar"). With(-i, "qux") @@ -145,7 +145,7 @@ func BenchmarkWith_chainStaticKConstV(b *testing.B) { } func BenchmarkWith_chainConstKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With("foo", benchVals[i%benchSize]). With("baz", -benchVals[i%benchSize]) @@ -153,7 +153,7 @@ func BenchmarkWith_chainConstKRandV(b *testing.B) { } func BenchmarkWith_chainRandKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(benchVals[i%benchSize], "bar"). With(-benchVals[i%benchSize], "qux") @@ -161,7 +161,7 @@ func BenchmarkWith_chainRandKConstV(b *testing.B) { } func BenchmarkWith_chainRandKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { err = err.With(benchVals[i%benchSize], benchVals[i%benchSize]). With(-benchVals[i%benchSize], -benchVals[i%benchSize]) @@ -169,7 +169,7 @@ func BenchmarkWith_chainRandKRandV(b *testing.B) { } func BenchmarkWithMap_constKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { m := map[string]any{"foo": "bar", "baz": "qux"} err = err.WithMap(m) @@ -177,7 +177,7 @@ func BenchmarkWithMap_constKConstV(b *testing.B) { } func BenchmarkWithMap_staticKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { m := map[string]any{ strconv.Itoa(benchSize - i): i, @@ -188,7 +188,7 @@ func BenchmarkWithMap_staticKStaticV(b *testing.B) { } func BenchmarkWithMap_constKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { m := map[string]any{"foo": i, "baz": -i} err = err.WithMap(m) @@ -196,7 +196,7 @@ func BenchmarkWithMap_constKStaticV(b *testing.B) { } func BenchmarkWithMap_staticKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { m := map[string]any{ strconv.Itoa(i): "bar", @@ -207,7 +207,7 @@ func BenchmarkWithMap_staticKConstV(b *testing.B) { } func BenchmarkWithMap_constKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { m := map[string]any{ "foo": benchVals[i%benchSize], @@ -218,7 +218,7 @@ func BenchmarkWithMap_constKRandV(b *testing.B) { } func BenchmarkWithMap_randKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { m := map[string]any{ strconv.FormatInt(benchVals[i%benchSize], 10): "bar", @@ -229,7 +229,7 @@ func BenchmarkWithMap_randKConstV(b *testing.B) { } func BenchmarkWithMap_randKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") for i := 0; i < b.N; i++ { m := map[string]any{ strconv.FormatInt(benchVals[i%benchSize], 10): benchVals[i%benchSize], @@ -240,7 +240,7 @@ func BenchmarkWithMap_randKRandV(b *testing.B) { } func BenchmarkWithClues_constKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") ctx := context.Background() for i := 0; i < b.N; i++ { ctx = clues.Add(ctx, "foo", "bar") @@ -249,7 +249,7 @@ func BenchmarkWithClues_constKConstV(b *testing.B) { } func BenchmarkWithClues_staticKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") ctx := context.Background() for i := 0; i < b.N; i++ { ctx = clues.Add(ctx, benchSize-i, i) @@ -258,7 +258,7 @@ func BenchmarkWithClues_staticKStaticV(b *testing.B) { } func BenchmarkWithClues_constKStaticV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") ctx := context.Background() for i := 0; i < b.N; i++ { ctx = clues.Add(ctx, "foo", i) @@ -267,7 +267,7 @@ func BenchmarkWithClues_constKStaticV(b *testing.B) { } func BenchmarkWithClues_staticKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") ctx := context.Background() for i := 0; i < b.N; i++ { ctx = clues.Add(ctx, i, "bar") @@ -276,7 +276,7 @@ func BenchmarkWithClues_staticKConstV(b *testing.B) { } func BenchmarkWithClues_constKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") ctx := context.Background() for i := 0; i < b.N; i++ { ctx = clues.Add(ctx, "foo", benchVals[i%benchSize]) @@ -285,7 +285,7 @@ func BenchmarkWithClues_constKRandV(b *testing.B) { } func BenchmarkWithClues_randKConstV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") ctx := context.Background() for i := 0; i < b.N; i++ { ctx = clues.Add(ctx, benchVals[i%benchSize], "bar") @@ -294,7 +294,7 @@ func BenchmarkWithClues_randKConstV(b *testing.B) { } func BenchmarkWithClues_randKRandV(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") ctx := context.Background() for i := 0; i < b.N; i++ { ctx = clues.Add(ctx, benchVals[i%benchSize], benchVals[i%benchSize]) @@ -303,7 +303,7 @@ func BenchmarkWithClues_randKRandV(b *testing.B) { } func BenchmarkInErr_const(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") var m map[string]any for i := 0; i < b.N; i++ { err = err.With("foo", "bar") @@ -313,7 +313,7 @@ func BenchmarkInErr_const(b *testing.B) { } func BenchmarkInErr_static(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") var m map[string]any for i := 0; i < b.N; i++ { err = err.With(i, -i) @@ -323,7 +323,7 @@ func BenchmarkInErr_static(b *testing.B) { } func BenchmarkInErr_rand(b *testing.B) { - err := clues.New("err") + err := clues.New(nil, "err") var m map[string]any for i := 0; i < b.N; i++ { err = err.With(benchVals[i%benchSize], benchVals[i%benchSize]) diff --git a/err_fmt_test.go b/err_fmt_test.go index b82e360..fa85556 100644 --- a/err_fmt_test.go +++ b/err_fmt_test.go @@ -1,7 +1,6 @@ package clues_test import ( - "context" stderr "errors" "fmt" "regexp" @@ -88,11 +87,11 @@ var ( errStd = stderr.New("an error") errErrs = errors.New("an error") fmtErrf = fmt.Errorf("an error") - cluErr = clues.New("an error") + cluErr = clues.Sentinel("an error") - cluesWrap = func(err error) error { return clues.Wrap(err, "clues wrap") } - cluesPlainStack = func(err error) error { return clues.Stack(err) } - cluesStack = func(err error) error { return clues.Stack(globalSentinel, err) } + cluesWrap = func(err error) error { return clues.Wrap(nil, err, "clues wrap") } + cluesPlainStack = func(err error) error { return clues.Stack(nil, err) } + cluesStack = func(err error) error { return clues.Stack(nil, globalSentinel, err) } ) const cluesInitFileLoc = `(:\d+|.+/clues/.+go:?\d+)\n` @@ -674,12 +673,12 @@ func TestFmt(t *testing.T) { // --------------------------------------------------------------------------- { name: "multi-stack stderr.New", - onion: clues.Stack( - clues.Stack( + onion: clues.Stack(nil, + clues.Stack(nil, stderr.New("top"), stderr.New("mid"), ), - clues.Stack( + clues.Stack(nil, globalSentinel, stderr.New("bot"), ), @@ -706,12 +705,12 @@ func TestFmt(t *testing.T) { }, { name: "multi-stack errors.New", - onion: clues.Stack( - clues.Stack( + onion: clues.Stack(nil, + clues.Stack(nil, errors.New("top"), errors.New("mid"), ), - clues.Stack( + clues.Stack(nil, globalSentinel, errors.New("bot"), ), @@ -748,12 +747,12 @@ func TestFmt(t *testing.T) { }, { name: "multi-stack fmt.Errorf", - onion: clues.Stack( - clues.Stack( + onion: clues.Stack(nil, + clues.Stack(nil, fmt.Errorf("top"), fmt.Errorf("mid"), ), - clues.Stack( + clues.Stack(nil, globalSentinel, fmt.Errorf("bot"), ), @@ -780,14 +779,14 @@ func TestFmt(t *testing.T) { }, { name: "multi-stack clues.New", - onion: clues.Stack( - clues.Stack( - clues.New("top"), - clues.New("mid"), + onion: clues.Stack(nil, + clues.Stack(nil, + clues.New(nil, "top"), + clues.New(nil, "mid"), ), - clues.Stack( + clues.Stack(nil, globalSentinel, - clues.New("bot"), + clues.New(nil, "bot"), ), ), expect: expect{ @@ -816,12 +815,12 @@ func TestFmt(t *testing.T) { // --------------------------------------------------------------------------- { name: "wrapped multi-stack stderr.New", - onion: clues.Stack( - clues.Wrap(clues.Stack( + onion: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, stderr.New("top"), stderr.New("mid"), ), "lhs"), - clues.Wrap(clues.Stack( + clues.Wrap(nil, clues.Stack(nil, globalSentinel, stderr.New("bot"), ), "rhs"), @@ -850,12 +849,12 @@ func TestFmt(t *testing.T) { }, { name: "wrapped multi-stack errors.New", - onion: clues.Stack( - clues.Wrap(clues.Stack( + onion: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, errors.New("top"), errors.New("mid"), ), "lhs"), - clues.Wrap(clues.Stack( + clues.Wrap(nil, clues.Stack(nil, globalSentinel, errors.New("bot"), ), "rhs"), @@ -894,12 +893,12 @@ func TestFmt(t *testing.T) { }, { name: "wrapped multi-stack fmt.Errorf", - onion: clues.Stack( - clues.Wrap(clues.Stack( + onion: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, fmt.Errorf("top"), fmt.Errorf("mid"), ), "lhs"), - clues.Wrap(clues.Stack( + clues.Wrap(nil, clues.Stack(nil, globalSentinel, fmt.Errorf("bot"), ), "rhs"), @@ -928,14 +927,14 @@ func TestFmt(t *testing.T) { }, { name: "wrapped multi-stack clues.New", - onion: clues.Stack( - clues.Wrap(clues.Stack( - clues.New("top"), - clues.New("mid"), + onion: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, + clues.New(nil, "top"), + clues.New(nil, "mid"), ), "lhs"), - clues.Wrap(clues.Stack( + clues.Wrap(nil, clues.Stack(nil, globalSentinel, - clues.New("bot"), + clues.New(nil, "bot"), ), "rhs"), ), expect: expect{ @@ -982,43 +981,43 @@ func TestFmt(t *testing.T) { // wrapped func bottomWrap(err error) error { - return clues.Wrap(err, "bottom wrap") + return clues.Wrap(nil, err, "bottom wrap") } func midWrap(err error) error { - return clues.Wrap(bottomWrap(err), "mid wrap") + return clues.Wrap(nil, bottomWrap(err), "mid wrap") } func topWrap(err error) error { - return clues.Wrap(midWrap(err), "top wrap") + return clues.Wrap(nil, midWrap(err), "top wrap") } // plain-stacked func bottomPlainStack(err error) error { - return clues.Stack(err) + return clues.Stack(nil, err) } func midPlainStack(err error) error { - return clues.Stack(bottomPlainStack(err)) + return clues.Stack(nil, bottomPlainStack(err)) } func topPlainStack(err error) error { - return clues.Stack(midPlainStack(err)) + return clues.Stack(nil, midPlainStack(err)) } // stacked func bottomStack(err error) error { - return clues.Stack(clues.New("bottom"), err) + return clues.Stack(nil, clues.New(nil, "bottom"), err) } func midStack(err error) error { - return clues.Stack(clues.New("mid"), bottomStack(err)) + return clues.Stack(nil, clues.New(nil, "mid"), bottomStack(err)) } func topStack(err error) error { - return clues.Stack(clues.New("top"), midStack(err)) + return clues.Stack(nil, clues.New(nil, "top"), midStack(err)) } func TestFmt_nestedFuncs(t *testing.T) { @@ -1394,21 +1393,13 @@ func TestSkipCaller(t *testing.T) { checkFmt{"%+v", "", regexp.MustCompile(test.expect)}. check(t, test.tracer(cluErr)) }) - t.Run("wrapWC", func(t *testing.T) { - checkFmt{"%+v", "", regexp.MustCompile(test.expectWrapped)}. - check(t, clues.WrapWC(context.Background(), test.tracer(cluErr), "wrap")) - }) t.Run("wrap", func(t *testing.T) { checkFmt{"%+v", "", regexp.MustCompile(test.expectWrapped)}. - check(t, clues.Wrap(test.tracer(cluErr), "wrap")) - }) - t.Run("stackWC", func(t *testing.T) { - checkFmt{"%+v", "", regexp.MustCompile(test.expectStacked)}. - check(t, clues.StackWC(context.Background(), cluErr, test.tracer(cluErr))) + check(t, clues.Wrap(nil, test.tracer(cluErr), "wrap")) }) t.Run("stack", func(t *testing.T) { checkFmt{"%+v", "", regexp.MustCompile(test.expectStacked)}. - check(t, clues.Stack(cluErr, test.tracer(cluErr))) + check(t, clues.Stack(nil, cluErr, test.tracer(cluErr))) }) }) } @@ -1510,21 +1501,13 @@ func TestSkipCaller(t *testing.T) { checkFmt{"%+v", "", regexp.MustCompile(test.expect)}. check(t, test.tracer(cluErr)) }) - t.Run("wrapWC", func(t *testing.T) { - checkFmt{"%+v", "", regexp.MustCompile(test.expectWrapped)}. - check(t, clues.WrapWC(context.Background(), test.tracer(cluErr), "wrap")) - }) t.Run("wrap", func(t *testing.T) { checkFmt{"%+v", "", regexp.MustCompile(test.expectWrapped)}. - check(t, clues.Wrap(test.tracer(cluErr), "wrap")) - }) - t.Run("stackWC", func(t *testing.T) { - checkFmt{"%+v", "", regexp.MustCompile(test.expectStacked)}. - check(t, clues.StackWC(context.Background(), cluErr, test.tracer(cluErr))) + check(t, clues.Wrap(nil, test.tracer(cluErr), "wrap")) }) t.Run("stack", func(t *testing.T) { checkFmt{"%+v", "", regexp.MustCompile(test.expectStacked)}. - check(t, clues.Stack(cluErr, test.tracer(cluErr))) + check(t, clues.Stack(nil, cluErr, test.tracer(cluErr))) }) }) } @@ -1577,21 +1560,13 @@ func TestSkipCaller(t *testing.T) { checkFmt{"%+v", "", regexp.MustCompile(test.expect)}. check(t, test.tracer(err)) }) - t.Run("wrapWC", func(t *testing.T) { - checkFmt{"%+v", "", regexp.MustCompile(test.expectWrapped)}. - check(t, clues.WrapWC(context.Background(), test.tracer(err), "wrap")) - }) t.Run("wrap", func(t *testing.T) { checkFmt{"%+v", "", regexp.MustCompile(test.expectWrapped)}. - check(t, clues.Wrap(test.tracer(err), "wrap")) - }) - t.Run("stackWC", func(t *testing.T) { - checkFmt{"%+v", "", regexp.MustCompile(test.expectStacked)}. - check(t, clues.StackWC(context.Background(), err, test.tracer(err))) + check(t, clues.Wrap(nil, test.tracer(err), "wrap")) }) t.Run("stack", func(t *testing.T) { checkFmt{"%+v", "", regexp.MustCompile(test.expectStacked)}. - check(t, clues.Stack(err, test.tracer(err))) + check(t, clues.Stack(nil, err, test.tracer(err))) }) }) } @@ -1642,23 +1617,13 @@ func TestComment(t *testing.T) { comments := clues.Comments(test.commenter(cluErr)).String() commentMatches(t, test.expect, comments) }) - t.Run("wrapWC", func(t *testing.T) { - err := clues.WrapWC(context.Background(), test.commenter(cluErr), "wrap") - comments := clues.Comments(err).String() - commentMatches(t, test.expectWrapped, comments) - }) t.Run("wrap", func(t *testing.T) { - err := clues.Wrap(test.commenter(cluErr), "wrap") + err := clues.Wrap(nil, test.commenter(cluErr), "wrap") comments := clues.Comments(err).String() commentMatches(t, test.expectWrapped, comments) }) - t.Run("stackWC", func(t *testing.T) { - err := clues.StackWC(context.Background(), cluErr, test.commenter(cluErr)) - comments := clues.Comments(err).String() - commentMatches(t, test.expectStacked, comments) - }) t.Run("stack", func(t *testing.T) { - err := clues.Stack(cluErr, test.commenter(cluErr)) + err := clues.Stack(nil, cluErr, test.commenter(cluErr)) comments := clues.Comments(err).String() commentMatches(t, test.expectStacked, comments) }) @@ -1708,23 +1673,13 @@ func TestComment(t *testing.T) { comments := clues.Comments(test.commenter(cluErr)).String() commentMatches(t, test.expect, comments) }) - t.Run("wrapWC", func(t *testing.T) { - err := clues.WrapWC(context.Background(), test.commenter(cluErr), "wrap") - comments := clues.Comments(err).String() - commentMatches(t, test.expectWrapped, comments) - }) t.Run("wrap", func(t *testing.T) { - err := clues.Wrap(test.commenter(cluErr), "wrap") + err := clues.Wrap(nil, test.commenter(cluErr), "wrap") comments := clues.Comments(err).String() commentMatches(t, test.expectWrapped, comments) }) - t.Run("stackWC", func(t *testing.T) { - err := clues.StackWC(context.Background(), cluErr, test.commenter(cluErr)) - comments := clues.Comments(err).String() - commentMatches(t, test.expectStacked, comments) - }) t.Run("stack", func(t *testing.T) { - err := clues.Stack(cluErr, test.commenter(cluErr)) + err := clues.Stack(nil, nil, cluErr, test.commenter(cluErr)) comments := clues.Comments(err).String() commentMatches(t, test.expectStacked, comments) }) @@ -1749,7 +1704,7 @@ func TestErrCore_String(t *testing.T) { { name: "all values", core: clues. - New("message"). + New(nil, "message"). With("key", "value"). Label("label"). Core(), @@ -1760,7 +1715,7 @@ func TestErrCore_String(t *testing.T) { { name: "message only", core: clues. - New("message"). + New(nil, "message"). Core(), expectS: `{"message"}`, expectVPlus: `{msg:"message", labels:[], values:{}, comments:[]}`, @@ -1769,7 +1724,7 @@ func TestErrCore_String(t *testing.T) { { name: "labels only", core: clues. - New(""). + New(nil, ""). Label("label"). Core(), expectS: `{[label]}`, @@ -1779,7 +1734,7 @@ func TestErrCore_String(t *testing.T) { { name: "values only", core: clues. - New(""). + New(nil, ""). With("key", "value"). Core(), expectS: `{{key:value}}`, diff --git a/err_test.go b/err_test.go index 9a192d5..b26dfba 100644 --- a/err_test.go +++ b/err_test.go @@ -30,35 +30,35 @@ func TestStack(t *testing.T) { { name: "SingleNil", getErr: func() error { - return clues.Stack(nil).OrNil() + return clues.Stack(nil, nil).OrNil() }, expectNil: true, }, { name: "DoubleNil", getErr: func() error { - return clues.Stack(nil, nil).OrNil() + return clues.Stack(nil, nil, nil).OrNil() }, expectNil: true, }, { name: "TripleNil", getErr: func() error { - return clues.Stack(nil, nil, nil).OrNil() + return clues.Stack(nil, nil, nil, nil).OrNil() }, expectNil: true, }, { name: "StackNilNil", getErr: func() error { - return clues.Stack(clues.Stack(nil), nil).OrNil() + return clues.Stack(nil, nil, clues.Stack(nil, nil), nil).OrNil() }, expectNil: true, }, { name: "NilStackNilNil", getErr: func() error { - return clues.Stack(nil, clues.Stack(nil), nil).OrNil() + return clues.Stack(nil, nil, clues.Stack(nil, nil), nil).OrNil() }, expectNil: true, }, @@ -67,7 +67,7 @@ func TestStack(t *testing.T) { getErr: func() error { var e testingErrorIface - return clues.Stack(nil, e, clues.Stack(nil)).OrNil() + return clues.Stack(nil, e, clues.Stack(nil, nil)).OrNil() }, expectNil: true, }, @@ -76,7 +76,7 @@ func TestStack(t *testing.T) { getErr: func() error { var e testingErrorIface = testingError{} - return clues.Stack(nil, e, clues.Stack(nil)).OrNil() + return clues.Stack(nil, e, clues.Stack(nil, nil)).OrNil() }, expectNil: false, }, @@ -85,14 +85,14 @@ func TestStack(t *testing.T) { getErr: func() error { var e testingErrorIface = &testingError{} - return clues.Stack(nil, e, clues.Stack(nil)).OrNil() + return clues.Stack(nil, e, clues.Stack(nil, nil)).OrNil() }, expectNil: false, }, { name: "NonPointerError", getErr: func() error { - return clues.Stack(nil, testingError{}, clues.Stack(nil)).OrNil() + return clues.Stack(nil, testingError{}, clues.Stack(nil, nil)).OrNil() }, expectNil: false, }, @@ -120,19 +120,19 @@ func TestHasLabel(t *testing.T) { }{ { name: "multiple stacked clues errors with label on first", - initial: clues.Stack( - clues.New("Labeled").Label(label), - clues.New("NotLabeled")), + initial: clues.Stack(nil, + clues.New(nil, "Labeled").Label(label), + clues.New(nil, "NotLabeled")), }, { name: "multiple stacked clues errors with label on second", - initial: clues.Stack( - clues.New("NotLabeled"), - clues.New("Labeled").Label(label)), + initial: clues.Stack(nil, + clues.New(nil, "NotLabeled"), + clues.New(nil, "Labeled").Label(label)), }, { name: "single stacked clues error with label", - initial: clues.Stack(clues.New("Labeled").Label(label)), + initial: clues.Stack(nil, clues.New(nil, "Labeled").Label(label)), }, } @@ -156,11 +156,11 @@ func TestLabel(t *testing.T) { }{ {"nil", nil, nil}, {"standard error", errors.New("an error"), nil}, - {"clues error", clues.New("clues error"), nil}, - {"clues error wrapped", fmt.Errorf("%w", clues.New("clues error")), nil}, + {"clues error", clues.New(nil, "clues error"), nil}, + {"clues error wrapped", fmt.Errorf("%w", clues.New(nil, "clues error")), nil}, { "clues error with label", - clues.New("clues error").Label("fnords"), + clues.New(nil, "clues error").Label("fnords"), func(t *testing.T, err *clues.Err) { if !err.HasLabel("fnords") { t.Error("expected error to have label [fnords]") @@ -169,7 +169,7 @@ func TestLabel(t *testing.T) { }, { "clues error with label wrapped", - fmt.Errorf("%w", clues.New("clues error").Label("fnords")), + fmt.Errorf("%w", clues.New(nil, "clues error").Label("fnords")), func(t *testing.T, err *clues.Err) { if !err.HasLabel("fnords") { t.Error("expected error to have label [fnords]") @@ -211,11 +211,11 @@ func TestLabels(t *testing.T) { var ( ma = msa{"a": struct{}{}} mab = msa{"a": struct{}{}, "b": struct{}{}} - a = clues.New("a").Label("a") - acopy = clues.New("acopy").Label("a") - b = clues.New("b").Label("b") - wrap = clues.Wrap( - clues.Stack( + a = clues.New(nil, "a").Label("a") + acopy = clues.New(nil, "acopy").Label("a") + b = clues.New(nil, "b").Label("b") + wrap = clues.Wrap(nil, + clues.Stack(nil, fmt.Errorf("%w", a), fmt.Errorf("%w", b), fmt.Errorf("%w", acopy), @@ -229,12 +229,12 @@ func TestLabels(t *testing.T) { }{ {"nil", nil, msa{}}, {"standard error", errors.New("an error"), msa{}}, - {"unlabeled error", clues.New("clues error"), msa{}}, + {"unlabeled error", clues.New(nil, "clues error"), msa{}}, {"pkg/errs wrap around labeled error", errors.Wrap(a, "wa"), ma}, - {"clues wrapped", clues.Wrap(a, "wrap"), ma}, - {"clues stacked", clues.Stack(a, b), mab}, - {"clues stacked with copy", clues.Stack(a, b, acopy), mab}, - {"error chain", clues.Stack(b, fmt.Errorf("%w", a), fmt.Errorf("%w", acopy)), mab}, + {"clues wrapped", clues.Wrap(nil, a, "wrap"), ma}, + {"clues stacked", clues.Stack(nil, a, b), mab}, + {"clues stacked with copy", clues.Stack(nil, a, b, acopy), mab}, + {"error chain", clues.Stack(nil, b, fmt.Errorf("%w", a), fmt.Errorf("%w", acopy)), mab}, {"error wrap chain", wrap, mab}, } for _, test := range table { @@ -247,12 +247,12 @@ func TestLabels(t *testing.T) { var ( base = errors.New("an error") - cerr = func() error { return clues.Stack(base) } + cerr = func() error { return clues.Stack(nil, base) } werr = func() error { - return fmt.Errorf("%w", clues.Wrap(base, "wrapped error with vals").With("z", 0)) + return fmt.Errorf("%w", clues.Wrap(nil, base, "wrapped error with vals").With("z", 0)) } serr = func() error { - return clues.Stack(clues.New("primary").With("z", 0), errors.New("secondary")) + return clues.Stack(nil, clues.New(nil, "primary").With("z", 0), errors.New("secondary")) } ) @@ -394,9 +394,9 @@ func TestValuePriority(t *testing.T) { // the last addition to a ctx should take priority ctx = clues.Add(ctx, "in-ctx", 2) - err := clues.NewWC(ctx, "err").With("in-err", 1) + err := clues.New(ctx, "err").With("in-err", 1) // the first addition to an error should take priority - err = clues.StackWC(ctx, err).With("in-err", 2) + err = clues.Stack(ctx, err).With("in-err", 2) return err }(), @@ -406,9 +406,9 @@ func TestValuePriority(t *testing.T) { name: "last stack wins", err: func() error { ctx := clues.Add(context.Background(), "in-ctx", 1) - err := clues.NewWC(ctx, "last in stack").With("in-err", 1) - err = clues.Stack( - clues.New("first in stack").With("in-err", 2), + err := clues.New(ctx, "last in stack").With("in-err", 1) + err = clues.Stack(nil, + clues.New(nil, "first in stack").With("in-err", 2), err) return err }(), @@ -418,7 +418,7 @@ func TestValuePriority(t *testing.T) { name: ".With wins over ctx", err: func() error { ctx := clues.Add(context.Background(), "k", 1) - err := clues.NewWC(ctx, "last in stack").With("k", 2) + err := clues.New(ctx, "last in stack").With("k", 2) return err }(), expect: msa{"k": 2}, @@ -433,7 +433,7 @@ func TestValuePriority(t *testing.T) { func TestUnwrap(t *testing.T) { e := errors.New("cause") - we := clues.Wrap(e, "outer") + we := clues.Wrap(nil, e, "outer") ce := we.Unwrap() if ce != e { @@ -445,7 +445,7 @@ func TestUnwrap(t *testing.T) { t.Errorf("expected result error [%v] to be base error [%v]\n", ce, e) } - se := clues.Stack(e) + se := clues.Stack(nil, e) ce = se.Unwrap() if ce != e { @@ -466,9 +466,9 @@ func TestWrapNilStackSlice(t *testing.T) { // an empty slice of errors sl := make([]error, 10) // when stacked - st := clues.Stack(sl...) + st := clues.Stack(nil, sl...) // then wrapped - e := clues.Wrap(st, "wrapped") + e := clues.Wrap(nil, st, "wrapped") // should contain nil if e.OrNil() != nil { t.Errorf("e.OrNil() <%+v> should be nil", e.OrNil()) @@ -485,65 +485,65 @@ func TestErr_Error(t *testing.T) { }{ { name: "new error", - err: clues.New("new"), + err: clues.New(nil, "new"), expect: "new", }, { name: "stacked error", - err: clues.Stack(sentinel), + err: clues.Stack(nil, sentinel), expect: sentinel.Error(), }, { name: "wrapped new error", - err: clues.Wrap(clues.New("new"), "wrap"), + err: clues.Wrap(nil, clues.New(nil, "new"), "wrap"), expect: "wrap: new", }, { name: "wrapped non-clues error", - err: clues.Wrap(sentinel, "wrap"), + err: clues.Wrap(nil, sentinel, "wrap"), expect: "wrap: " + sentinel.Error(), }, { name: "wrapped stacked error", - err: clues.Wrap(clues.Stack(sentinel), "wrap"), + err: clues.Wrap(nil, clues.Stack(nil, sentinel), "wrap"), expect: "wrap: " + sentinel.Error(), }, { name: "multiple wraps", - err: clues.Wrap(clues.Wrap(clues.New("new"), "wrap"), "wrap2"), + err: clues.Wrap(nil, clues.Wrap(nil, clues.New(nil, "new"), "wrap"), "wrap2"), expect: "wrap2: wrap: new", }, { name: "wrap-stack-wrap-new", - err: clues.Wrap(clues.Stack(clues.Wrap(clues.New("new"), "wrap")), "wrap2"), + err: clues.Wrap(nil, clues.Stack(nil, clues.Wrap(nil, clues.New(nil, "new"), "wrap")), "wrap2"), expect: "wrap2: wrap: new", }, { name: "many stacked errors", - err: clues.Stack(sentinel, errors.New("middle"), errors.New("base")), + err: clues.Stack(nil, sentinel, errors.New("middle"), errors.New("base")), expect: sentinel.Error() + ": middle: base", }, { name: "stacked stacks", - err: clues.Stack( - clues.Stack(sentinel, errors.New("left")), - clues.Stack(errors.New("right"), errors.New("base")), + err: clues.Stack(nil, + clues.Stack(nil, sentinel, errors.New("left")), + clues.Stack(nil, errors.New("right"), errors.New("base")), ), expect: sentinel.Error() + ": left: right: base", }, { name: "wrapped stacks", - err: clues.Stack( - clues.Wrap(clues.Stack(errors.New("top"), errors.New("left")), "left-stack"), - clues.Wrap(clues.Stack(errors.New("right"), errors.New("base")), "right-stack"), + err: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, errors.New("top"), errors.New("left")), "left-stack"), + clues.Wrap(nil, clues.Stack(nil, errors.New("right"), errors.New("base")), "right-stack"), ), expect: "left-stack: top: left: right-stack: right: base", }, { name: "wrapped stacks, all clues.New", - err: clues.Stack( - clues.Wrap(clues.Stack(clues.New("top"), clues.New("left")), "left-stack"), - clues.Wrap(clues.Stack(clues.New("right"), clues.New("base")), "right-stack"), + err: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, clues.New(nil, "top"), clues.New(nil, "left")), "left-stack"), + clues.Wrap(nil, clues.Stack(nil, clues.New(nil, "right"), clues.New(nil, "base")), "right-stack"), ), expect: "left-stack: top: left: right-stack: right: base", }, @@ -566,45 +566,45 @@ func TestErrValues_stacks(t *testing.T) { }{ { name: "single err", - err: clues.Stack(clues.New("an err").With("k", "v")), + err: clues.Stack(nil, clues.New(nil, "an err").With("k", "v")), expect: msa{"k": "v"}, }, { name: "two stack", - err: clues.Stack( - clues.New("an err").With("k", "v"), - clues.New("other").With("k2", "v2"), + err: clues.Stack(nil, + clues.New(nil, "an err").With("k", "v"), + clues.New(nil, "other").With("k2", "v2"), ), expect: msa{"k": "v", "k2": "v2"}, }, { name: "sandvitch", - err: clues.Stack( - clues.New("top").With("k", "v"), + err: clues.Stack(nil, + clues.New(nil, "top").With("k", "v"), errors.New("mid"), - clues.New("base").With("k2", "v2"), + clues.New(nil, "base").With("k2", "v2"), ), expect: msa{"k": "v", "k2": "v2"}, }, { name: "value collision", - err: clues.Stack( - clues.New("top").With("k", "v"), - clues.New("mid").With("k2", "v2"), - clues.New("base").With("k", "v3"), + err: clues.Stack(nil, + clues.New(nil, "top").With("k", "v"), + clues.New(nil, "mid").With("k2", "v2"), + clues.New(nil, "base").With("k", "v3"), ), expect: msa{"k": "v3", "k2": "v2"}, }, { name: "double double", - err: clues.Stack( - clues.Stack( - clues.New("top").With("k", "v"), - clues.New("left").With("k2", "v2"), + err: clues.Stack(nil, + clues.Stack(nil, + clues.New(nil, "top").With("k", "v"), + clues.New(nil, "left").With("k2", "v2"), ), - clues.Stack( - clues.New("right").With("k3", "v3"), - clues.New("base").With("k4", "v4"), + clues.Stack(nil, + clues.New(nil, "right").With("k3", "v3"), + clues.New(nil, "base").With("k4", "v4"), ), ), expect: msa{ @@ -616,14 +616,14 @@ func TestErrValues_stacks(t *testing.T) { }, { name: "double double collision", - err: clues.Stack( - clues.Stack( - clues.New("top").With("k", "v"), - clues.New("left").With("k2", "v2"), + err: clues.Stack(nil, + clues.Stack(nil, + clues.New(nil, "top").With("k", "v"), + clues.New(nil, "left").With("k2", "v2"), ), - clues.Stack( - clues.New("right").With("k3", "v3"), - clues.New("base").With("k", "v4"), + clues.Stack(nil, + clues.New(nil, "right").With("k3", "v3"), + clues.New(nil, "base").With("k", "v4"), ), ), expect: msa{ @@ -634,17 +634,17 @@ func TestErrValues_stacks(t *testing.T) { }, { name: "double double animal wrap", - err: clues.Stack( - clues.Wrap( - clues.Stack( - clues.New("top").With("k", "v"), - clues.New("left").With("k2", "v2"), + err: clues.Stack(nil, + clues.Wrap(nil, + clues.Stack(nil, + clues.New(nil, "top").With("k", "v"), + clues.New(nil, "left").With("k2", "v2"), ), "left-stack"), - clues.Wrap( - clues.Stack( - clues.New("right").With("k3", "v3"), - clues.New("base").With("k4", "v4"), + clues.Wrap(nil, + clues.Stack(nil, + clues.New(nil, "right").With("k3", "v3"), + clues.New(nil, "base").With("k4", "v4"), ), "right-stack"), ), @@ -657,17 +657,17 @@ func TestErrValues_stacks(t *testing.T) { }, { name: "double double animal wrap collision", - err: clues.Stack( - clues.Wrap( - clues.Stack( - clues.New("top").With("k", "v"), - clues.New("left").With("k2", "v2"), + err: clues.Stack(nil, + clues.Wrap(nil, + clues.Stack(nil, + clues.New(nil, "top").With("k", "v"), + clues.New(nil, "left").With("k2", "v2"), ), "left-stack"), - clues.Wrap( - clues.Stack( - clues.New("right").With("k3", "v3"), - clues.New("base").With("k", "v4"), + clues.Wrap(nil, + clues.Stack(nil, + clues.New(nil, "right").With("k3", "v3"), + clues.New(nil, "base").With("k", "v4"), ), "right-stack"), ), @@ -687,7 +687,7 @@ func TestErrValues_stacks(t *testing.T) { } func TestImmutableErrors(t *testing.T) { - err := clues.New("an error").With("k", "v") + err := clues.New(nil, "an error").With("k", "v") check := msa{"k": "v"} pre := clues.InErr(err) mustEquals(t, check, pre.Map(), true) @@ -732,10 +732,10 @@ var ( target = mockTarget{errors.New(tgt)} sentinel = errors.New(stnl) other = errors.New("other") - leftTop = clues.New(lt).With(lt, "v"+lt).Label(lt) - leftBase = clues.New(lb).With(lb, "v"+lb).Label(lb) - rightTop = clues.New(rt).With(rt, "v"+rt).Label(rt) - rightBase = clues.New(rb).With(rb, "v"+rb).Label(rb) + leftTop = clues.New(nil, lt).With(lt, "v"+lt).Label(lt) + leftBase = clues.New(nil, lb).With(lb, "v"+lb).Label(lb) + rightTop = clues.New(nil, rt).With(rt, "v"+rt).Label(rt) + rightBase = clues.New(nil, rb).With(rb, "v"+rb).Label(rb) ) var testTable = []struct { @@ -747,79 +747,72 @@ var testTable = []struct { }{ { name: "plain stack", - err: clues.Stack(target, sentinel), + err: clues.Stack(nil, target, sentinel), expectMsg: "target: sentinel", expectLabels: msa{}, expectValues: msa{}, }, { name: "plain wrap", - err: clues.Wrap(clues.Stack(target, sentinel), "wrap"), + err: clues.Wrap(nil, clues.Stack(nil, target, sentinel), "wrap"), expectLabels: msa{}, expectMsg: "wrap: target: sentinel", expectValues: msa{}, }, { name: "two stack; top", - err: clues.Stack(clues.Stack(target, sentinel), other), + err: clues.Stack(nil, clues.Stack(nil, target, sentinel), other), expectMsg: "target: sentinel: other", expectLabels: msa{}, expectValues: msa{}, }, { name: "two stack; base", - err: clues.Stack(other, clues.Stack(target, sentinel)), + err: clues.Stack(nil, other, clues.Stack(nil, target, sentinel)), expectMsg: "other: target: sentinel", expectLabels: msa{}, expectValues: msa{}, }, { name: "two wrap", - err: clues.Wrap(clues.Wrap(clues.Stack(target, sentinel), "inner"), "outer"), + err: clues.Wrap(nil, clues.Wrap(nil, clues.Stack(nil, target, sentinel), "inner"), "outer"), expectMsg: "outer: inner: target: sentinel", expectLabels: msa{}, expectValues: msa{}, }, { name: "wrap stack", - err: clues.Wrap(clues.Stack(target, sentinel), "wrap"), + err: clues.Wrap(nil, clues.Stack(nil, target, sentinel), "wrap"), expectMsg: "wrap: target: sentinel", expectLabels: msa{}, expectValues: msa{}, }, { name: "stackwrap", - err: clues.StackWrap(target, sentinel, "wrap"), - expectMsg: "target: wrap: sentinel", - expectLabels: msa{}, - expectValues: msa{}, - }, - { - name: "stackwrapWC", - err: clues.StackWrapWC(context.Background(), target, sentinel, "wrap"), + err: clues.StackWrap(nil, target, sentinel, "wrap"), expectMsg: "target: wrap: sentinel", expectLabels: msa{}, expectValues: msa{}, }, { name: "wrap two stack: top", - err: clues.Wrap(clues.Stack(target, sentinel, other), "wrap"), + err: clues.Wrap(nil, clues.Stack(nil, target, sentinel, other), "wrap"), expectMsg: "wrap: target: sentinel: other", expectLabels: msa{}, expectValues: msa{}, }, { name: "wrap two stack: base", - err: clues.Wrap(clues.Stack(other, target, sentinel), "wrap"), + err: clues.Wrap(nil, clues.Stack(nil, other, target, sentinel), "wrap"), expectMsg: "wrap: other: target: sentinel", expectLabels: msa{}, expectValues: msa{}, }, { name: "double double stack; left top", - err: clues.Stack( - clues.Stack(target, sentinel, leftBase), - clues.Stack(rightTop, rightBase), + err: clues.Stack(nil, + clues.Stack(nil, target, sentinel, leftBase), + clues.Stack(nil, rightTop, rightBase), ), expectMsg: "target: sentinel: left-base: right-top: right-base", expectLabels: msa{ @@ -835,9 +828,9 @@ var testTable = []struct { }, { name: "double double stack; left base", - err: clues.Stack( - clues.Stack(leftTop, target, sentinel), - clues.Stack(rightTop, rightBase), + err: clues.Stack(nil, + clues.Stack(nil, leftTop, target, sentinel), + clues.Stack(nil, rightTop, rightBase), ), expectMsg: "left-top: target: sentinel: right-top: right-base", expectLabels: msa{ @@ -853,9 +846,9 @@ var testTable = []struct { }, { name: "double double stack; right top", - err: clues.Stack( - clues.Stack(leftTop, leftBase), - clues.Stack(target, sentinel, rightBase), + err: clues.Stack(nil, + clues.Stack(nil, leftTop, leftBase), + clues.Stack(nil, target, sentinel, rightBase), ), expectMsg: "left-top: left-base: target: sentinel: right-base", expectLabels: msa{ @@ -871,9 +864,9 @@ var testTable = []struct { }, { name: "double double animal wrap; right base", - err: clues.Stack( - clues.Wrap(clues.Stack(leftTop, leftBase), "left-stack"), - clues.Wrap(clues.Stack(rightTop, target, sentinel), "right-stack"), + err: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, leftTop, leftBase), "left-stack"), + clues.Wrap(nil, clues.Stack(nil, rightTop, target, sentinel), "right-stack"), ), expectMsg: "left-stack: left-top: left-base: right-stack: right-top: target: sentinel", expectLabels: msa{ @@ -889,9 +882,9 @@ var testTable = []struct { }, { name: "double double animal wrap; left top", - err: clues.Stack( - clues.Wrap(clues.Stack(target, sentinel, leftBase), "left-stack"), - clues.Wrap(clues.Stack(rightTop, rightBase), "right-stack"), + err: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, target, sentinel, leftBase), "left-stack"), + clues.Wrap(nil, clues.Stack(nil, rightTop, rightBase), "right-stack"), ), expectMsg: "left-stack: target: sentinel: left-base: right-stack: right-top: right-base", expectLabels: msa{ @@ -907,9 +900,9 @@ var testTable = []struct { }, { name: "double double animal wrap; left base", - err: clues.Stack( - clues.Wrap(clues.Stack(leftTop, target, sentinel), "left-stack"), - clues.Wrap(clues.Stack(rightTop, rightBase), "right-stack"), + err: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, leftTop, target, sentinel), "left-stack"), + clues.Wrap(nil, clues.Stack(nil, rightTop, rightBase), "right-stack"), ), expectMsg: "left-stack: left-top: target: sentinel: right-stack: right-top: right-base", expectLabels: msa{ @@ -925,9 +918,9 @@ var testTable = []struct { }, { name: "double double animal wrap; right top", - err: clues.Stack( - clues.Wrap(clues.Stack(leftTop, leftBase), "left-stack"), - clues.Wrap(clues.Stack(target, sentinel, rightBase), "right-stack"), + err: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, leftTop, leftBase), "left-stack"), + clues.Wrap(nil, clues.Stack(nil, target, sentinel, rightBase), "right-stack"), ), expectMsg: "left-stack: left-top: left-base: right-stack: target: sentinel: right-base", expectLabels: msa{ @@ -943,9 +936,9 @@ var testTable = []struct { }, { name: "double double animal wrap; right base", - err: clues.Stack( - clues.Wrap(clues.Stack(leftTop, leftBase), "left-stack"), - clues.Wrap(clues.Stack(rightTop, target, sentinel), "right-stack"), + err: clues.Stack(nil, + clues.Wrap(nil, clues.Stack(nil, leftTop, leftBase), "left-stack"), + clues.Wrap(nil, clues.Stack(nil, rightTop, target, sentinel), "right-stack"), ), expectMsg: "left-stack: left-top: left-base: right-stack: right-top: target: sentinel", expectLabels: msa{ @@ -970,7 +963,7 @@ func TestIs(t *testing.T) { }) } - notSentinel := clues.New("sentinel") + notSentinel := clues.New(nil, "sentinel") // NOT Is checks table := []struct { @@ -979,24 +972,24 @@ func TestIs(t *testing.T) { }{ { name: "plain stack", - err: clues.Stack(notSentinel), + err: clues.Stack(nil, notSentinel), }, { name: "plain wrap", - err: clues.Wrap(notSentinel, "wrap"), + err: clues.Wrap(nil, notSentinel, "wrap"), }, { name: "double double animal wrap", - err: clues.Stack( - clues.Wrap( - clues.Stack( - clues.New("left-top"), - clues.New("left-base"), + err: clues.Stack(nil, + clues.Wrap(nil, + clues.Stack(nil, + clues.New(nil, "left-top"), + clues.New(nil, "left-base"), ), "left-stack"), - clues.Wrap( - clues.Stack( - clues.New("right-top"), + clues.Wrap(nil, + clues.Stack(nil, + clues.New(nil, "right-top"), notSentinel, ), "right-stack"), @@ -1031,24 +1024,24 @@ func TestAs(t *testing.T) { }{ { name: "plain stack", - err: clues.Stack(notTarget), + err: clues.Stack(nil, notTarget), }, { name: "plain wrap", - err: clues.Wrap(notTarget, "wrap"), + err: clues.Wrap(nil, notTarget, "wrap"), }, { name: "double double animal wrap", - err: clues.Stack( - clues.Wrap( - clues.Stack( - clues.New("left-top"), - clues.New("left-base"), + err: clues.Stack(nil, + clues.Wrap(nil, + clues.Stack(nil, + clues.New(nil, "left-top"), + clues.New(nil, "left-base"), ), "left-stack"), - clues.Wrap( - clues.Stack( - clues.New("right-top"), + clues.Wrap(nil, + clues.Stack(nil, + clues.New(nil, "right-top"), notTarget, ), "right-stack"), @@ -1079,18 +1072,18 @@ func TestToCore(t *testing.T) { } func TestStackNils(t *testing.T) { - result := clues.Stack(nil) + result := clues.Stack(nil, nil) if result != nil { t.Errorf("expected nil, got [%v]", result) } - e := clues.New("err") - result = clues.Stack(e, nil) + e := clues.New(nil, "err") + result = clues.Stack(nil, e, nil) if result.Error() != e.Error() { t.Errorf("expected [%v], got [%v]", e, result) } - result = clues.Stack(nil, e) + result = clues.Stack(nil, nil, e) if result.Error() != e.Error() { t.Errorf("expected [%v], got [%v]", e, result) } @@ -1109,12 +1102,12 @@ func TestOrNil(t *testing.T) { }, { name: "nil stack", - err: clues.Stack(nil).With("foo", "bar"), + err: clues.Stack(nil, nil).With("foo", "bar"), expectNil: true, }, { name: "nil wrap", - err: clues.Wrap(nil, "msg").With("foo", "bar"), + err: clues.Wrap(nil, nil, "msg").With("foo", "bar"), expectNil: true, }, { @@ -1195,7 +1188,7 @@ func TestLabelCounter_iterative(t *testing.T) { var ( lc = labelCounter{} ctx = clues.AddLabelCounter(context.Background(), lc) - err = clues.NewWC(ctx, "an err") + err = clues.New(ctx, "an err") ) for _, l := range test.labels { @@ -1213,7 +1206,7 @@ func TestLabelCounter_variadic(t *testing.T) { var ( lc = labelCounter{} ctx = clues.AddLabelCounter(context.Background(), lc) - err = clues.NewWC(ctx, "an err") + err = clues.New(ctx, "an err") ) err.Label(test.labels...) @@ -1229,14 +1222,14 @@ func TestLabelCounter_iterative_stacked(t *testing.T) { var ( lc = labelCounter{} ctx = clues.AddLabelCounter(context.Background(), lc) - err = clues.NewWC(ctx, "an err") + err = clues.New(ctx, "an err") ) for _, l := range test.labels { err.Label(l) } - err = clues.Stack(err) + err = clues.Stack(nil, err) // duplicates on the wrapped error should not get counted for _, l := range test.labels { @@ -1254,13 +1247,13 @@ func TestLabelCounter_variadic_stacked(t *testing.T) { var ( lc = labelCounter{} ctx = clues.AddLabelCounter(context.Background(), lc) - err = clues.NewWC(ctx, "an err") + err = clues.New(ctx, "an err") ) err.Label(test.labels...) // duplicates on the wrapped error should not get counted - err = clues.Stack(err).Label(test.labels...) + err = clues.Stack(nil, err).Label(test.labels...) mustEquals(t, toMSA(test.expect), toMSA(lc), false) }) @@ -1273,14 +1266,14 @@ func TestLabelCounter_iterative_wrapped(t *testing.T) { var ( lc = labelCounter{} ctx = clues.AddLabelCounter(context.Background(), lc) - err = clues.NewWC(ctx, "an err") + err = clues.New(ctx, "an err") ) for _, l := range test.labels { err.Label(l) } - err = clues.Wrap(err, "wrap") + err = clues.Wrap(nil, err, "wrap") // duplicates on the wrapped error should not get counted for _, l := range test.labels { @@ -1298,13 +1291,13 @@ func TestLabelCounter_variadic_wrapped(t *testing.T) { var ( lc = labelCounter{} ctx = clues.AddLabelCounter(context.Background(), lc) - err = clues.NewWC(ctx, "an err") + err = clues.New(ctx, "an err") ) err.Label(test.labels...) // duplicates on the wrapped error should not get counted - err = clues.Wrap(err, "wrap").Label(test.labels...) + err = clues.Wrap(nil, err, "wrap").Label(test.labels...) mustEquals(t, toMSA(test.expect), toMSA(lc), false) }) @@ -1317,7 +1310,7 @@ func TestLabelCounter_iterative_noCluesInErr(t *testing.T) { var ( lc = labelCounter{} ctx = clues.AddLabelCounter(context.Background(), lc) - err = clues.New("an err") + err = clues.New(nil, "an err") ) for _, l := range test.labels { @@ -1338,7 +1331,7 @@ func TestLabelCounter_variadic_noCluesInErr(t *testing.T) { var ( lc = labelCounter{} ctx = clues.AddLabelCounter(context.Background(), lc) - err = clues.New("an err") + err = clues.New(nil, "an err") ) err.Label(test.labels...).WithClues(ctx) @@ -1362,11 +1355,11 @@ func cluesWithSkipCaller(err *clues.Err, depth int) error { } func wrapWithFuncWithGeneric[E error](err E) *clues.Err { - return clues.Wrap(err, "with-generic") + return clues.Wrap(nil, err, "with-generic") } func withNoTrace(err error) *clues.Err { - return clues.Wrap(err, "no-trace").NoTrace() + return clues.Wrap(nil, err, "no-trace").NoTrace() } func withCommentWrapper(