github.com/cockroachdb/errors@v1.11.1/errbase/stack_format_test.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. See the License for the specific language governing 13 // permissions and limitations under the License. 14 15 package errbase_test 16 17 import ( 18 "fmt" 19 "regexp" 20 "strings" 21 "testing" 22 23 "github.com/cockroachdb/errors/errbase" 24 "github.com/cockroachdb/errors/testutils" 25 pkgErr "github.com/pkg/errors" 26 ) 27 28 func TestSimplifyStacks(t *testing.T) { 29 leaf := func() error { 30 return pkgErr.New("hello world") 31 } 32 wrapper := func() error { 33 err := leaf() 34 return pkgErr.WithStack(err) 35 } 36 errWrapper := wrapper() 37 t.Logf("error: %+v", errWrapper) 38 39 t.Run("low level API", func(t *testing.T) { 40 tt := testutils.T{t} 41 // Extract the stack trace from the leaf. 42 errLeaf := errbase.UnwrapOnce(errWrapper) 43 leafP, ok := errLeaf.(errbase.StackTraceProvider) 44 if !ok { 45 t.Fatal("leaf error does not provide stack trace") 46 } 47 leafT := leafP.StackTrace() 48 spv := fmtClean(leafT) 49 t.Logf("-- leaf trace --%+v", spv) 50 if !strings.Contains(spv, "TestSimplifyStacks") { 51 t.Fatalf("expected test function in trace, got:%v", spv) 52 } 53 leafLines := strings.Split(spv, "\n") 54 55 // Extract the stack trace from the wrapper. 56 wrapperP, ok := errWrapper.(errbase.StackTraceProvider) 57 if !ok { 58 t.Fatal("wrapper error does not provide stack trace") 59 } 60 wrapperT := wrapperP.StackTrace() 61 spv = fmtClean(wrapperT) 62 t.Logf("-- wrapper trace --%+v", spv) 63 wrapperLines := strings.Split(spv, "\n") 64 65 // Sanity check before we verify the result. 66 tt.Check(len(wrapperLines) > 0) 67 tt.CheckDeepEqual(wrapperLines[3:], leafLines[5:]) 68 69 // Elide the suffix and verify that we arrive to the same result. 70 simplified, hasElided := errbase.ElideSharedStackTraceSuffix(leafT, wrapperT) 71 spv = fmtClean(simplified) 72 t.Logf("-- simplified (%v) --%+v", hasElided, spv) 73 simplifiedLines := strings.Split(spv, "\n") 74 tt.CheckDeepEqual(simplifiedLines, wrapperLines[0:3]) 75 }) 76 77 t.Run("high level API", func(t *testing.T) { 78 tt := testutils.T{t} 79 80 spv := fmtClean(errbase.Formattable(errWrapper)) 81 tt.CheckStringEqual(spv, `hello world 82 (1) 83 -- stack trace: 84 | github.com/cockroachdb/errors/errbase_test.TestSimplifyStacks.func2 85 | <tab><path>:<lineno> 86 | [...repeated from below...] 87 Wraps: (2) hello world 88 | github.com/cockroachdb/errors/errbase_test.TestSimplifyStacks.func1 89 | <tab><path>:<lineno> 90 | github.com/cockroachdb/errors/errbase_test.TestSimplifyStacks.func2 91 | <tab><path>:<lineno> 92 | github.com/cockroachdb/errors/errbase_test.TestSimplifyStacks 93 | <tab><path>:<lineno> 94 | testing.tRunner 95 | <tab><path>:<lineno> 96 | runtime.goexit 97 | <tab><path>:<lineno> 98 Error types: (1) *errors.withStack (2) *errors.fundamental`) 99 }) 100 } 101 102 func fmtClean(x interface{}) string { 103 spv := fmt.Sprintf("%+v", x) 104 spv = fileref.ReplaceAllString(spv, "<path>:<lineno>") 105 spv = strings.ReplaceAll(spv, "\t", "<tab>") 106 return spv 107 } 108 109 var fileref = regexp.MustCompile(`([a-zA-Z0-9\._/@-]*\.(?:go|s):\d+)`)