package mock_test import ( "context" "errors" "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/abci/example/kvstore" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/bytes" "github.com/tendermint/tendermint/rpc/client" "github.com/tendermint/tendermint/rpc/client/mock" ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" ) func TestABCIMock(t *testing.T) { assert, require := assert.New(t), require.New(t) key, value := []byte("foo"), []byte("bar") height := int64(10) goodTx := types.Tx{0x01, 0xff} badTx := types.Tx{0x12, 0x21} m := mock.ABCIMock{ Info: mock.Call{Error: errors.New("foobar")}, Query: mock.Call{Response: abci.ResponseQuery{ Key: key, Value: value, Height: height, }}, // Broadcast commit depends on call BroadcastCommit: mock.Call{ Args: goodTx, Response: &ctypes.ResultBroadcastTxCommit{ CheckTx: abci.ResponseCheckTx{Data: bytes.HexBytes("stand")}, DeliverTx: abci.ResponseDeliverTx{Data: bytes.HexBytes("deliver")}, }, Error: errors.New("bad tx"), }, Broadcast: mock.Call{Error: errors.New("must commit")}, } // now, let's try to make some calls _, err := m.ABCIInfo(context.Background()) require.NotNil(err) assert.Equal("foobar", err.Error()) // query always returns the response _query, err := m.ABCIQueryWithOptions(context.Background(), "/", nil, client.ABCIQueryOptions{Prove: false}) query := _query.Response require.Nil(err) require.NotNil(query) assert.EqualValues(key, query.Key) assert.EqualValues(value, query.Value) assert.Equal(height, query.Height) // non-commit calls always return errors _, err = m.BroadcastTxSync(context.Background(), goodTx) require.NotNil(err) assert.Equal("must commit", err.Error()) _, err = m.BroadcastTxAsync(context.Background(), goodTx) require.NotNil(err) assert.Equal("must commit", err.Error()) // commit depends on the input _, err = m.BroadcastTxCommit(context.Background(), badTx) require.NotNil(err) assert.Equal("bad tx", err.Error()) bres, err := m.BroadcastTxCommit(context.Background(), goodTx) require.Nil(err, "%+v", err) assert.EqualValues(0, bres.CheckTx.Code) assert.EqualValues("stand", bres.CheckTx.Data) assert.EqualValues("deliver", bres.DeliverTx.Data) } func TestABCIRecorder(t *testing.T) { assert, require := assert.New(t), require.New(t) // This mock returns errors on everything but Query m := mock.ABCIMock{ Info: mock.Call{Response: abci.ResponseInfo{ Data: "data", Version: "v0.9.9", }}, Query: mock.Call{Error: errors.New("query")}, Broadcast: mock.Call{Error: errors.New("broadcast")}, BroadcastCommit: mock.Call{Error: errors.New("broadcast_commit")}, } r := mock.NewABCIRecorder(m) require.Equal(0, len(r.Calls)) _, err := r.ABCIInfo(context.Background()) assert.Nil(err, "expected no err on info") _, err = r.ABCIQueryWithOptions( context.Background(), "path", bytes.HexBytes("data"), client.ABCIQueryOptions{Prove: false}, ) assert.NotNil(err, "expected error on query") require.Equal(2, len(r.Calls)) info := r.Calls[0] assert.Equal("abci_info", info.Name) assert.Nil(info.Error) assert.Nil(info.Args) require.NotNil(info.Response) ir, ok := info.Response.(*ctypes.ResultABCIInfo) require.True(ok) assert.Equal("data", ir.Response.Data) assert.Equal("v0.9.9", ir.Response.Version) query := r.Calls[1] assert.Equal("abci_query", query.Name) assert.Nil(query.Response) require.NotNil(query.Error) assert.Equal("query", query.Error.Error()) require.NotNil(query.Args) qa, ok := query.Args.(mock.QueryArgs) require.True(ok) assert.Equal("path", qa.Path) assert.EqualValues("data", qa.Data) assert.False(qa.Prove) // now add some broadcasts (should all err) txs := []types.Tx{{1}, {2}, {3}} _, err = r.BroadcastTxCommit(context.Background(), txs[0]) assert.NotNil(err, "expected err on broadcast") _, err = r.BroadcastTxSync(context.Background(), txs[1]) assert.NotNil(err, "expected err on broadcast") _, err = r.BroadcastTxAsync(context.Background(), txs[2]) assert.NotNil(err, "expected err on broadcast") require.Equal(5, len(r.Calls)) bc := r.Calls[2] assert.Equal("broadcast_tx_commit", bc.Name) assert.Nil(bc.Response) require.NotNil(bc.Error) assert.EqualValues(bc.Args, txs[0]) bs := r.Calls[3] assert.Equal("broadcast_tx_sync", bs.Name) assert.Nil(bs.Response) require.NotNil(bs.Error) assert.EqualValues(bs.Args, txs[1]) ba := r.Calls[4] assert.Equal("broadcast_tx_async", ba.Name) assert.Nil(ba.Response) require.NotNil(ba.Error) assert.EqualValues(ba.Args, txs[2]) } func TestABCIApp(t *testing.T) { assert, require := assert.New(t), require.New(t) app := kvstore.NewApplication() m := mock.ABCIApp{app} // get some info info, err := m.ABCIInfo(context.Background()) require.Nil(err) assert.Equal(`{"size":0}`, info.Response.GetData()) // add a key key, value := "foo", "bar" tx := fmt.Sprintf("%s=%s", key, value) res, err := m.BroadcastTxCommit(context.Background(), types.Tx(tx)) require.Nil(err) assert.True(res.CheckTx.IsOK()) require.NotNil(res.DeliverTx) assert.True(res.DeliverTx.IsOK()) // commit // TODO: This may not be necessary in the future if res.Height == -1 { m.App.Commit() } // check the key _qres, err := m.ABCIQueryWithOptions( context.Background(), "/key", bytes.HexBytes(key), client.ABCIQueryOptions{Prove: true}, ) qres := _qres.Response require.Nil(err) assert.EqualValues(value, qres.Value) // XXX Check proof }