package errors import ( "errors" "fmt" "reflect" "strings" ) func (s *errorsTestSuite) TestStackTrace() { cases := map[string]struct { err error wantError string }{ "New gives us a stacktrace": { err: Wrap(ErrNoSignatures, "name"), wantError: "name: no signatures supplied", }, "Wrapping stderr gives us a stacktrace": { err: Wrap(fmt.Errorf("foo"), "standard"), wantError: "standard: foo", }, "Wrapping pkg/errors gives us clean stacktrace": { err: Wrap(errors.New("bar"), "pkg"), wantError: "pkg: bar", }, "Wrapping inside another function is still clean": { err: Wrap(fmt.Errorf("indirect"), "do the do"), wantError: "do the do: indirect", }, } // Wrapping code is unwanted in the errors stack trace. unwantedSrc := []string{ "github.com/cosmos/cosmos-sdk/types/errors.Wrap\n", "github.com/cosmos/cosmos-sdk/types/errors.Wrapf\n", "runtime.goexit\n", } const thisTestSrc = "types/errors/stacktrace_test.go" for _, tc := range cases { s.Require().True(reflect.DeepEqual(tc.err.Error(), tc.wantError)) s.Require().NotNil(stackTrace(tc.err)) fullStack := fmt.Sprintf("%+v", tc.err) s.Require().True(strings.Contains(fullStack, thisTestSrc)) s.Require().True(strings.Contains(fullStack, tc.wantError)) for _, src := range unwantedSrc { if strings.Contains(fullStack, src) { s.T().Logf("Stack trace below\n----%s\n----", fullStack) s.T().Logf("full stack contains unwanted source file path: %q", src) } } tinyStack := fmt.Sprintf("%v", tc.err) s.Require().True(strings.HasPrefix(tinyStack, tc.wantError)) s.Require().False(strings.Contains(tinyStack, "\n")) // contains a link to where it was created, which must // be here, not the Wrap() function s.Require().True(strings.Contains(tinyStack, thisTestSrc)) } }