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+)`)