github.com/Finschia/finschia-sdk@v0.48.1/types/errors/abci_test.go (about)

     1  package errors
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/suite"
    10  )
    11  
    12  type abciTestSuite struct {
    13  	suite.Suite
    14  }
    15  
    16  func TestABCITestSuite(t *testing.T) {
    17  	suite.Run(t, new(abciTestSuite))
    18  }
    19  
    20  func (s *abciTestSuite) SetupSuite() {
    21  	s.T().Parallel()
    22  }
    23  
    24  func (s *abciTestSuite) TestABCInfo() {
    25  	cases := map[string]struct {
    26  		err       error
    27  		debug     bool
    28  		wantCode  uint32
    29  		wantSpace string
    30  		wantLog   string
    31  	}{
    32  		"plain SDK error": {
    33  			err:       ErrUnauthorized,
    34  			debug:     false,
    35  			wantLog:   "unauthorized",
    36  			wantCode:  ErrUnauthorized.code,
    37  			wantSpace: RootCodespace,
    38  		},
    39  		"wrapped SDK error": {
    40  			err:       Wrap(Wrap(ErrUnauthorized, "foo"), "bar"),
    41  			debug:     false,
    42  			wantLog:   "bar: foo: unauthorized",
    43  			wantCode:  ErrUnauthorized.code,
    44  			wantSpace: RootCodespace,
    45  		},
    46  		"nil is empty message": {
    47  			err:       nil,
    48  			debug:     false,
    49  			wantLog:   "",
    50  			wantCode:  0,
    51  			wantSpace: "",
    52  		},
    53  		"nil SDK error is not an error": {
    54  			err:       (*Error)(nil),
    55  			debug:     false,
    56  			wantLog:   "",
    57  			wantCode:  0,
    58  			wantSpace: "",
    59  		},
    60  		"stdlib returns error message in debug mode": {
    61  			err:       io.EOF,
    62  			debug:     true,
    63  			wantLog:   "EOF",
    64  			wantCode:  1,
    65  			wantSpace: UndefinedCodespace,
    66  		},
    67  		// This is hard to test because of attached stacktrace. This
    68  		// case is tested in an another test.
    69  		//"wrapped stdlib is a full message in debug mode": {
    70  		//	err:      Wrap(io.EOF, "cannot read file"),
    71  		//	debug:    true,
    72  		//	wantLog:  "cannot read file: EOF",
    73  		//	wantCode: 1,
    74  		//},
    75  		"custom error": {
    76  			err:       customErr{},
    77  			debug:     false,
    78  			wantLog:   "custom",
    79  			wantCode:  999,
    80  			wantSpace: "extern",
    81  		},
    82  		"custom error in debug mode": {
    83  			err:       customErr{},
    84  			debug:     true,
    85  			wantLog:   "custom",
    86  			wantCode:  999,
    87  			wantSpace: "extern",
    88  		},
    89  	}
    90  
    91  	for testName, tc := range cases {
    92  		s.T().Run(testName, func(t *testing.T) {
    93  			space, code, log := ABCIInfo(tc.err, tc.debug)
    94  			s.Require().Equal(tc.wantSpace, space, testName)
    95  			s.Require().Equal(tc.wantCode, code, testName)
    96  			s.Require().Equal(tc.wantLog, log, testName)
    97  		})
    98  	}
    99  }
   100  
   101  func (s *abciTestSuite) TestABCIInfoStacktrace() {
   102  	cases := map[string]struct {
   103  		err            error
   104  		debug          bool
   105  		wantStacktrace bool
   106  		wantErrMsg     string
   107  	}{
   108  		"wrapped SDK error in debug mode provides stacktrace": {
   109  			err:            Wrap(ErrUnauthorized, "wrapped"),
   110  			debug:          true,
   111  			wantStacktrace: true,
   112  			wantErrMsg:     "wrapped: unauthorized",
   113  		},
   114  		"wrapped SDK error in non-debug mode does not have stacktrace": {
   115  			err:            Wrap(ErrUnauthorized, "wrapped"),
   116  			debug:          false,
   117  			wantStacktrace: false,
   118  			wantErrMsg:     "wrapped: unauthorized",
   119  		},
   120  		"wrapped stdlib error in debug mode provides stacktrace": {
   121  			err:            Wrap(fmt.Errorf("stdlib"), "wrapped"),
   122  			debug:          true,
   123  			wantStacktrace: true,
   124  			wantErrMsg:     "wrapped: stdlib",
   125  		},
   126  	}
   127  
   128  	const thisTestSrc = "github.com/Finschia/finschia-sdk/types/errors.(*abciTestSuite).TestABCIInfoStacktrace"
   129  
   130  	for testName, tc := range cases {
   131  		s.T().Run(testName, func(t *testing.T) {
   132  			_, _, log := ABCIInfo(tc.err, tc.debug)
   133  			if !tc.wantStacktrace {
   134  				s.Require().Equal(tc.wantErrMsg, log, testName)
   135  			} else {
   136  				s.Require().True(strings.Contains(log, thisTestSrc), testName)
   137  				s.Require().True(strings.Contains(log, tc.wantErrMsg), testName)
   138  			}
   139  		})
   140  	}
   141  }
   142  
   143  func (s *abciTestSuite) TestABCIInfoHidesStacktrace() {
   144  	err := Wrap(ErrUnauthorized, "wrapped")
   145  	_, _, log := ABCIInfo(err, false)
   146  	s.Require().Equal("wrapped: unauthorized", log)
   147  }
   148  
   149  func (s *abciTestSuite) TestABCIInfoSerializeErr() {
   150  	var (
   151  		// Create errors with stacktrace for equal comparison.
   152  		myErrDecode = Wrap(ErrTxDecode, "test")
   153  		myErrAddr   = Wrap(ErrInvalidAddress, "tester")
   154  		myPanic     = ErrPanic
   155  	)
   156  
   157  	specs := map[string]struct {
   158  		src   error
   159  		debug bool
   160  		exp   string
   161  	}{
   162  		"single error": {
   163  			src:   myErrDecode,
   164  			debug: false,
   165  			exp:   "test: tx parse error",
   166  		},
   167  		"second error": {
   168  			src:   myErrAddr,
   169  			debug: false,
   170  			exp:   "tester: invalid address",
   171  		},
   172  		"single error with debug": {
   173  			src:   myErrDecode,
   174  			debug: true,
   175  			exp:   fmt.Sprintf("%+v", myErrDecode),
   176  		},
   177  		"do not redact in debug encoder": {
   178  			src:   myPanic,
   179  			debug: true,
   180  			exp:   fmt.Sprintf("%+v", myPanic),
   181  		},
   182  	}
   183  	for msg, spec := range specs {
   184  		spec := spec
   185  		_, _, log := ABCIInfo(spec.src, spec.debug)
   186  		s.Require().Equal(spec.exp, log, msg)
   187  	}
   188  }
   189  
   190  func (s *abciTestSuite) TestQueryResultWithDebug() {
   191  	q := QueryResultWithDebug(Wrap(errInternal, "test error"), true)
   192  	s.Require().Equal(q.Code, uint32(1))
   193  	s.Require().Equal(q.Codespace, "undefined")
   194  }
   195  
   196  // customErr is a custom implementation of an error that provides an ABCICode
   197  // method.
   198  type customErr struct{}
   199  
   200  func (customErr) Codespace() string { return "extern" }
   201  
   202  func (customErr) ABCICode() uint32 { return 999 }
   203  
   204  func (customErr) Error() string { return "custom" }