From 4ac087ab63b2433275c35471b6b80f91a19187f4 Mon Sep 17 00:00:00 2001 From: mossid Date: Sat, 5 Jan 2019 09:19:30 +0100 Subject: [PATCH 1/7] invert dependency --- store/iavl/store.go | 5 +- store/iavl/store_test.go | 2 +- store/rootmulti/proof_test.go | 3 +- store/rootmulti/store.go | 2 +- store/rootmulti/store_test.go | 9 +- store/types/errors.go | 154 ++++++++++++++++++++++++++++++++++ 6 files changed, 163 insertions(+), 12 deletions(-) create mode 100644 store/types/errors.go diff --git a/store/iavl/store.go b/store/iavl/store.go index 29e375b55f65..1b52bb6c64e6 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -11,8 +11,7 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" - stypes "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/store/cachekv" "github.com/cosmos/cosmos-sdk/store/tracekv" @@ -236,7 +235,7 @@ func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) { subspace := req.Data res.Key = subspace - iterator := stypes.KVStorePrefixIterator(st, subspace) + iterator := types.KVStorePrefixIterator(st, subspace) for ; iterator.Valid(); iterator.Next() { KVs = append(KVs, types.KVPair{Key: iterator.Key(), Value: iterator.Value()}) } diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index 360fa712cd93..6149ee241ce1 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -11,7 +11,7 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) var ( diff --git a/store/rootmulti/proof_test.go b/store/rootmulti/proof_test.go index 885d0ddb4eb4..4ecebaa5b927 100644 --- a/store/rootmulti/proof_test.go +++ b/store/rootmulti/proof_test.go @@ -3,13 +3,12 @@ package rootmulti import ( "testing" - "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" dbm "github.com/tendermint/tendermint/libs/db" "github.com/cosmos/cosmos-sdk/store/iavl" - stypes "github.com/cosmos/cosmos-sdk/store/types" + "github.com/cosmos/cosmos-sdk/store/types" ) func TestVerifyIAVLStoreQueryProof(t *testing.T) { diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index 8be98a1d8c52..dec2d32aadb3 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -15,7 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/iavl" "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/transient" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) const ( diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index 75aed91b6c4b..ac4fc6a313ac 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -8,8 +8,7 @@ import ( "github.com/tendermint/tendermint/crypto/merkle" dbm "github.com/tendermint/tendermint/libs/db" - stypes "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/store/types" ) const useDebugDB = false @@ -158,18 +157,18 @@ func TestMultiStoreQuery(t *testing.T) { query := abci.RequestQuery{Path: "/key", Data: k, Height: ver} qres := multi.Query(query) require.EqualValues(t, types.CodeUnknownRequest, qres.Code) - require.EqualValues(t, types.CodespaceRoot, qres.Codespace) + require.EqualValues(t, types.CodespaceQuery, qres.Codespace) query.Path = "h897fy32890rf63296r92" qres = multi.Query(query) require.EqualValues(t, types.CodeUnknownRequest, qres.Code) - require.EqualValues(t, types.CodespaceRoot, qres.Codespace) + require.EqualValues(t, types.CodespaceQuery, qres.Codespace) // Test invalid store name. query.Path = "/garbage/key" qres = multi.Query(query) require.EqualValues(t, types.CodeUnknownRequest, qres.Code) - require.EqualValues(t, types.CodespaceRoot, qres.Codespace) + require.EqualValues(t, types.CodespaceQuery, qres.Codespace) // Test valid query with data. query.Path = "/store1/key" diff --git a/store/types/errors.go b/store/types/errors.go new file mode 100644 index 000000000000..c6471c7bdc4a --- /dev/null +++ b/store/types/errors.go @@ -0,0 +1,154 @@ +package types + +import ( + "fmt" + + cmn "github.com/tendermint/tendermint/libs/common" + + "github.com/cosmos/cosmos-sdk/codec" + + abci "github.com/tendermint/tendermint/abci/types" +) + +// CodeType - ABCI code identifier within codespace +type CodeType uint32 + +// CodespaceType - codespace identifier +type CodespaceType string + +// IsOK - is everything okay? +func (code CodeType) IsOK() bool { + if code == CodeOK { + return true + } + return false +} + +// SDK error codes +const ( + // Base error codes + CodeOK CodeType = 0 + CodeInternal CodeType = 1 + CodeTxDecode CodeType = 2 + CodeUnknownRequest CodeType = 6 + + // CodespaceQuery is a codespace for error codes in this file only. + CodespaceQuery CodespaceType = "query" +) + +func unknownCodeMsg(code CodeType) string { + return fmt.Sprintf("unknown code %d", code) +} + +// NOTE: Don't stringer this, we'll put better messages in later. +func CodeToDefaultMsg(code CodeType) string { + switch code { + case CodeInternal: + return "internal error" + case CodeTxDecode: + return "tx parse error" + case CodeUnknownRequest: + return "unknown request" + default: + return unknownCodeMsg(code) + } +} + +//-------------------------------------------------------------------------------- +// All errors are created via constructors so as to enable us to hijack them +// and inject stack traces if we really want to. + +// nolint +func ErrInternal(msg string) Error { + return newQueryError(CodeInternal, msg) +} +func ErrTxDecode(msg string) Error { + return newQueryError(CodeTxDecode, msg) +} +func ErrUnknownRequest(msg string) Error { + return newQueryError(CodeUnknownRequest, msg) +} + +//---------------------------------------- +// Error & queryError + +type cmnError = cmn.Error + +// sdk Error type +type Error interface { + // Implements cmn.Error + // Error() string + // Stacktrace() cmn.Error + // Trace(offset int, format string, args ...interface{}) cmn.Error + // Data() interface{} + cmnError + + Code() CodeType + ABCILog() string + QueryResult() abci.ResponseQuery +} + +func newQueryError(code CodeType, format string, args ...interface{}) *queryError { + if format == "" { + format = CodeToDefaultMsg(code) + } + return &queryError{ + code: code, + cmnError: cmn.NewError(format, args...), + } +} + +type queryError struct { + code CodeType + cmnError +} + +// Implements ABCIError. +func (err *queryError) Error() string { + return fmt.Sprintf(`ERROR: +Codespace: %s +Code: %d +Message: %#v +`, CodespaceQuery, err.code, err.cmnError.Error()) +} + +// Implements Error. +func (err *queryError) Code() CodeType { + return err.code +} + +// Implements ABCIError. +func (err *queryError) ABCILog() string { + cdc := codec.New() + errMsg := err.cmnError.Error() + jsonErr := humanReadableError{ + Codespace: CodespaceQuery, + Code: err.code, + Message: errMsg, + } + bz, er := cdc.MarshalJSON(jsonErr) + if er != nil { + panic(er) + } + stringifiedJSON := string(bz) + return stringifiedJSON +} + +// QueryResult allows us to return sdk.Error.QueryResult() in query responses +func (err *queryError) QueryResult() abci.ResponseQuery { + return abci.ResponseQuery{ + Code: uint32(err.Code()), + Codespace: string(CodespaceQuery), + Log: err.ABCILog(), + } +} + +//---------------------------------------- +// REST error utilities + +// parses the error into an object-like struct for exporting +type humanReadableError struct { + Codespace CodespaceType `json:"codespace"` + Code CodeType `json:"code"` + Message string `json:"message"` +} From 54e82df1696790c5e3bc73ea6e0df11a663865b5 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 25 Jan 2019 13:42:08 +0100 Subject: [PATCH 2/7] rm /types import --- store/iavl/store.go | 7 +++---- store/rootmulti/proof_test.go | 2 +- store/rootmulti/store_test.go | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/store/iavl/store.go b/store/iavl/store.go index 1b52bb6c64e6..da282149fc00 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -11,10 +11,9 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" - "github.com/cosmos/cosmos-sdk/store/types" - "github.com/cosmos/cosmos-sdk/store/cachekv" "github.com/cosmos/cosmos-sdk/store/tracekv" + "github.com/cosmos/cosmos-sdk/store/types" ) const ( @@ -290,8 +289,8 @@ var _ types.Iterator = (*iavlIterator)(nil) func newIAVLIterator(tree *iavl.ImmutableTree, start, end []byte, ascending bool) *iavlIterator { iter := &iavlIterator{ tree: tree, - start: stypes.Cp(start), - end: stypes.Cp(end), + start: types.Cp(start), + end: types.Cp(end), ascending: ascending, iterCh: make(chan cmn.KVPair, 0), // Set capacity > 0? quitCh: make(chan struct{}), diff --git a/store/rootmulti/proof_test.go b/store/rootmulti/proof_test.go index 4ecebaa5b927..5498fba1ce0e 100644 --- a/store/rootmulti/proof_test.go +++ b/store/rootmulti/proof_test.go @@ -14,7 +14,7 @@ import ( func TestVerifyIAVLStoreQueryProof(t *testing.T) { // Create main tree for testing. db := dbm.NewMemDB() - iStore, err := iavl.LoadStore(db, types.CommitID{}, stypes.PruneNothing) + iStore, err := iavl.LoadStore(db, types.CommitID{}, types.PruneNothing) store := iStore.(*iavl.Store) require.Nil(t, err) store.Set([]byte("MYKEY"), []byte("MYVALUE")) diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index ac4fc6a313ac..33898c0f0382 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -195,7 +195,7 @@ func TestMultiStoreQuery(t *testing.T) { func newMultiStoreWithMounts(db dbm.DB) *Store { store := NewStore(db) - store.pruningOpts = stypes.PruneSyncable + store.pruningOpts = types.PruneSyncable store.MountStoreWithDB( types.NewKVStoreKey("store1"), types.StoreTypeIAVL, nil) store.MountStoreWithDB( From 33ad6657958f866cc80e625fe4ebb25c85a204b8 Mon Sep 17 00:00:00 2001 From: mossid Date: Fri, 25 Jan 2019 14:02:26 +0100 Subject: [PATCH 3/7] add test for errors --- store/types/errors_test.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 store/types/errors_test.go diff --git a/store/types/errors_test.go b/store/types/errors_test.go new file mode 100644 index 000000000000..2d00563631bb --- /dev/null +++ b/store/types/errors_test.go @@ -0,0 +1,35 @@ +package types_test + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func subst(str string) string { + return strings.Replace(str, "sdk", "query", -1) +} + +func errEqual(t *testing.T, err1 types.Error, err2 sdk.Error, ty string) { + errMsg := "%s mismatch in %s between store/types and types" + + require.EqualValues(t, err1.Code(), err2.Code(), errMsg, "Code", ty) + + require.EqualValues(t, err1.ABCILog(), subst(err2.ABCILog()), errMsg, "ABCILog", ty) + require.EqualValues(t, err1.QueryResult().Code, err2.QueryResult().Code, errMsg, "QueryResult.Code", ty) + require.EqualValues(t, err1.QueryResult().Log, subst(err2.QueryResult().Log), errMsg, "QueryResult.Log", ty) + require.EqualValues(t, err1.Error(), subst(err2.Error()), errMsg, "Error", ty) + require.EqualValues(t, types.CodeToDefaultMsg(err1.Code()), sdk.CodeToDefaultMsg(err2.Code()), errMsg, "CodeToDefaultMsg", ty) +} + +func TestErrMatch(t *testing.T) { + msg := "test error msg" + + errEqual(t, types.ErrInternal(msg), sdk.ErrInternal(msg), "ErrInternal") + errEqual(t, types.ErrTxDecode(msg), sdk.ErrTxDecode(msg), "ErrTxDecode") + errEqual(t, types.ErrUnknownRequest(msg), sdk.ErrUnknownRequest(msg), "ErrUnknownRequest") +} From 65b5b199147f522e900d890c80c53f1d68670782 Mon Sep 17 00:00:00 2001 From: mossid Date: Mon, 4 Feb 2019 23:33:14 +0100 Subject: [PATCH 4/7] rm remaining stypes --- store/gaskv/store_test.go | 28 ++++++++++++++-------------- store/iavl/store.go | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/store/gaskv/store_test.go b/store/gaskv/store_test.go index 8d6acd86ef8a..a5b8f8907faa 100644 --- a/store/gaskv/store_test.go +++ b/store/gaskv/store_test.go @@ -8,15 +8,15 @@ import ( "github.com/cosmos/cosmos-sdk/store/dbadapter" "github.com/cosmos/cosmos-sdk/store/gaskv" - stypes "github.com/cosmos/cosmos-sdk/store/types" + "github.com/cosmos/cosmos-sdk/store/types" "github.com/stretchr/testify/require" ) -func newGasKVStore() stypes.KVStore { - meter := stypes.NewGasMeter(10000) +func newGasKVStore() types.KVStore { + meter := types.NewGasMeter(10000) mem := dbadapter.Store{dbm.NewMemDB()} - return gaskv.NewStore(mem, meter, stypes.KVGasConfig()) + return gaskv.NewStore(mem, meter, types.KVGasConfig()) } func bz(s string) []byte { return []byte(s) } @@ -26,20 +26,20 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestGasKVStoreBasic(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - meter := stypes.NewGasMeter(10000) - st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) + meter := types.NewGasMeter(10000) + st := gaskv.NewStore(mem, meter, types.KVGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") st.Set(keyFmt(1), valFmt(1)) require.Equal(t, valFmt(1), st.Get(keyFmt(1))) st.Delete(keyFmt(1)) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") - require.Equal(t, meter.GasConsumed(), stypes.Gas(6429)) + require.Equal(t, meter.GasConsumed(), types.Gas(6429)) } func TestGasKVStoreIterator(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - meter := stypes.NewGasMeter(10000) - st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) + meter := types.NewGasMeter(10000) + st := gaskv.NewStore(mem, meter, types.KVGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") require.Empty(t, st.Get(keyFmt(2)), "Expected `key2` to be empty") st.Set(keyFmt(1), valFmt(1)) @@ -57,20 +57,20 @@ func TestGasKVStoreIterator(t *testing.T) { iterator.Next() require.False(t, iterator.Valid()) require.Panics(t, iterator.Next) - require.Equal(t, meter.GasConsumed(), stypes.Gas(6987)) + require.Equal(t, meter.GasConsumed(), types.Gas(6987)) } func TestGasKVStoreOutOfGasSet(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - meter := stypes.NewGasMeter(0) - st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) + meter := types.NewGasMeter(0) + st := gaskv.NewStore(mem, meter, types.KVGasConfig()) require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas") } func TestGasKVStoreOutOfGasIterator(t *testing.T) { mem := dbadapter.Store{dbm.NewMemDB()} - meter := stypes.NewGasMeter(20000) - st := gaskv.NewStore(mem, meter, stypes.KVGasConfig()) + meter := types.NewGasMeter(20000) + st := gaskv.NewStore(mem, meter, types.KVGasConfig()) st.Set(keyFmt(1), valFmt(1)) iterator := st.Iterator(nil, nil) iterator.Next() diff --git a/store/iavl/store.go b/store/iavl/store.go index da282149fc00..968000668c75 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -130,7 +130,7 @@ func (st *Store) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.Ca // Implements types.KVStore. func (st *Store) Set(key, value []byte) { - stypes.AssertValidValue(value) + types.AssertValidValue(value) st.tree.Set(key, value) } From e3924a8196bbb89f6d8204b17086107f1777fd34 Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 5 Feb 2019 01:42:53 +0100 Subject: [PATCH 5/7] deduplicate errors --- store/errors/errors.go | 19 +++++ store/iavl/store.go | 5 +- store/rootmulti/store.go | 13 ++-- store/types/errors.go | 154 ------------------------------------- store/types/errors_test.go | 35 --------- 5 files changed, 29 insertions(+), 197 deletions(-) create mode 100644 store/errors/errors.go delete mode 100644 store/types/errors.go delete mode 100644 store/types/errors_test.go diff --git a/store/errors/errors.go b/store/errors/errors.go new file mode 100644 index 000000000000..3fe644fcc199 --- /dev/null +++ b/store/errors/errors.go @@ -0,0 +1,19 @@ +package errors + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type Error = sdk.Error + +func ErrInternal(msg string) Error { + return sdk.ErrInternal(msg) +} + +func ErrTxDecode(msg string) Error { + return sdk.ErrTxDecode(msg) +} + +func ErrUnknownRequest(msg string) Error { + return sdk.ErrUnknownRequest(msg) +} diff --git a/store/iavl/store.go b/store/iavl/store.go index 968000668c75..49299301ef15 100644 --- a/store/iavl/store.go +++ b/store/iavl/store.go @@ -12,6 +12,7 @@ import ( dbm "github.com/tendermint/tendermint/libs/db" "github.com/cosmos/cosmos-sdk/store/cachekv" + "github.com/cosmos/cosmos-sdk/store/errors" "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -184,7 +185,7 @@ func getHeight(tree *iavl.MutableTree, req abci.RequestQuery) int64 { func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) { if len(req.Data) == 0 { msg := "Query cannot be zero length" - return types.ErrTxDecode(msg).QueryResult() + return errors.ErrTxDecode(msg).QueryResult() } tree := st.tree @@ -244,7 +245,7 @@ func (st *Store) Query(req abci.RequestQuery) (res abci.ResponseQuery) { default: msg := fmt.Sprintf("Unexpected Query path: %v", req.Path) - return types.ErrUnknownRequest(msg).QueryResult() + return errors.ErrUnknownRequest(msg).QueryResult() } return diff --git a/store/rootmulti/store.go b/store/rootmulti/store.go index dec2d32aadb3..85d9b5b206d8 100644 --- a/store/rootmulti/store.go +++ b/store/rootmulti/store.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/cachemulti" "github.com/cosmos/cosmos-sdk/store/dbadapter" + "github.com/cosmos/cosmos-sdk/store/errors" "github.com/cosmos/cosmos-sdk/store/iavl" "github.com/cosmos/cosmos-sdk/store/tracekv" "github.com/cosmos/cosmos-sdk/store/transient" @@ -288,12 +289,12 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery { store := rs.getStoreByName(storeName) if store == nil { msg := fmt.Sprintf("no such store: %s", storeName) - return types.ErrUnknownRequest(msg).QueryResult() + return errors.ErrUnknownRequest(msg).QueryResult() } queryable, ok := store.(types.Queryable) if !ok { msg := fmt.Sprintf("store %s doesn't support queries", storeName) - return types.ErrUnknownRequest(msg).QueryResult() + return errors.ErrUnknownRequest(msg).QueryResult() } // trim the path and make the query @@ -305,12 +306,12 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery { } if res.Proof == nil || len(res.Proof.Ops) == 0 { - return types.ErrInternal("substore proof was nil/empty when it should never be").QueryResult() + return errors.ErrInternal("substore proof was nil/empty when it should never be").QueryResult() } commitInfo, errMsg := getCommitInfo(rs.db, res.Height) if errMsg != nil { - return types.ErrInternal(errMsg.Error()).QueryResult() + return errors.ErrInternal(errMsg.Error()).QueryResult() } // Restore origin path and append proof op. @@ -327,9 +328,9 @@ func (rs *Store) Query(req abci.RequestQuery) abci.ResponseQuery { // parsePath expects a format like /[/] // Must start with /, subpath may be empty // Returns error if it doesn't start with / -func parsePath(path string) (storeName string, subpath string, err types.Error) { +func parsePath(path string) (storeName string, subpath string, err errors.Error) { if !strings.HasPrefix(path, "/") { - err = types.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path)) + err = errors.ErrUnknownRequest(fmt.Sprintf("invalid path: %s", path)) return } diff --git a/store/types/errors.go b/store/types/errors.go deleted file mode 100644 index c6471c7bdc4a..000000000000 --- a/store/types/errors.go +++ /dev/null @@ -1,154 +0,0 @@ -package types - -import ( - "fmt" - - cmn "github.com/tendermint/tendermint/libs/common" - - "github.com/cosmos/cosmos-sdk/codec" - - abci "github.com/tendermint/tendermint/abci/types" -) - -// CodeType - ABCI code identifier within codespace -type CodeType uint32 - -// CodespaceType - codespace identifier -type CodespaceType string - -// IsOK - is everything okay? -func (code CodeType) IsOK() bool { - if code == CodeOK { - return true - } - return false -} - -// SDK error codes -const ( - // Base error codes - CodeOK CodeType = 0 - CodeInternal CodeType = 1 - CodeTxDecode CodeType = 2 - CodeUnknownRequest CodeType = 6 - - // CodespaceQuery is a codespace for error codes in this file only. - CodespaceQuery CodespaceType = "query" -) - -func unknownCodeMsg(code CodeType) string { - return fmt.Sprintf("unknown code %d", code) -} - -// NOTE: Don't stringer this, we'll put better messages in later. -func CodeToDefaultMsg(code CodeType) string { - switch code { - case CodeInternal: - return "internal error" - case CodeTxDecode: - return "tx parse error" - case CodeUnknownRequest: - return "unknown request" - default: - return unknownCodeMsg(code) - } -} - -//-------------------------------------------------------------------------------- -// All errors are created via constructors so as to enable us to hijack them -// and inject stack traces if we really want to. - -// nolint -func ErrInternal(msg string) Error { - return newQueryError(CodeInternal, msg) -} -func ErrTxDecode(msg string) Error { - return newQueryError(CodeTxDecode, msg) -} -func ErrUnknownRequest(msg string) Error { - return newQueryError(CodeUnknownRequest, msg) -} - -//---------------------------------------- -// Error & queryError - -type cmnError = cmn.Error - -// sdk Error type -type Error interface { - // Implements cmn.Error - // Error() string - // Stacktrace() cmn.Error - // Trace(offset int, format string, args ...interface{}) cmn.Error - // Data() interface{} - cmnError - - Code() CodeType - ABCILog() string - QueryResult() abci.ResponseQuery -} - -func newQueryError(code CodeType, format string, args ...interface{}) *queryError { - if format == "" { - format = CodeToDefaultMsg(code) - } - return &queryError{ - code: code, - cmnError: cmn.NewError(format, args...), - } -} - -type queryError struct { - code CodeType - cmnError -} - -// Implements ABCIError. -func (err *queryError) Error() string { - return fmt.Sprintf(`ERROR: -Codespace: %s -Code: %d -Message: %#v -`, CodespaceQuery, err.code, err.cmnError.Error()) -} - -// Implements Error. -func (err *queryError) Code() CodeType { - return err.code -} - -// Implements ABCIError. -func (err *queryError) ABCILog() string { - cdc := codec.New() - errMsg := err.cmnError.Error() - jsonErr := humanReadableError{ - Codespace: CodespaceQuery, - Code: err.code, - Message: errMsg, - } - bz, er := cdc.MarshalJSON(jsonErr) - if er != nil { - panic(er) - } - stringifiedJSON := string(bz) - return stringifiedJSON -} - -// QueryResult allows us to return sdk.Error.QueryResult() in query responses -func (err *queryError) QueryResult() abci.ResponseQuery { - return abci.ResponseQuery{ - Code: uint32(err.Code()), - Codespace: string(CodespaceQuery), - Log: err.ABCILog(), - } -} - -//---------------------------------------- -// REST error utilities - -// parses the error into an object-like struct for exporting -type humanReadableError struct { - Codespace CodespaceType `json:"codespace"` - Code CodeType `json:"code"` - Message string `json:"message"` -} diff --git a/store/types/errors_test.go b/store/types/errors_test.go deleted file mode 100644 index 2d00563631bb..000000000000 --- a/store/types/errors_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package types_test - -import ( - "strings" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func subst(str string) string { - return strings.Replace(str, "sdk", "query", -1) -} - -func errEqual(t *testing.T, err1 types.Error, err2 sdk.Error, ty string) { - errMsg := "%s mismatch in %s between store/types and types" - - require.EqualValues(t, err1.Code(), err2.Code(), errMsg, "Code", ty) - - require.EqualValues(t, err1.ABCILog(), subst(err2.ABCILog()), errMsg, "ABCILog", ty) - require.EqualValues(t, err1.QueryResult().Code, err2.QueryResult().Code, errMsg, "QueryResult.Code", ty) - require.EqualValues(t, err1.QueryResult().Log, subst(err2.QueryResult().Log), errMsg, "QueryResult.Log", ty) - require.EqualValues(t, err1.Error(), subst(err2.Error()), errMsg, "Error", ty) - require.EqualValues(t, types.CodeToDefaultMsg(err1.Code()), sdk.CodeToDefaultMsg(err2.Code()), errMsg, "CodeToDefaultMsg", ty) -} - -func TestErrMatch(t *testing.T) { - msg := "test error msg" - - errEqual(t, types.ErrInternal(msg), sdk.ErrInternal(msg), "ErrInternal") - errEqual(t, types.ErrTxDecode(msg), sdk.ErrTxDecode(msg), "ErrTxDecode") - errEqual(t, types.ErrUnknownRequest(msg), sdk.ErrUnknownRequest(msg), "ErrUnknownRequest") -} From 67f9143d77784ffebdc5755c36a4d9a4cc73b40f Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 5 Feb 2019 19:15:16 +0100 Subject: [PATCH 6/7] fix test --- store/errors/errors.go | 9 +++++++++ store/iavl/store_test.go | 21 +++++++++++---------- store/rootmulti/store_test.go | 19 ++++++++++--------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/store/errors/errors.go b/store/errors/errors.go index 3fe644fcc199..4867d79762c1 100644 --- a/store/errors/errors.go +++ b/store/errors/errors.go @@ -4,6 +4,15 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +const ( + CodeOK = sdk.CodeOK + CodeInternal = sdk.CodeInternal + CodeTxDecode = sdk.CodeTxDecode + CodeUnknownRequest = sdk.CodeUnknownRequest + + CodespaceRoot = sdk.CodespaceRoot +) + type Error = sdk.Error func ErrInternal(msg string) Error { diff --git a/store/iavl/store_test.go b/store/iavl/store_test.go index 6149ee241ce1..b46c202a53b2 100644 --- a/store/iavl/store_test.go +++ b/store/iavl/store_test.go @@ -11,6 +11,7 @@ import ( cmn "github.com/tendermint/tendermint/libs/common" dbm "github.com/tendermint/tendermint/libs/db" + "github.com/cosmos/cosmos-sdk/store/errors" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -443,7 +444,7 @@ func TestIAVLStoreQuery(t *testing.T) { // query subspace before anything set qres := iavlStore.Query(querySub) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Equal(t, valExpSubEmpty, qres.Value) // set data @@ -452,24 +453,24 @@ func TestIAVLStoreQuery(t *testing.T) { // set data without commit, doesn't show up qres = iavlStore.Query(query) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Nil(t, qres.Value) // commit it, but still don't see on old version cid = iavlStore.Commit() qres = iavlStore.Query(query) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Nil(t, qres.Value) // but yes on the new version query.Height = cid.Version qres = iavlStore.Query(query) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Equal(t, v1, qres.Value) // and for the subspace qres = iavlStore.Query(querySub) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Equal(t, valExpSub1, qres.Value) // modify @@ -478,28 +479,28 @@ func TestIAVLStoreQuery(t *testing.T) { // query will return old values, as height is fixed qres = iavlStore.Query(query) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Equal(t, v1, qres.Value) // update to latest in the query and we are happy query.Height = cid.Version qres = iavlStore.Query(query) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Equal(t, v3, qres.Value) query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version} qres = iavlStore.Query(query2) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Equal(t, v2, qres.Value) // and for the subspace qres = iavlStore.Query(querySub) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Equal(t, valExpSub2, qres.Value) // default (height 0) will show latest -1 query0 := abci.RequestQuery{Path: "/key", Data: k1} qres = iavlStore.Query(query0) - require.Equal(t, uint32(types.CodeOK), qres.Code) + require.Equal(t, uint32(errors.CodeOK), qres.Code) require.Equal(t, v1, qres.Value) } diff --git a/store/rootmulti/store_test.go b/store/rootmulti/store_test.go index 33898c0f0382..85ada55873d2 100644 --- a/store/rootmulti/store_test.go +++ b/store/rootmulti/store_test.go @@ -8,6 +8,7 @@ import ( "github.com/tendermint/tendermint/crypto/merkle" dbm "github.com/tendermint/tendermint/libs/db" + "github.com/cosmos/cosmos-sdk/store/errors" "github.com/cosmos/cosmos-sdk/store/types" ) @@ -156,37 +157,37 @@ func TestMultiStoreQuery(t *testing.T) { // Test bad path. query := abci.RequestQuery{Path: "/key", Data: k, Height: ver} qres := multi.Query(query) - require.EqualValues(t, types.CodeUnknownRequest, qres.Code) - require.EqualValues(t, types.CodespaceQuery, qres.Codespace) + require.EqualValues(t, errors.CodeUnknownRequest, qres.Code) + require.EqualValues(t, errors.CodespaceRoot, qres.Codespace) query.Path = "h897fy32890rf63296r92" qres = multi.Query(query) - require.EqualValues(t, types.CodeUnknownRequest, qres.Code) - require.EqualValues(t, types.CodespaceQuery, qres.Codespace) + require.EqualValues(t, errors.CodeUnknownRequest, qres.Code) + require.EqualValues(t, errors.CodespaceRoot, qres.Codespace) // Test invalid store name. query.Path = "/garbage/key" qres = multi.Query(query) - require.EqualValues(t, types.CodeUnknownRequest, qres.Code) - require.EqualValues(t, types.CodespaceQuery, qres.Codespace) + require.EqualValues(t, errors.CodeUnknownRequest, qres.Code) + require.EqualValues(t, errors.CodespaceRoot, qres.Codespace) // Test valid query with data. query.Path = "/store1/key" qres = multi.Query(query) - require.EqualValues(t, types.CodeOK, qres.Code) + require.EqualValues(t, errors.CodeOK, qres.Code) require.Equal(t, v, qres.Value) // Test valid but empty query. query.Path = "/store2/key" query.Prove = true qres = multi.Query(query) - require.EqualValues(t, types.CodeOK, qres.Code) + require.EqualValues(t, errors.CodeOK, qres.Code) require.Nil(t, qres.Value) // Test store2 data. query.Data = k2 qres = multi.Query(query) - require.EqualValues(t, types.CodeOK, qres.Code) + require.EqualValues(t, errors.CodeOK, qres.Code) require.Equal(t, v2, qres.Value) } From 14a33ed29a7c980551a38e5a103a493ea515909d Mon Sep 17 00:00:00 2001 From: mossid Date: Tue, 5 Feb 2019 19:16:26 +0100 Subject: [PATCH 7/7] fix lint --- store/errors/errors.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/store/errors/errors.go b/store/errors/errors.go index 4867d79762c1..361a10fdb0da 100644 --- a/store/errors/errors.go +++ b/store/errors/errors.go @@ -4,6 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) +// nolint - reexport const ( CodeOK = sdk.CodeOK CodeInternal = sdk.CodeInternal @@ -13,16 +14,16 @@ const ( CodespaceRoot = sdk.CodespaceRoot ) +// nolint - reexport type Error = sdk.Error +// nolint - reexport func ErrInternal(msg string) Error { return sdk.ErrInternal(msg) } - func ErrTxDecode(msg string) Error { return sdk.ErrTxDecode(msg) } - func ErrUnknownRequest(msg string) Error { return sdk.ErrUnknownRequest(msg) }