2019-07-31 09:37:11 -07:00
package errors
import (
"fmt"
"io"
"strings"
"testing"
2020-03-04 09:49:59 -08:00
2020-10-08 04:42:32 -07:00
"github.com/stretchr/testify/suite"
2019-07-31 09:37:11 -07:00
)
2020-10-08 04:42:32 -07:00
type abciTestSuite struct {
suite . Suite
}
func TestABCITestSuite ( t * testing . T ) {
suite . Run ( t , new ( abciTestSuite ) )
}
func ( s * abciTestSuite ) SetupSuite ( ) {
s . T ( ) . Parallel ( )
}
func ( s * abciTestSuite ) TestABCInfo ( ) {
2019-07-31 09:37:11 -07:00
cases := map [ string ] struct {
err error
debug bool
wantCode uint32
wantSpace string
wantLog string
} {
2019-12-27 09:57:54 -08:00
"plain SDK error" : {
2019-07-31 09:37:11 -07:00
err : ErrUnauthorized ,
debug : false ,
wantLog : "unauthorized" ,
wantCode : ErrUnauthorized . code ,
wantSpace : RootCodespace ,
} ,
2019-12-27 09:57:54 -08:00
"wrapped SDK error" : {
2019-07-31 09:37:11 -07:00
err : Wrap ( Wrap ( ErrUnauthorized , "foo" ) , "bar" ) ,
debug : false ,
2020-03-27 16:19:44 -07:00
wantLog : "bar: foo: unauthorized" ,
2019-07-31 09:37:11 -07:00
wantCode : ErrUnauthorized . code ,
wantSpace : RootCodespace ,
} ,
"nil is empty message" : {
err : nil ,
debug : false ,
wantLog : "" ,
wantCode : 0 ,
wantSpace : "" ,
} ,
2019-12-27 09:57:54 -08:00
"nil SDK error is not an error" : {
2019-07-31 09:37:11 -07:00
err : ( * Error ) ( nil ) ,
debug : false ,
wantLog : "" ,
wantCode : 0 ,
wantSpace : "" ,
} ,
"stdlib is generic message" : {
err : io . EOF ,
debug : false ,
2020-07-05 09:56:17 -07:00
wantLog : "internal" ,
2019-07-31 09:37:11 -07:00
wantCode : 1 ,
wantSpace : UndefinedCodespace ,
} ,
"stdlib returns error message in debug mode" : {
err : io . EOF ,
debug : true ,
wantLog : "EOF" ,
wantCode : 1 ,
wantSpace : UndefinedCodespace ,
} ,
"wrapped stdlib is only a generic message" : {
err : Wrap ( io . EOF , "cannot read file" ) ,
debug : false ,
2020-07-05 09:56:17 -07:00
wantLog : "internal" ,
2019-07-31 09:37:11 -07:00
wantCode : 1 ,
wantSpace : UndefinedCodespace ,
} ,
// This is hard to test because of attached stacktrace. This
// case is tested in an another test.
//"wrapped stdlib is a full message in debug mode": {
// err: Wrap(io.EOF, "cannot read file"),
// debug: true,
// wantLog: "cannot read file: EOF",
// wantCode: 1,
//},
"custom error" : {
err : customErr { } ,
debug : false ,
wantLog : "custom" ,
wantCode : 999 ,
wantSpace : "extern" ,
} ,
"custom error in debug mode" : {
err : customErr { } ,
debug : true ,
wantLog : "custom" ,
wantCode : 999 ,
wantSpace : "extern" ,
} ,
}
for testName , tc := range cases {
2020-10-08 04:42:32 -07:00
space , code , log := ABCIInfo ( tc . err , tc . debug )
s . Require ( ) . Equal ( tc . wantSpace , space , testName )
s . Require ( ) . Equal ( tc . wantCode , code , testName )
s . Require ( ) . Equal ( tc . wantLog , log , testName )
2019-07-31 09:37:11 -07:00
}
}
2020-10-08 04:42:32 -07:00
func ( s * abciTestSuite ) TestABCIInfoStacktrace ( ) {
2019-07-31 09:37:11 -07:00
cases := map [ string ] struct {
err error
debug bool
wantStacktrace bool
wantErrMsg string
} {
2019-12-27 09:57:54 -08:00
"wrapped SDK error in debug mode provides stacktrace" : {
2019-07-31 09:37:11 -07:00
err : Wrap ( ErrUnauthorized , "wrapped" ) ,
debug : true ,
wantStacktrace : true ,
2020-03-27 16:19:44 -07:00
wantErrMsg : "wrapped: unauthorized" ,
2019-07-31 09:37:11 -07:00
} ,
2019-12-27 09:57:54 -08:00
"wrapped SDK error in non-debug mode does not have stacktrace" : {
2019-07-31 09:37:11 -07:00
err : Wrap ( ErrUnauthorized , "wrapped" ) ,
debug : false ,
wantStacktrace : false ,
2020-03-27 16:19:44 -07:00
wantErrMsg : "wrapped: unauthorized" ,
2019-07-31 09:37:11 -07:00
} ,
"wrapped stdlib error in debug mode provides stacktrace" : {
err : Wrap ( fmt . Errorf ( "stdlib" ) , "wrapped" ) ,
debug : true ,
wantStacktrace : true ,
2020-03-27 16:19:44 -07:00
wantErrMsg : "wrapped: stdlib" ,
2019-07-31 09:37:11 -07:00
} ,
"wrapped stdlib error in non-debug mode does not have stacktrace" : {
err : Wrap ( fmt . Errorf ( "stdlib" ) , "wrapped" ) ,
debug : false ,
wantStacktrace : false ,
2020-07-05 09:56:17 -07:00
wantErrMsg : "internal" ,
2019-07-31 09:37:11 -07:00
} ,
}
2020-10-08 04:42:32 -07:00
const thisTestSrc = "github.com/cosmos/cosmos-sdk/types/errors.(*abciTestSuite).TestABCIInfoStacktrace"
2019-07-31 09:37:11 -07:00
for testName , tc := range cases {
2020-10-08 04:42:32 -07:00
_ , _ , log := ABCIInfo ( tc . err , tc . debug )
if ! tc . wantStacktrace {
s . Require ( ) . Equal ( tc . wantErrMsg , log , testName )
continue
}
2019-07-31 09:37:11 -07:00
2020-10-08 04:42:32 -07:00
s . Require ( ) . True ( strings . Contains ( log , thisTestSrc ) , testName )
s . Require ( ) . True ( strings . Contains ( log , tc . wantErrMsg ) , testName )
2019-07-31 09:37:11 -07:00
}
}
2020-10-08 04:42:32 -07:00
func ( s * abciTestSuite ) TestABCIInfoHidesStacktrace ( ) {
2019-07-31 09:37:11 -07:00
err := Wrap ( ErrUnauthorized , "wrapped" )
_ , _ , log := ABCIInfo ( err , false )
2020-10-08 04:42:32 -07:00
s . Require ( ) . Equal ( "wrapped: unauthorized" , log )
2020-07-05 09:56:17 -07:00
}
2019-07-31 09:37:11 -07:00
2020-10-08 04:42:32 -07:00
func ( s * abciTestSuite ) TestRedact ( ) {
2020-07-05 09:56:17 -07:00
cases := map [ string ] struct {
err error
untouched bool // if true we expect the same error after redact
changed error // if untouched == false, expect this error
} {
"panic looses message" : {
err : Wrap ( ErrPanic , "some secret stack trace" ) ,
2020-11-30 08:59:35 -08:00
changed : errPanicWithMsg ,
2020-07-05 09:56:17 -07:00
} ,
"sdk errors untouched" : {
err : Wrap ( ErrUnauthorized , "cannot drop db" ) ,
untouched : true ,
} ,
"pass though custom errors with ABCI code" : {
err : customErr { } ,
untouched : true ,
} ,
"redact stdlib error" : {
err : fmt . Errorf ( "stdlib error" ) ,
changed : errInternal ,
} ,
2019-07-31 09:37:11 -07:00
}
2020-07-05 09:56:17 -07:00
for name , tc := range cases {
spec := tc
2020-10-08 04:42:32 -07:00
redacted := Redact ( spec . err )
if spec . untouched {
s . Require ( ) . Equal ( spec . err , redacted , name )
continue
}
// see if we got the expected redact
s . Require ( ) . Equal ( spec . changed , redacted , name )
// make sure the ABCI code did not change
s . Require ( ) . Equal ( abciCode ( spec . err ) , abciCode ( redacted ) , name )
2019-07-31 09:37:11 -07:00
}
}
2020-10-08 04:42:32 -07:00
func ( s * abciTestSuite ) TestABCIInfoSerializeErr ( ) {
2019-07-31 09:37:11 -07:00
var (
2019-08-15 06:54:10 -07:00
// Create errors with stacktrace for equal comparison.
2019-07-31 09:37:11 -07:00
myErrDecode = Wrap ( ErrTxDecode , "test" )
myErrAddr = Wrap ( ErrInvalidAddress , "tester" )
myPanic = ErrPanic
)
specs := map [ string ] struct {
src error
debug bool
exp string
} {
"single error" : {
src : myErrDecode ,
debug : false ,
2020-03-27 16:19:44 -07:00
exp : "test: tx parse error" ,
2019-07-31 09:37:11 -07:00
} ,
"second error" : {
src : myErrAddr ,
debug : false ,
2020-03-27 16:19:44 -07:00
exp : "tester: invalid address" ,
2019-07-31 09:37:11 -07:00
} ,
"single error with debug" : {
src : myErrDecode ,
debug : true ,
exp : fmt . Sprintf ( "%+v" , myErrDecode ) ,
} ,
"redact in default encoder" : {
src : myPanic ,
2022-05-06 06:58:48 -07:00
exp : "error message redacted to hide potential sensitive info. Use the '--trace' flag if you are running a node to see the full stack trace error: panic" ,
2019-07-31 09:37:11 -07:00
} ,
"do not redact in debug encoder" : {
src : myPanic ,
debug : true ,
exp : fmt . Sprintf ( "%+v" , myPanic ) ,
} ,
}
for msg , spec := range specs {
2019-10-17 06:47:35 -07:00
spec := spec
2020-10-08 04:42:32 -07:00
_ , _ , log := ABCIInfo ( spec . src , spec . debug )
s . Require ( ) . Equal ( spec . exp , log , msg )
2019-07-31 09:37:11 -07:00
}
}
// customErr is a custom implementation of an error that provides an ABCICode
// method.
type customErr struct { }
func ( customErr ) Codespace ( ) string { return "extern" }
func ( customErr ) ABCICode ( ) uint32 { return 999 }
func ( customErr ) Error ( ) string { return "custom" }