mock application framework compiling

This commit is contained in:
rigelrozanski 2018-06-07 16:13:11 -07:00
parent 3c17fa285c
commit f58b454985
3 changed files with 281 additions and 0 deletions

85
tests/mock/app.go Normal file
View File

@ -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{}
}

View File

@ -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{})
}

96
x/bank/app_test.go Normal file
View File

@ -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)
}