github.com/newrelic/go-agent@v3.26.0+incompatible/_integrations/nrpkgerrors/nrkpgerrors_test.go (about)

     1  // Copyright 2020 New Relic Corporation. All rights reserved.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package nrpkgerrors
     5  
     6  import (
     7  	"runtime"
     8  	"strings"
     9  	"testing"
    10  
    11  	newrelic "github.com/newrelic/go-agent"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  func topFrameFunction(stack []uintptr) string {
    16  	var frame runtime.Frame
    17  	frames := runtime.CallersFrames(stack)
    18  	if nil != frames {
    19  		frame, _ = frames.Next()
    20  	}
    21  	return frame.Function
    22  }
    23  
    24  type basicError struct{}
    25  
    26  func (e basicError) Error() string { return "something went wrong" }
    27  
    28  func alpha(e error) error { return errors.WithStack(e) }
    29  func beta(e error) error  { return errors.WithStack(e) }
    30  func gamma(e error) error { return errors.WithStack(e) }
    31  
    32  func theta(e error) error { return errors.WithMessage(e, "theta") }
    33  
    34  func TestWrappedStackTrace(t *testing.T) {
    35  	testcases := []struct {
    36  		Error          error
    37  		ExpectTopFrame string
    38  	}{
    39  		{Error: basicError{}, ExpectTopFrame: ""},
    40  		{Error: alpha(basicError{}), ExpectTopFrame: "alpha"},
    41  		{Error: alpha(beta(gamma(basicError{}))), ExpectTopFrame: "gamma"},
    42  		{Error: alpha(theta(basicError{})), ExpectTopFrame: "alpha"},
    43  		{Error: alpha(theta(beta(basicError{}))), ExpectTopFrame: "beta"},
    44  		{Error: alpha(theta(beta(theta(basicError{})))), ExpectTopFrame: "beta"},
    45  		{Error: theta(basicError{}), ExpectTopFrame: ""},
    46  	}
    47  
    48  	for idx, tc := range testcases {
    49  		e := Wrap(tc.Error)
    50  		st := e.(newrelic.StackTracer).StackTrace()
    51  		fn := topFrameFunction(st)
    52  		if !strings.Contains(fn, tc.ExpectTopFrame) {
    53  			t.Errorf("testcase %d: expected %s got %s",
    54  				idx, tc.ExpectTopFrame, fn)
    55  		}
    56  	}
    57  }
    58  
    59  type withClass struct{ class string }
    60  
    61  func errorWithClass(class string) error { return withClass{class: class} }
    62  
    63  func (e withClass) Error() string      { return "something went wrong" }
    64  func (e withClass) ErrorClass() string { return e.class }
    65  
    66  type classAndCause struct {
    67  	cause error
    68  	class string
    69  }
    70  
    71  func wrapWithClass(e error, class string) error { return classAndCause{cause: e, class: class} }
    72  
    73  func (e classAndCause) Error() string      { return e.cause.Error() }
    74  func (e classAndCause) Cause() error       { return e.cause }
    75  func (e classAndCause) ErrorClass() string { return e.class }
    76  
    77  func TestWrappedErrorClass(t *testing.T) {
    78  	// First choice is any ErrorClass of the immediate error.
    79  	// Second choice is any ErrorClass of the error's cause.
    80  	// Final choice is the reflect type of the error's cause.
    81  	testcases := []struct {
    82  		Error       error
    83  		ExpectClass string
    84  	}{
    85  		{Error: basicError{}, ExpectClass: "nrpkgerrors.basicError"},
    86  		{Error: errorWithClass("zap"), ExpectClass: "zap"},
    87  		{Error: wrapWithClass(errorWithClass("zap"), "zip"), ExpectClass: "zip"},
    88  		{Error: theta(wrapWithClass(errorWithClass("zap"), "zip")), ExpectClass: "zap"},
    89  		{Error: alpha(basicError{}), ExpectClass: "nrpkgerrors.basicError"},
    90  		{Error: wrapWithClass(basicError{}, "zip"), ExpectClass: "zip"},
    91  		{Error: alpha(wrapWithClass(basicError{}, "zip")), ExpectClass: "nrpkgerrors.basicError"},
    92  	}
    93  
    94  	for idx, tc := range testcases {
    95  		e := Wrap(tc.Error)
    96  		class := e.(newrelic.ErrorClasser).ErrorClass()
    97  		if class != tc.ExpectClass {
    98  			t.Errorf("testcase %d: expected %s got %s",
    99  				idx, tc.ExpectClass, class)
   100  		}
   101  	}
   102  }