diff --git a/errutil/utilities.go b/errutil/utilities.go index 2fd126d..78e4d20 100644 --- a/errutil/utilities.go +++ b/errutil/utilities.go @@ -15,6 +15,7 @@ package errutil import ( + "github.com/cockroachdb/errors/join" "github.com/cockroachdb/errors/secondary" "github.com/cockroachdb/errors/withstack" "github.com/cockroachdb/redact" @@ -158,3 +159,10 @@ func WrapWithDepthf(depth int, err error, format string, args ...interface{}) er err = withstack.WithStackDepth(err, depth+1) return err } + +// JoinWithDepth constructs a Join error with the provided list of +// errors as arguments, and wraps it in a `WithStackDepth` to capture a +// stacktrace alongside. +func JoinWithDepth(depth int, errs ...error) error { + return withstack.WithStackDepth(join.Join(errs...), depth+1) +} diff --git a/errutil_api.go b/errutil_api.go index 512bded..166eee1 100644 --- a/errutil_api.go +++ b/errutil_api.go @@ -192,3 +192,19 @@ func HandleAsAssertionFailureDepth(depth int, origErr error) error { // - it also supports recursing through causes with Cause(). // - if it detects an API use error, its panic object is a valid error. func As(err error, target interface{}) bool { return errutil.As(err, target) } + +// Join returns an error that wraps the given errors. +// Any nil error values are discarded. +// Join returns nil if errs contains no non-nil values. +// The error formats as the concatenation of the strings obtained +// by calling the Error method of each element of errs, with a newline +// between each string. A stack trace is also retained. +func Join(errs ...error) error { + return errutil.JoinWithDepth(1, errs...) +} + +// JoinWithDepth is like Join but the depth at which the call stack is +// captured can be specified. +func JoinWithDepth(depth int, errs ...error) error { + return errutil.JoinWithDepth(depth+1, errs...) +} diff --git a/errutil_api_test.go b/errutil_api_test.go index cd3fa34..a70c2b7 100644 --- a/errutil_api_test.go +++ b/errutil_api_test.go @@ -2,6 +2,7 @@ package errors_test import ( "fmt" + "strings" "testing" "github.com/cockroachdb/errors" @@ -17,3 +18,14 @@ func TestUnwrap(t *testing.T) { // (per API documentation) tt.Check(errors.Unwrap(e) == nil) } + +// More detailed testing of Join is in datadriven_test.go. Here we make +// sure that the public API includes the stacktrace wrapper. +func TestJoin(t *testing.T) { + e := errors.Join(errors.New("abc123"), errors.New("def456")) + printed := fmt.Sprintf("%+v", e) + expected := `Error types: (1) *withstack.withStack (2) *join.joinError (3) *withstack.withStack (4) *errutil.leafError (5) *withstack.withStack (6) *errutil.leafError` + if !strings.Contains(printed, expected) { + t.Errorf("Expected: %s to contain: %s", printed, expected) + } +} diff --git a/fmttests/datadriven_test.go b/fmttests/datadriven_test.go index c1eb9fa..f724ffe 100644 --- a/fmttests/datadriven_test.go +++ b/fmttests/datadriven_test.go @@ -37,6 +37,7 @@ import ( "github.com/cockroachdb/errors/errutil" "github.com/cockroachdb/errors/hintdetail" "github.com/cockroachdb/errors/issuelink" + "github.com/cockroachdb/errors/join" "github.com/cockroachdb/errors/report" "github.com/cockroachdb/errors/safedetails" "github.com/cockroachdb/errors/secondary" @@ -276,6 +277,9 @@ var wrapCommands = map[string]commandFn{ ctx = logtags.AddTag(ctx, "safe", redact.Safe(456)) return contexttags.WithContextTags(err, ctx) }, + "join": func(err error, args []arg) error { + return join.Join(err, errutil.New(strfy(args))) + }, } var noPrefixWrappers = map[string]bool{ @@ -300,6 +304,7 @@ var noPrefixWrappers = map[string]bool{ "stack": true, "tags": true, "telemetry": true, + "join": true, } var wrapOnlyExceptions = map[string]string{} @@ -329,6 +334,7 @@ func init() { // means they don't match. "nofmt", "errorf", + "join", } { wrapOnlyExceptions[v] = ` accept %\+v via Formattable.*IRREGULAR: not same as %\+v diff --git a/fmttests/testdata/format/wrap-fmt b/fmttests/testdata/format/wrap-fmt index 1625ad0..e02fa87 100644 --- a/fmttests/testdata/format/wrap-fmt +++ b/fmttests/testdata/format/wrap-fmt @@ -2251,6 +2251,197 @@ Type: "*fmttests.errFmt" Title: "×" (NO STACKTRACE) +run +fmt innerone innertwo +join outerthree outerfour + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s) +---- +&join.joinError{ + errs: { + &fmttests.errFmt{msg:"innerone\ninnertwo"}, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &fmttests.errFmt{msg:"innerone\ninnertwo"}, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +== Error() +innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +innerone +(1) innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) innerone + | innertwo + | -- this is innerone + | innertwo's + | multi-line leaf payload +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *fmttests.errFmt +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +‹innerone› +(1) ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) ‹innerone› +‹ | innertwo› +‹ | -- this is innerone› +‹ | innertwo's› +‹ | multi-line leaf payload› +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *fmttests.errFmt +===== +===== Sentry reporting +===== +== Message payload +× +(1) × + | × + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) × +× +× +× +× +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *fmttests.errFmt +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "×" +(NO STACKTRACE) + run fmt innerone innertwo migrated outerthree outerfour diff --git a/fmttests/testdata/format/wrap-fmt-via-network b/fmttests/testdata/format/wrap-fmt-via-network index 4ca1890..91ff2a1 100644 --- a/fmttests/testdata/format/wrap-fmt-via-network +++ b/fmttests/testdata/format/wrap-fmt-via-network @@ -2913,6 +2913,237 @@ Type: "*fmttests.errFmt" Title: "×" (NO STACKTRACE) +run +fmt innerone innertwo +join outerthree outerfour +opaque + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s)innerone.*innertwo +---- +&join.joinError{ + errs: { + &errbase.opaqueLeaf{ + msg: "innerone\ninnertwo", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/fmttests/*fmttests.errFmt", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errFmt", Extension:""}, + ReportablePayload: nil, + FullDetails: (*types.Any)(nil), + }, + }, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &errbase.opaqueLeaf{ + msg: "innerone\ninnertwo", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/fmttests/*fmttests.errFmt", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errFmt", Extension:""}, + ReportablePayload: nil, + FullDetails: (*types.Any)(nil), + }, + }, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +== Error() +innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +innerone +(1) innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) innerone + | innertwo + | + | (opaque error leaf) + | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueLeaf +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +‹innerone› +(1) ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) ‹innerone› + | ‹innertwo› + | + | (opaque error leaf) + | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueLeaf +===== +===== Sentry reporting +===== +== Message payload +× +(1) × + | × + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) × + | × + | + | (opaque error leaf) + | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errFmt +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueLeaf +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "×" +(NO STACKTRACE) + run fmt innerone innertwo migrated outerthree outerfour diff --git a/fmttests/testdata/format/wrap-goerr b/fmttests/testdata/format/wrap-goerr index 1e5fb5f..1380a7b 100644 --- a/fmttests/testdata/format/wrap-goerr +++ b/fmttests/testdata/format/wrap-goerr @@ -2052,6 +2052,188 @@ Type: "*errors.errorString" Title: "×" (NO STACKTRACE) +run +goerr innerone innertwo +join outerthree outerfour + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s) +---- +&join.joinError{ + errs: { + &errors.errorString{s:"innerone\ninnertwo"}, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &errors.errorString{s:"innerone\ninnertwo"}, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +== Error() +innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +innerone +(1) innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) innerone + | innertwo +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *errors.errorString +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +‹innerone› +(1) ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) ‹innerone› +‹ | innertwo› +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *errors.errorString +===== +===== Sentry reporting +===== +== Message payload +× +(1) × + | × + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) × +× +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *errors.errorString +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "×" +(NO STACKTRACE) + run goerr innerone innertwo migrated outerthree outerfour diff --git a/fmttests/testdata/format/wrap-goerr-via-network b/fmttests/testdata/format/wrap-goerr-via-network index 77c7cf6..c097698 100644 --- a/fmttests/testdata/format/wrap-goerr-via-network +++ b/fmttests/testdata/format/wrap-goerr-via-network @@ -2388,6 +2388,212 @@ Type: "*errors.errorString" Title: "×" (NO STACKTRACE) +run +goerr innerone innertwo +join outerthree outerfour +opaque + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s)innerone.*innertwo +---- +&join.joinError{ + errs: { + &errors.errorString{s:"innerone\ninnertwo"}, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &errors.errorString{s:"innerone\ninnertwo"}, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +== Error() +innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +innerone +(1) innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) innerone + | innertwo +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errors.errorString +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +‹innerone› +(1) ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) ‹innerone› +‹ | innertwo› +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errors.errorString +===== +===== Sentry reporting +===== +== Message payload +× +(1) × + | × + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) × +× +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errors.errorString +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "×" +(NO STACKTRACE) + run goerr innerone innertwo migrated outerthree outerfour diff --git a/fmttests/testdata/format/wrap-newf b/fmttests/testdata/format/wrap-newf index 0737c0f..6793c56 100644 --- a/fmttests/testdata/format/wrap-newf +++ b/fmttests/testdata/format/wrap-newf @@ -4272,6 +4272,209 @@ Title: "*errutil.leafError: new-style ×\nvia *withstack.withStack" :: (github.com/cockroachdb/errors/fmttests.glob.)...funcNN... +run +newf innerone innertwo +join outerthree outerfour + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s) +---- +&join.joinError{ + errs: { + &withstack.withStack{ + cause: &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"}, + stack: &stack{...}, + }, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &withstack.withStack{ + cause: &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"}, + stack: &stack{...}, + }, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +== Error() +new-style innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +new-style innerone +(1) new-style innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | [...repeated from below...] +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (5) new-style innerone + | innertwo +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *withstack.withStack (5) *errutil.leafError +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +new-style ‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +new-style ‹innerone› +(1) new-style ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | [...repeated from below...] +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (5) new-style ‹innerone› + | ‹innertwo› +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *withstack.withStack (5) *errutil.leafError +===== +===== Sentry reporting +===== +== Message payload +new-style × +(1) new-style × + | × + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | [...repeated from below...] +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (5) new-style × + | × +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *withstack.withStack (5) *errutil.leafError +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "new-style ×" +(NO STACKTRACE) + run newf innerone innertwo migrated outerthree outerfour diff --git a/fmttests/testdata/format/wrap-newf-via-network b/fmttests/testdata/format/wrap-newf-via-network index 4c2ef5d..4a1b87a 100644 --- a/fmttests/testdata/format/wrap-newf-via-network +++ b/fmttests/testdata/format/wrap-newf-via-network @@ -5035,6 +5035,319 @@ Title: "*errutil.leafError: new-style ×\nvia *withstack.withStack" :: (github.com/cockroachdb/errors/fmttests.glob.)...funcNN... +run +newf innerone innertwo +join outerthree outerfour +opaque + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s)innerone.*innertwo +---- +&join.joinError{ + errs: { + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"new-style ‹innerone›\n‹innertwo›"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +== Error() +new-style innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +new-style innerone +(1) new-style innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (5) new-style innerone + | innertwo +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueWrapper (5) *errutil.leafError +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +new-style ‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +new-style ‹innerone› +(1) new-style ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (5) new-style ‹innerone› + | ‹innertwo› +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueWrapper (5) *errutil.leafError +===== +===== Sentry reporting +===== +== Message payload +new-style × +(1) new-style × + | × + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (5) new-style × + | × +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueWrapper (5) *errutil.leafError +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "new-style ×" +(NO STACKTRACE) + run newf innerone innertwo migrated outerthree outerfour diff --git a/fmttests/testdata/format/wrap-nofmt b/fmttests/testdata/format/wrap-nofmt index 863af37..da0421b 100644 --- a/fmttests/testdata/format/wrap-nofmt +++ b/fmttests/testdata/format/wrap-nofmt @@ -2052,6 +2052,188 @@ Type: "*fmttests.errNoFmt" Title: "×" (NO STACKTRACE) +run +nofmt innerone innertwo +join outerthree outerfour + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s) +---- +&join.joinError{ + errs: { + &fmttests.errNoFmt{msg:"innerone\ninnertwo"}, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &fmttests.errNoFmt{msg:"innerone\ninnertwo"}, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +== Error() +innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +innerone +(1) innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) innerone + | innertwo +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *fmttests.errNoFmt +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +‹innerone› +(1) ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) ‹innerone› +‹ | innertwo› +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *fmttests.errNoFmt +===== +===== Sentry reporting +===== +== Message payload +× +(1) × + | × + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) × +× +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *fmttests.errNoFmt +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "×" +(NO STACKTRACE) + run nofmt innerone innertwo migrated outerthree outerfour diff --git a/fmttests/testdata/format/wrap-nofmt-via-network b/fmttests/testdata/format/wrap-nofmt-via-network index 6227508..9ffca03 100644 --- a/fmttests/testdata/format/wrap-nofmt-via-network +++ b/fmttests/testdata/format/wrap-nofmt-via-network @@ -2913,6 +2913,237 @@ Type: "*fmttests.errNoFmt" Title: "×" (NO STACKTRACE) +run +nofmt innerone innertwo +join outerthree outerfour +opaque + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s)innerone.*innertwo +---- +&join.joinError{ + errs: { + &errbase.opaqueLeaf{ + msg: "innerone\ninnertwo", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt", Extension:""}, + ReportablePayload: nil, + FullDetails: (*types.Any)(nil), + }, + }, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &errbase.opaqueLeaf{ + msg: "innerone\ninnertwo", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt", Extension:""}, + ReportablePayload: nil, + FullDetails: (*types.Any)(nil), + }, + }, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +== Error() +innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +innerone +(1) innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) innerone + | innertwo + | + | (opaque error leaf) + | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueLeaf +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +‹innerone› +(1) ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) ‹innerone› + | ‹innertwo› + | + | (opaque error leaf) + | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueLeaf +===== +===== Sentry reporting +===== +== Message payload +× +(1) × + | × + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) × + | × + | + | (opaque error leaf) + | type name: github.com/cockroachdb/errors/fmttests/*fmttests.errNoFmt +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueLeaf +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "×" +(NO STACKTRACE) + run nofmt innerone innertwo migrated outerthree outerfour diff --git a/fmttests/testdata/format/wrap-pkgerr b/fmttests/testdata/format/wrap-pkgerr index 9ca8b90..105e5fd 100644 --- a/fmttests/testdata/format/wrap-pkgerr +++ b/fmttests/testdata/format/wrap-pkgerr @@ -4118,6 +4118,203 @@ Title: "*errors.fundamental: ×" :: (github.com/cockroachdb/errors/fmttests.glob.)...funcNN... +run +pkgerr innerone innertwo +join outerthree outerfour + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s) +---- +&join.joinError{ + errs: { + &errors.fundamental{ + msg: "innerone\ninnertwo", + stack: &stack{...}, + }, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &errors.fundamental{ + msg: "innerone\ninnertwo", + stack: &stack{...}, + }, + &withstack.withStack{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + stack: &stack{...}, + }, + }, +} +== Error() +innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +innerone +(1) innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | [...repeated from below...] +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) innerone + | innertwo + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *errors.fundamental +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +‹innerone› +(1) ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | [...repeated from below...] +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) ‹innerone› +‹ | innertwo› +‹ | github.com/cockroachdb/errors/fmttests.glob..func9› +‹ | :› +‹ | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1› +‹ | :› +‹ | github.com/cockroachdb/datadriven.runDirective.func1› +‹ | :› +‹ | github.com/cockroachdb/datadriven.runDirective› +‹ | :› +‹ | github.com/cockroachdb/datadriven.runDirectiveOrSubTest› +‹ | :› +‹ | github.com/cockroachdb/datadriven.runTestInternal› +‹ | :› +‹ | github.com/cockroachdb/datadriven.RunTest› +‹ | :› +‹ | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2› +‹ | :› +‹ | github.com/cockroachdb/datadriven.Walk› +‹ | :› +‹ | github.com/cockroachdb/datadriven.Walk.func1› +‹ | :› +‹ | testing.tRunner› +‹ | :› +‹ | runtime.goexit› +‹ | :› +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *errors.fundamental +===== +===== Sentry reporting +===== +== Message payload +× +(1) × + | × + | outerthree + | outerfour +Wraps: (2) attached stack trace + -- stack trace: + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | [...repeated from below...] +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) × +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +× +Error types: (1) *join.joinError (2) *withstack.withStack (3) *errutil.leafError (4) *errors.fundamental +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "×" +(NO STACKTRACE) + run pkgerr innerone innertwo migrated outerthree outerfour diff --git a/fmttests/testdata/format/wrap-pkgerr-via-network b/fmttests/testdata/format/wrap-pkgerr-via-network index 7af01eb..5c9cfc1 100644 --- a/fmttests/testdata/format/wrap-pkgerr-via-network +++ b/fmttests/testdata/format/wrap-pkgerr-via-network @@ -4919,6 +4919,315 @@ Title: "*errors.fundamental: ×" :: (github.com/cockroachdb/errors/fmttests.glob.)...funcNN... +run +pkgerr innerone innertwo +join outerthree outerfour +opaque + +accept %\+v via Formattable.*IRREGULAR: not same as %\+v +accept %\#v via Formattable.*IRREGULAR: not same as %\#v + +require (?s)innerone.*innertwo +---- +&join.joinError{ + errs: { + &errbase.opaqueLeaf{ + msg: "innerone\ninnertwo", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/pkg/errors/*errors.fundamental", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/pkg/errors/*errors.fundamental", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + }, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +===== +===== non-redactable formats +===== +== %#v +&join.joinError{ + errs: { + &errbase.opaqueLeaf{ + msg: "innerone\ninnertwo", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/pkg/errors/*errors.fundamental", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/pkg/errors/*errors.fundamental", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + }, + &errbase.opaqueWrapper{ + cause: &errutil.leafError{msg:"outerthree\nouterfour"}, + prefix: "", + details: errorspb.EncodedErrorDetails{ + OriginalTypeName: "github.com/cockroachdb/errors/withstack/*withstack.withStack", + ErrorTypeMark: errorspb.ErrorTypeMark{FamilyName:"github.com/cockroachdb/errors/withstack/*withstack.withStack", Extension:""}, + ReportablePayload: {"\ngithub.com/cockroachdb/errors/fmttests.glob...funcNN...\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1\n\:\ngithub.com/cockroachdb/datadriven.runDirective.func1\n\:\ngithub.com/cockroachdb/datadriven.runDirective\n\:\ngithub.com/cockroachdb/datadriven.runDirectiveOrSubTest\n\:\ngithub.com/cockroachdb/datadriven.runTestInternal\n\:\ngithub.com/cockroachdb/datadriven.RunTest\n\:\ngithub.com/cockroachdb/errors/fmttests.TestDatadriven.func2\n\:\ngithub.com/cockroachdb/datadriven.Walk\n\:\ngithub.com/cockroachdb/datadriven.Walk.func1\n\:\ntesting.tRunner\n\:\nruntime.goexit\n\:"}, + FullDetails: (*types.Any)(nil), + }, + messageType: 0, + }, + }, +} +== Error() +innerone +innertwo +outerthree +outerfour +== %v = Error(), good +== %s = Error(), good +== %q = quoted Error(), good +== %x = hex Error(), good +== %X = HEX Error(), good +== %+v +innerone +(1) innerone + | innertwo + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) innerone + | innertwo + | + | (opaque error leaf) + | type name: github.com/pkg/errors/*errors.fundamental + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueLeaf +== %#v via Formattable() = %#v, good +== %v via Formattable() = Error(), good +== %s via Formattable() = %v via Formattable(), good +== %q via Formattable() = quoted %v via Formattable(), good +== %+v via Formattable() == %+v, good +===== +===== redactable formats +===== +== printed via redact Print(), ok - congruent with %v +‹innerone› +‹innertwo› +outerthree +outerfour +== printed via redact Printf() %v = Print(), good +== printed via redact Printf() %s = Print(), good +== printed via redact Printf() %q, refused - good +== printed via redact Printf() %x, refused - good +== printed via redact Printf() %X, refused - good +== printed via redact Printf() %+v, ok - congruent with %+v +‹innerone› +(1) ‹innerone› + | ‹innertwo› + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) ‹innerone› + | ‹innertwo› + | + | (opaque error leaf) + | type name: github.com/pkg/errors/*errors.fundamental + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueLeaf +===== +===== Sentry reporting +===== +== Message payload +× +(1) × + | × + | outerthree + | outerfour +Wraps: (2) + | (opaque error wrapper) + | type name: github.com/cockroachdb/errors/withstack/*withstack.withStack + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +└─ Wraps: (3) outerthree + | outerfour +Wraps: (4) × + | × + | + | (opaque error leaf) + | type name: github.com/pkg/errors/*errors.fundamental + | reportable 0: + | + | github.com/cockroachdb/errors/fmttests.glob...funcNN... + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2.1 + | : + | github.com/cockroachdb/datadriven.runDirective.func1 + | : + | github.com/cockroachdb/datadriven.runDirective + | : + | github.com/cockroachdb/datadriven.runDirectiveOrSubTest + | : + | github.com/cockroachdb/datadriven.runTestInternal + | : + | github.com/cockroachdb/datadriven.RunTest + | : + | github.com/cockroachdb/errors/fmttests.TestDatadriven.func2 + | : + | github.com/cockroachdb/datadriven.Walk + | : + | github.com/cockroachdb/datadriven.Walk.func1 + | : + | testing.tRunner + | : + | runtime.goexit + | : +Error types: (1) *join.joinError (2) *errbase.opaqueWrapper (3) *errutil.leafError (4) *errbase.opaqueLeaf +-- report composition: +*join.joinError +== Extra "error types" +github.com/cockroachdb/errors/join/*join.joinError (*::) +== Exception 1 (Module: "error domain: ") +Type: "*join.joinError" +Title: "×" +(NO STACKTRACE) + run pkgerr innerone innertwo migrated outerthree outerfour diff --git a/join/join.go b/join/join.go new file mode 100644 index 0000000..7ca5fcd --- /dev/null +++ b/join/join.go @@ -0,0 +1,105 @@ +// Copyright 2019 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package join + +import ( + "context" + "fmt" + + "github.com/cockroachdb/errors/errbase" + "github.com/cockroachdb/redact" + "github.com/gogo/protobuf/proto" +) + +// Join returns an error that wraps the given errors. +// Any nil error values are discarded. +// Join returns nil if errs contains no non-nil values. +// The error formats as the concatenation of the strings obtained +// by calling the Error method of each element of errs, with a newline +// between each string. +func Join(errs ...error) error { + n := 0 + for _, err := range errs { + if err != nil { + n++ + } + } + if n == 0 { + return nil + } + e := &joinError{ + errs: make([]error, 0, n), + } + for _, err := range errs { + if err != nil { + e.errs = append(e.errs, err) + } + } + return e +} + +type joinError struct { + errs []error +} + +var _ error = (*joinError)(nil) +var _ fmt.Formatter = (*joinError)(nil) +var _ errbase.SafeFormatter = (*joinError)(nil) + +func (e *joinError) Error() string { + return redact.Sprint(e).StripMarkers() +} + +func (e *joinError) Unwrap() []error { + return e.errs +} + +func (e *joinError) SafeFormatError(p errbase.Printer) error { + for i, err := range e.errs { + if i > 0 { + p.Print("\n") + } + p.Print(err) + } + return nil +} + +func (e *joinError) Format(s fmt.State, verb rune) { + errbase.FormatError(e, s, verb) +} + +func init() { + errbase.RegisterMultiCauseEncoder( + errbase.GetTypeKey(&joinError{}), + func( + ctx context.Context, + err error, + ) (msg string, safeDetails []string, payload proto.Message) { + return "", nil, nil + }, + ) + errbase.RegisterMultiCauseDecoder( + errbase.GetTypeKey(&joinError{}), + func( + ctx context.Context, + causes []error, + msgPrefix string, + safeDetails []string, + payload proto.Message, + ) error { + return Join(causes...) + }, + ) +} diff --git a/join/join_test.go b/join/join_test.go new file mode 100644 index 0000000..aaf4b70 --- /dev/null +++ b/join/join_test.go @@ -0,0 +1,57 @@ +// Copyright 2019 The Cockroach Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. + +package join + +import ( + "errors" + "testing" + + "github.com/cockroachdb/errors/safedetails" + "github.com/cockroachdb/redact" +) + +func TestJoin(t *testing.T) { + e := Join(errors.New("abc123"), errors.New("def456")) + expected := "abc123\ndef456" + if e.Error() != expected { + t.Errorf("Expected: %s; Got: %s", expected, e.Error()) + } + + e = Join(errors.New("abc123"), nil, errors.New("def456"), nil) + if e.Error() != expected { + t.Errorf("Expected: %s; Got: %s", expected, e.Error()) + } + + e = Join(nil, nil, nil) + if e != nil { + t.Errorf("expected nil error") + } + + e = Join( + errors.New("information"), + safedetails.WithSafeDetails(errors.New("detailed error"), "trace_id: %d", redact.Safe(1234)), + ) + printed := redact.Sprintf("%+v", e) + expectedR := redact.RedactableString(`‹information› +(1) ‹information› + | ‹detailed error› +Wraps: (2) trace_id: 1234 +└─ Wraps: (3) ‹detailed error› +Wraps: (4) ‹information› +Error types: (1) *join.joinError (2) *safedetails.withSafeDetails (3) *errors.errorString (4) *errors.errorString`) + if printed != expectedR { + t.Errorf("Expected: %s; Got: %s", expectedR, printed) + } +}