mock application framework compiling
This commit is contained in:
parent
3c17fa285c
commit
f58b454985
|
@ -0,0 +1,85 @@
|
|||
package mock
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"os"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/abci/types"
|
||||
dbm "github.com/tendermint/tmlibs/db"
|
||||
"github.com/tendermint/tmlibs/log"
|
||||
|
||||
bam "github.com/cosmos/cosmos-sdk/baseapp"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
)
|
||||
|
||||
// Extended ABCI application
|
||||
type App struct {
|
||||
*bam.BaseApp
|
||||
Cdc *wire.Codec // public since the codec is passed into the module anyways.
|
||||
KeyMain *sdk.KVStoreKey
|
||||
KeyAccount *sdk.KVStoreKey
|
||||
|
||||
// TODO: Abstract this out from not needing to be auth specifically
|
||||
AccountMapper auth.AccountMapper
|
||||
FeeCollectionKeeper auth.FeeCollectionKeeper
|
||||
|
||||
GenesisAccounts []auth.Account
|
||||
}
|
||||
|
||||
// NewApp is used for testing the server. For the internal mock app stuff, it uses code in helpers.go
|
||||
func NewApp() *App {
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "sdk/app")
|
||||
db := dbm.NewMemDB()
|
||||
|
||||
// create the cdc with some standard codecs
|
||||
cdc := wire.NewCodec()
|
||||
sdk.RegisterWire(cdc)
|
||||
wire.RegisterCrypto(cdc)
|
||||
|
||||
// create your application object
|
||||
app := &App{
|
||||
BaseApp: bam.NewBaseApp("mock", cdc, logger, db),
|
||||
Cdc: cdc,
|
||||
KeyMain: sdk.NewKVStoreKey("main"),
|
||||
KeyAccount: sdk.NewKVStoreKey("acc"),
|
||||
}
|
||||
|
||||
// define the accountMapper
|
||||
app.AccountMapper = auth.NewAccountMapper(
|
||||
app.Cdc,
|
||||
app.KeyAccount, // target store
|
||||
&auth.BaseAccount{}, // prototype
|
||||
)
|
||||
|
||||
// initialize the app, the chainers and blockers can be overwritten before calling complete setup
|
||||
app.SetInitChainer(app.initChainer)
|
||||
|
||||
app.SetAnteHandler(auth.NewAnteHandler(app.AccountMapper, app.FeeCollectionKeeper))
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
// complete the application setup after the routes have been registered
|
||||
func (app App) CompleteSetup(t *testing.T, newKeys []*sdk.KVStoreKey) {
|
||||
|
||||
newKeys = append(newKeys, app.KeyMain)
|
||||
newKeys = append(newKeys, app.KeyAccount)
|
||||
app.MountStoresIAVL(newKeys...)
|
||||
err := app.LoadLatestVersion(app.KeyMain)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// custom logic for initialization
|
||||
func (app App) initChainer(ctx sdk.Context, _ abci.RequestInitChain) abci.ResponseInitChain {
|
||||
|
||||
// load the accounts
|
||||
for _, acc := range app.GenesisAccounts {
|
||||
app.AccountMapper.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
return abci.ResponseInitChain{}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package mock
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
)
|
||||
|
||||
var chainID = "" // TODO
|
||||
|
||||
// set the mock app genesis
|
||||
func SetGenesis(app *App, accs []auth.Account) {
|
||||
|
||||
// pass the accounts in via the application (lazy) instead of through RequestInitChain
|
||||
app.GenesisAccounts = accs
|
||||
|
||||
app.InitChain(abci.RequestInitChain{})
|
||||
app.Commit()
|
||||
}
|
||||
|
||||
// check an account balance
|
||||
func CheckBalance(t *testing.T, app *App, addr sdk.Address, exp sdk.Coins) {
|
||||
ctxDeliver := app.BaseApp.NewContext(false, abci.Header{})
|
||||
res := app.AccountMapper.GetAccount(ctxDeliver, addr)
|
||||
assert.Equal(t, exp, res.GetCoins())
|
||||
}
|
||||
|
||||
// generate a signed transaction
|
||||
func GenTx(msg sdk.Msg, seq []int64, priv ...crypto.PrivKeyEd25519) auth.StdTx {
|
||||
|
||||
// make the transaction free
|
||||
fee := auth.StdFee{
|
||||
sdk.Coins{{"foocoin", 0}},
|
||||
100000,
|
||||
}
|
||||
|
||||
sigs := make([]auth.StdSignature, len(priv))
|
||||
for i, p := range priv {
|
||||
sigs[i] = auth.StdSignature{
|
||||
PubKey: p.PubKey(),
|
||||
Signature: p.Sign(auth.StdSignBytes(chainID, seq, fee, msg)),
|
||||
Sequence: seq[i],
|
||||
}
|
||||
}
|
||||
return auth.NewStdTx(msg, fee, sigs)
|
||||
}
|
||||
|
||||
// simulate a block
|
||||
func SignCheckDeliver(t *testing.T, app *App, msg sdk.Msg, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) {
|
||||
|
||||
// Sign the tx
|
||||
tx := GenTx(msg, seq, priv...)
|
||||
|
||||
// Run a Check
|
||||
res := app.Check(tx)
|
||||
if expPass {
|
||||
require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||
} else {
|
||||
require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||
}
|
||||
|
||||
// Simulate a Block
|
||||
app.BeginBlock(abci.RequestBeginBlock{})
|
||||
res = app.Deliver(tx)
|
||||
if expPass {
|
||||
require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||
} else {
|
||||
require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||
}
|
||||
app.EndBlock(abci.RequestEndBlock{})
|
||||
|
||||
// XXX fix code or add explaination as to why using commit breaks a bunch of these tests
|
||||
//app.Commit()
|
||||
}
|
||||
|
||||
// XXX the only reason we are using Sign Deliver here is because the tests
|
||||
// break on check tx the second time you use SignCheckDeliver in a test because
|
||||
// the checktx state has not been updated likely because commit is not being
|
||||
// called!
|
||||
func SignDeliver(t *testing.T, app App, msg sdk.Msg, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) {
|
||||
|
||||
// Sign the tx
|
||||
tx := GenTx(msg, seq, priv...)
|
||||
|
||||
// Simulate a Block
|
||||
app.BeginBlock(abci.RequestBeginBlock{})
|
||||
res := app.Deliver(tx)
|
||||
if expPass {
|
||||
require.Equal(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||
} else {
|
||||
require.NotEqual(t, sdk.ABCICodeOK, res.Code, res.Log)
|
||||
}
|
||||
app.EndBlock(abci.RequestEndBlock{})
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package bank
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/tests/mock"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
// test bank module in a mock application
|
||||
var (
|
||||
chainID = "" // TODO
|
||||
|
||||
accName = "foobart"
|
||||
|
||||
priv1 = crypto.GenPrivKeyEd25519()
|
||||
addr1 = priv1.PubKey().Address()
|
||||
priv2 = crypto.GenPrivKeyEd25519()
|
||||
addr2 = priv2.PubKey().Address()
|
||||
addr3 = crypto.GenPrivKeyEd25519().PubKey().Address()
|
||||
priv4 = crypto.GenPrivKeyEd25519()
|
||||
addr4 = priv4.PubKey().Address()
|
||||
coins = sdk.Coins{{"foocoin", 10}}
|
||||
halfCoins = sdk.Coins{{"foocoin", 5}}
|
||||
manyCoins = sdk.Coins{{"foocoin", 1}, {"barcoin", 1}}
|
||||
fee = auth.StdFee{
|
||||
sdk.Coins{{"foocoin", 0}},
|
||||
100000,
|
||||
}
|
||||
|
||||
sendMsg1 = MsgSend{
|
||||
Inputs: []Input{NewInput(addr1, coins)},
|
||||
Outputs: []Output{NewOutput(addr2, coins)},
|
||||
}
|
||||
)
|
||||
|
||||
func TestMsgSendWithAccounts(t *testing.T) {
|
||||
|
||||
// initialize the mock application
|
||||
mapp := mock.NewApp()
|
||||
|
||||
RegisterWire(mapp.Cdc)
|
||||
coinKeeper := NewKeeper(mapp.AccountMapper)
|
||||
mapp.Router().AddRoute("bank", NewHandler(coinKeeper))
|
||||
|
||||
mapp.CompleteSetup(t, []*sdk.KVStoreKey{})
|
||||
|
||||
// Add an account at genesis
|
||||
coins, err := sdk.ParseCoins("77foocoin")
|
||||
require.Nil(t, err)
|
||||
//acc := auth.NewAccountWithAddress(addr1)
|
||||
//acc.SetCoins(coins)
|
||||
//accs := []auth.Account{acc}
|
||||
|
||||
baseAcc := &auth.BaseAccount{
|
||||
Address: addr1,
|
||||
Coins: coins,
|
||||
}
|
||||
baseAccs := []auth.Account{baseAcc}
|
||||
|
||||
// Construct genesis state
|
||||
mock.SetGenesis(mapp, baseAccs)
|
||||
|
||||
// A checkTx context (true)
|
||||
ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
|
||||
res1 := mapp.AccountMapper.GetAccount(ctxCheck, addr1)
|
||||
require.NotNil(t, res1)
|
||||
assert.Equal(t, baseAcc, res1.(*auth.BaseAccount))
|
||||
|
||||
// Run a CheckDeliver
|
||||
mock.SignCheckDeliver(t, mapp, sendMsg1, []int64{0}, true, priv1)
|
||||
|
||||
// Check balances
|
||||
mock.CheckBalance(t, mapp, addr1, sdk.Coins{{"foocoin", 67}})
|
||||
mock.CheckBalance(t, mapp, addr2, sdk.Coins{{"foocoin", 10}})
|
||||
|
||||
// Delivering again should cause replay error
|
||||
mock.SignCheckDeliver(t, mapp, sendMsg1, []int64{0}, false, priv1)
|
||||
|
||||
// bumping the txnonce number without resigning should be an auth error
|
||||
tx := mock.GenTx(sendMsg1, []int64{0}, priv1)
|
||||
tx.Signatures[0].Sequence = 1
|
||||
res := mapp.Deliver(tx)
|
||||
|
||||
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
|
||||
|
||||
// resigning the tx with the bumped sequence should work
|
||||
mock.SignCheckDeliver(t, mapp, sendMsg1, []int64{1}, true, priv1)
|
||||
}
|
Loading…
Reference in New Issue