github.com/Finschia/finschia-sdk@v0.48.1/server/mock/app.go (about) 1 package mock 2 3 import ( 4 "context" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "path/filepath" 9 10 ocabci "github.com/Finschia/ostracon/abci/types" 11 "github.com/Finschia/ostracon/libs/log" 12 "github.com/Finschia/ostracon/types" 13 abci "github.com/tendermint/tendermint/abci/types" 14 15 bam "github.com/Finschia/finschia-sdk/baseapp" 16 "github.com/Finschia/finschia-sdk/codec" 17 storetypes "github.com/Finschia/finschia-sdk/store/types" 18 sdk "github.com/Finschia/finschia-sdk/types" 19 ) 20 21 // NewApp creates a simple mock kvstore app for testing. It should work 22 // similar to a real app. Make sure rootDir is empty before running the test, 23 // in order to guarantee consistent results 24 func NewApp(rootDir string, logger log.Logger) (ocabci.Application, error) { 25 db, err := sdk.NewLevelDB("mock", filepath.Join(rootDir, "data")) 26 if err != nil { 27 return nil, err 28 } 29 30 // Capabilities key to access the main KVStore. 31 capKeyMainStore := sdk.NewKVStoreKey("main") 32 33 // Create BaseApp. 34 baseApp := bam.NewBaseApp("kvstore", logger, db, decodeTx) 35 36 // Set mounts for BaseApp's MultiStore. 37 baseApp.MountStores(capKeyMainStore) 38 39 baseApp.SetInitChainer(InitChainer(capKeyMainStore)) 40 41 baseApp.Router().AddRoute(sdk.NewRoute("kvstore", KVStoreHandler(capKeyMainStore))) 42 43 // Load latest version. 44 if err := baseApp.LoadLatestVersion(); err != nil { 45 return nil, err 46 } 47 48 return baseApp, nil 49 } 50 51 // KVStoreHandler is a simple handler that takes kvstoreTx and writes 52 // them to the db 53 func KVStoreHandler(storeKey sdk.StoreKey) sdk.Handler { 54 return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { 55 dTx, ok := msg.(kvstoreTx) 56 if !ok { 57 return nil, errors.New("KVStoreHandler should only receive kvstoreTx") 58 } 59 60 // tx is already unmarshalled 61 key := dTx.key 62 value := dTx.value 63 64 store := ctx.KVStore(storeKey) 65 store.Set(key, value) 66 67 return &sdk.Result{ 68 Log: fmt.Sprintf("set %s=%s", key, value), 69 }, nil 70 } 71 } 72 73 // basic KV structure 74 type KV struct { 75 Key string `json:"key"` 76 Value string `json:"value"` 77 } 78 79 // What Genesis JSON is formatted as 80 type GenesisJSON struct { 81 Values []KV `json:"values"` 82 } 83 84 // InitChainer returns a function that can initialize the chain 85 // with key/value pairs 86 func InitChainer(key sdk.StoreKey) func(sdk.Context, abci.RequestInitChain) abci.ResponseInitChain { 87 return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { 88 stateJSON := req.AppStateBytes 89 90 genesisState := new(GenesisJSON) 91 err := json.Unmarshal(stateJSON, genesisState) 92 if err != nil { 93 panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468 94 // return sdk.ErrGenesisParse("").TraceCause(err, "") 95 } 96 97 for _, val := range genesisState.Values { 98 store := ctx.KVStore(key) 99 store.Set([]byte(val.Key), []byte(val.Value)) 100 } 101 return abci.ResponseInitChain{} 102 } 103 } 104 105 // AppGenState can be passed into InitCmd, returns a static string of a few 106 // key-values that can be parsed by InitChainer 107 func AppGenState(_ *codec.LegacyAmino, _ types.GenesisDoc, _ []json.RawMessage) (appState json. 108 RawMessage, err error, 109 ) { 110 appState = json.RawMessage(`{ 111 "values": [ 112 { 113 "key": "hello", 114 "value": "goodbye" 115 }, 116 { 117 "key": "foo", 118 "value": "bar" 119 } 120 ] 121 }`) 122 return 123 } 124 125 // AppGenStateEmpty returns an empty transaction state for mocking. 126 func AppGenStateEmpty(_ *codec.LegacyAmino, _ types.GenesisDoc, _ []json.RawMessage) ( 127 appState json.RawMessage, err error, 128 ) { 129 appState = json.RawMessage(``) 130 return 131 } 132 133 // Manually write the handlers for this custom message 134 type MsgServer interface { 135 Test(ctx context.Context, msg *kvstoreTx) (*sdk.Result, error) 136 } 137 138 type MsgServerImpl struct { 139 capKeyMainStore *storetypes.KVStoreKey 140 } 141 142 func (m MsgServerImpl) Test(ctx context.Context, msg *kvstoreTx) (*sdk.Result, error) { 143 return KVStoreHandler(m.capKeyMainStore)(sdk.UnwrapSDKContext(ctx), msg) 144 }