tendermint/rpc/test/client_test.go

409 lines
11 KiB
Go
Raw Normal View History

2016-01-10 13:33:52 -08:00
package rpctest
import (
2016-07-05 11:41:50 -07:00
"bytes"
2016-08-22 13:00:48 -07:00
crand "crypto/rand"
2016-01-10 13:33:52 -08:00
"fmt"
2016-08-22 13:00:48 -07:00
"math/rand"
2016-01-10 13:33:52 -08:00
"testing"
2016-08-22 13:00:48 -07:00
"time"
2016-01-10 13:33:52 -08:00
2017-02-21 10:57:10 -08:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2017-04-09 20:07:15 -07:00
2017-01-28 08:27:13 -08:00
abci "github.com/tendermint/abci/types"
"github.com/tendermint/tendermint/rpc/core"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
2017-04-27 16:51:18 -07:00
rpc "github.com/tendermint/tendermint/rpc/lib/client"
"github.com/tendermint/tendermint/state/txindex/null"
2016-01-10 13:33:52 -08:00
"github.com/tendermint/tendermint/types"
2017-04-25 07:49:01 -07:00
. "github.com/tendermint/tmlibs/common"
2016-01-10 13:33:52 -08:00
)
//--------------------------------------------------------------------------------
// Test the HTTP client
2016-08-22 13:00:48 -07:00
// These tests assume the dummy app
2016-03-02 22:18:11 -08:00
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
// status
2016-01-10 13:33:52 -08:00
func TestURIStatus(t *testing.T) {
testStatus(t, GetURIClient())
2016-01-10 13:33:52 -08:00
}
func TestJSONStatus(t *testing.T) {
testStatus(t, GetJSONClient())
2016-01-10 13:33:52 -08:00
}
func testStatus(t *testing.T, client rpc.HTTPClient) {
2017-02-21 10:36:18 -08:00
chainID := GetConfig().GetString("chain_id")
tmResult := new(ctypes.TMResult)
_, err := client.Call("status", map[string]interface{}{}, tmResult)
require.Nil(t, err)
2017-02-21 10:36:18 -08:00
status := (*tmResult).(*ctypes.ResultStatus)
2017-02-21 10:57:10 -08:00
assert.Equal(t, chainID, status.NodeInfo.Network)
2016-01-10 13:33:52 -08:00
}
2016-07-05 11:41:50 -07:00
//--------------------------------------------------------------------------------
// broadcast tx sync
2016-08-22 13:00:48 -07:00
// random bytes (excluding byte('='))
2017-02-21 10:57:10 -08:00
func randBytes(t *testing.T) []byte {
2016-08-22 13:00:48 -07:00
n := rand.Intn(10) + 2
buf := make([]byte, n)
_, err := crand.Read(buf)
2017-02-21 10:57:10 -08:00
require.Nil(t, err)
2016-08-22 13:00:48 -07:00
return bytes.Replace(buf, []byte("="), []byte{100}, -1)
}
2016-07-05 11:41:50 -07:00
func TestURIBroadcastTxSync(t *testing.T) {
testBroadcastTxSync(t, GetURIClient())
2016-07-05 11:41:50 -07:00
}
func TestJSONBroadcastTxSync(t *testing.T) {
testBroadcastTxSync(t, GetJSONClient())
}
func testBroadcastTxSync(t *testing.T, client rpc.HTTPClient) {
2017-04-12 18:23:58 -07:00
mem := node.MempoolReactor().Mempool
initMemSize := mem.Size()
2016-07-05 11:41:50 -07:00
tmResult := new(ctypes.TMResult)
2017-02-21 10:57:10 -08:00
tx := randBytes(t)
_, err := client.Call("broadcast_tx_sync", map[string]interface{}{"tx": tx}, tmResult)
2017-02-21 10:57:10 -08:00
require.Nil(t, err)
2016-07-05 11:41:50 -07:00
res := (*tmResult).(*ctypes.ResultBroadcastTx)
2017-02-21 10:57:10 -08:00
require.Equal(t, abci.CodeType_OK, res.Code)
2017-04-12 18:23:58 -07:00
require.Equal(t, initMemSize+1, mem.Size())
2016-07-05 11:41:50 -07:00
txs := mem.Reap(1)
2017-02-21 10:57:10 -08:00
require.EqualValues(t, tx, txs[0])
2016-07-05 11:41:50 -07:00
mem.Flush()
}
2016-08-22 13:00:48 -07:00
//--------------------------------------------------------------------------------
// query
2017-03-22 12:13:18 -07:00
func testTxKV(t *testing.T) ([]byte, []byte, types.Tx) {
2017-02-21 10:57:10 -08:00
k := randBytes(t)
v := randBytes(t)
2017-03-22 12:13:18 -07:00
return k, v, types.Tx(Fmt("%s=%s", k, v))
2016-08-22 13:00:48 -07:00
}
func sendTx(t *testing.T, client rpc.HTTPClient) ([]byte, []byte) {
2016-08-22 13:00:48 -07:00
tmResult := new(ctypes.TMResult)
2017-02-21 10:57:10 -08:00
k, v, tx := testTxKV(t)
2017-04-25 07:49:01 -07:00
_, err := client.Call("broadcast_tx_commit", map[string]interface{}{"tx": tx}, tmResult)
2017-02-21 10:57:10 -08:00
require.Nil(t, err)
2017-04-25 07:49:01 -07:00
bres := (*tmResult).(*ctypes.ResultBroadcastTxCommit)
require.NotNil(t, 0, bres.DeliverTx, "%#v", bres)
2017-04-27 16:51:18 -07:00
require.EqualValues(t, 0, bres.CheckTx.Code, "%#v", bres)
require.EqualValues(t, 0, bres.DeliverTx.Code, "%#v", bres)
2016-08-22 13:00:48 -07:00
return k, v
}
2017-01-12 12:53:32 -08:00
func TestURIABCIQuery(t *testing.T) {
testABCIQuery(t, GetURIClient())
2016-08-22 13:00:48 -07:00
}
2017-01-12 12:53:32 -08:00
func TestJSONABCIQuery(t *testing.T) {
2017-04-25 07:49:01 -07:00
testABCIQuery(t, GetJSONClient())
}
func testABCIQuery(t *testing.T, client rpc.HTTPClient) {
k, _ := sendTx(t, client)
2017-04-21 14:28:13 -07:00
time.Sleep(time.Millisecond * 500)
2016-08-22 13:00:48 -07:00
tmResult := new(ctypes.TMResult)
_, err := client.Call("abci_query",
map[string]interface{}{"path": "", "data": k, "prove": false}, tmResult)
2017-02-21 10:57:10 -08:00
require.Nil(t, err)
2017-04-21 14:28:13 -07:00
resQuery := (*tmResult).(*ctypes.ResultABCIQuery)
2017-04-27 16:51:18 -07:00
require.EqualValues(t, 0, resQuery.Code)
2016-11-22 18:28:57 -08:00
2016-08-22 13:00:48 -07:00
// XXX: specific to value returned by the dummy
2017-04-27 16:51:18 -07:00
require.NotEqual(t, 0, len(resQuery.Value))
2016-08-22 13:00:48 -07:00
}
2016-07-05 11:41:50 -07:00
//--------------------------------------------------------------------------------
// broadcast tx commit
func TestURIBroadcastTxCommit(t *testing.T) {
testBroadcastTxCommit(t, GetURIClient())
2016-07-05 11:41:50 -07:00
}
func TestJSONBroadcastTxCommit(t *testing.T) {
testBroadcastTxCommit(t, GetJSONClient())
2017-04-11 03:57:06 -07:00
}
func testBroadcastTxCommit(t *testing.T, client rpc.HTTPClient) {
2017-04-11 03:57:06 -07:00
require := require.New(t)
tmResult := new(ctypes.TMResult)
tx := randBytes(t)
_, err := client.Call("broadcast_tx_commit", map[string]interface{}{"tx": tx}, tmResult)
require.Nil(err)
res := (*tmResult).(*ctypes.ResultBroadcastTxCommit)
checkTx := res.CheckTx
2017-02-21 10:57:10 -08:00
require.Equal(abci.CodeType_OK, checkTx.Code)
2017-01-12 12:55:03 -08:00
deliverTx := res.DeliverTx
2017-02-21 10:57:10 -08:00
require.Equal(abci.CodeType_OK, deliverTx.Code)
2016-07-05 11:41:50 -07:00
mem := node.MempoolReactor().Mempool
2017-02-21 10:57:10 -08:00
require.Equal(0, mem.Size())
// TODO: find tx in block
2016-07-05 11:41:50 -07:00
}
2016-01-10 13:33:52 -08:00
2017-04-13 11:18:35 -07:00
//--------------------------------------------------------------------------------
// query tx
func TestURITx(t *testing.T) {
2017-04-13 13:26:07 -07:00
testTx(t, GetURIClient(), true)
core.SetTxIndexer(&null.TxIndex{})
testTx(t, GetJSONClient(), false)
core.SetTxIndexer(node.ConsensusState().GetState().TxIndexer)
2017-04-13 11:18:35 -07:00
}
func TestJSONTx(t *testing.T) {
2017-04-13 13:26:07 -07:00
testTx(t, GetJSONClient(), true)
2017-04-13 11:18:35 -07:00
core.SetTxIndexer(&null.TxIndex{})
2017-04-13 13:26:07 -07:00
testTx(t, GetJSONClient(), false)
core.SetTxIndexer(node.ConsensusState().GetState().TxIndexer)
2017-04-13 13:26:07 -07:00
}
func testTx(t *testing.T, client rpc.HTTPClient, withIndexer bool) {
2017-04-13 11:43:16 -07:00
assert, require := assert.New(t), require.New(t)
2017-04-13 11:18:35 -07:00
// first we broadcast a tx
tmResult := new(ctypes.TMResult)
2017-04-13 13:04:20 -07:00
txBytes := randBytes(t)
tx := types.Tx(txBytes)
_, err := client.Call("broadcast_tx_commit", map[string]interface{}{"tx": txBytes}, tmResult)
2017-04-13 11:18:35 -07:00
require.Nil(err)
res := (*tmResult).(*ctypes.ResultBroadcastTxCommit)
checkTx := res.CheckTx
require.Equal(abci.CodeType_OK, checkTx.Code)
deliverTx := res.DeliverTx
require.Equal(abci.CodeType_OK, deliverTx.Code)
mem := node.MempoolReactor().Mempool
require.Equal(0, mem.Size())
txHash := tx.Hash()
txHash2 := types.Tx("a different tx").Hash()
2017-04-13 11:43:16 -07:00
cases := []struct {
valid bool
hash []byte
prove bool
2017-04-13 11:43:16 -07:00
}{
// only valid if correct hash provided
{true, txHash, false},
{true, txHash, true},
{false, txHash2, false},
{false, txHash2, true},
{false, nil, false},
{false, nil, true},
2017-04-13 11:43:16 -07:00
}
for i, tc := range cases {
idx := fmt.Sprintf("%d", i)
2017-04-13 11:43:16 -07:00
// now we query for the tx.
// since there's only one tx, we know index=0.
tmResult = new(ctypes.TMResult)
query := map[string]interface{}{
"hash": tc.hash,
"prove": tc.prove,
2017-04-13 11:43:16 -07:00
}
_, err = client.Call("tx", query, tmResult)
valid := (withIndexer && tc.valid)
2017-04-13 13:26:07 -07:00
if !valid {
require.NotNil(err, idx)
2017-04-13 11:43:16 -07:00
} else {
require.Nil(err, idx)
2017-04-13 11:43:16 -07:00
res2 := (*tmResult).(*ctypes.ResultTx)
assert.Equal(tx, res2.Tx, idx)
assert.Equal(res.Height, res2.Height, idx)
assert.Equal(0, res2.Index, idx)
2017-04-13 13:04:20 -07:00
assert.Equal(abci.CodeType_OK, res2.TxResult.Code, idx)
2017-04-13 11:43:16 -07:00
// time to verify the proof
proof := res2.Proof
if tc.prove && assert.Equal(tx, proof.Data, idx) {
assert.True(proof.Proof.Verify(proof.Index, proof.Total, tx.Hash(), proof.RootHash), idx)
2017-04-13 11:43:16 -07:00
}
}
}
2017-04-13 11:18:35 -07:00
}
2016-01-10 13:33:52 -08:00
//--------------------------------------------------------------------------------
// Test the websocket service
var wsTyp = "JSONRPC"
// make a simple connection to the server
func TestWSConnect(t *testing.T) {
2017-02-21 10:36:18 -08:00
wsc := GetWSClient()
2016-01-13 18:20:25 -08:00
wsc.Stop()
2016-01-10 13:33:52 -08:00
}
// receive a new block message
func TestWSNewBlock(t *testing.T) {
2017-02-21 10:36:18 -08:00
wsc := GetWSClient()
2016-01-10 13:33:52 -08:00
eid := types.EventStringNewBlock()
2017-02-21 10:57:10 -08:00
require.Nil(t, wsc.Subscribe(eid))
2016-01-10 13:33:52 -08:00
defer func() {
2017-02-21 10:57:10 -08:00
require.Nil(t, wsc.Unsubscribe(eid))
2016-01-13 18:20:25 -08:00
wsc.Stop()
2016-01-10 13:33:52 -08:00
}()
2016-01-13 18:20:25 -08:00
waitForEvent(t, wsc, eid, true, func() {}, func(eid string, b interface{}) error {
2017-02-21 10:36:18 -08:00
// fmt.Println("Check:", b)
2016-01-10 13:33:52 -08:00
return nil
})
}
// receive a few new block messages in a row, with increasing height
func TestWSBlockchainGrowth(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
2017-02-21 10:36:18 -08:00
wsc := GetWSClient()
2016-01-10 13:33:52 -08:00
eid := types.EventStringNewBlock()
2017-02-21 10:57:10 -08:00
require.Nil(t, wsc.Subscribe(eid))
2016-01-10 13:33:52 -08:00
defer func() {
2017-02-21 10:57:10 -08:00
require.Nil(t, wsc.Unsubscribe(eid))
2016-01-13 18:20:25 -08:00
wsc.Stop()
2016-01-10 13:33:52 -08:00
}()
2016-01-13 18:20:25 -08:00
2016-01-10 13:33:52 -08:00
// listen for NewBlock, ensure height increases by 1
2016-01-13 18:20:25 -08:00
var initBlockN int
for i := 0; i < 3; i++ {
waitForEvent(t, wsc, eid, true, func() {}, func(eid string, eventData interface{}) error {
block := eventData.(types.EventDataNewBlock).Block
if i == 0 {
initBlockN = block.Header.Height
} else {
if block.Header.Height != initBlockN+i {
return fmt.Errorf("Expected block %d, got block %d", initBlockN+i, block.Header.Height)
}
}
return nil
})
}
2016-01-10 13:33:52 -08:00
}
2016-10-06 12:23:22 -07:00
func TestWSTxEvent(t *testing.T) {
2017-02-21 10:57:10 -08:00
require := require.New(t)
2017-02-21 10:36:18 -08:00
wsc := GetWSClient()
2017-02-21 10:57:10 -08:00
tx := randBytes(t)
2016-10-06 12:23:22 -07:00
// listen for the tx I am about to submit
eid := types.EventStringTx(types.Tx(tx))
2017-02-21 10:57:10 -08:00
require.Nil(wsc.Subscribe(eid))
2016-10-06 12:23:22 -07:00
defer func() {
2017-02-21 10:57:10 -08:00
require.Nil(wsc.Unsubscribe(eid))
2016-10-06 12:23:22 -07:00
wsc.Stop()
}()
// send an tx
tmResult := new(ctypes.TMResult)
_, err := GetJSONClient().Call("broadcast_tx_sync", map[string]interface{}{"tx": tx}, tmResult)
2017-02-21 10:57:10 -08:00
require.Nil(err)
2016-10-06 12:23:22 -07:00
waitForEvent(t, wsc, eid, true, func() {}, func(eid string, b interface{}) error {
evt, ok := b.(types.EventDataTx)
2017-02-21 10:57:10 -08:00
require.True(ok, "Got wrong event type: %#v", b)
require.Equal(tx, []byte(evt.Tx), "Returned different tx")
require.Equal(abci.CodeType_OK, evt.Code)
2016-10-06 12:23:22 -07:00
return nil
})
}
2016-01-10 13:33:52 -08:00
/* TODO: this with dummy app..
func TestWSDoubleFire(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode.")
}
con := newWSCon(t)
eid := types.EventStringAccInput(user[0].Address)
subscribe(t, con, eid)
defer func() {
unsubscribe(t, con, eid)
con.Close()
}()
amt := int64(100)
toAddr := user[1].Address
// broadcast the transaction, wait to hear about it
waitForEvent(t, con, eid, true, func() {
tx := makeDefaultSendTxSigned(t, wsTyp, toAddr, amt)
broadcastTx(t, wsTyp, tx)
}, func(eid string, b []byte) error {
return nil
})
// but make sure we don't hear about it twice
waitForEvent(t, con, eid, false, func() {
}, func(eid string, b []byte) error {
return nil
})
}*/
2016-05-11 20:33:09 -07:00
//--------------------------------------------------------------------------------
2017-04-12 18:23:58 -07:00
//TODO needs to be refactored so we don't use a mutable config but rather update specific values we're interested in
2016-05-11 20:33:09 -07:00
// unsafe_set_config
2017-04-12 18:23:58 -07:00
//var stringVal = "my string"
//var intVal = 987654321
//var boolVal = true
//
//// don't change these
//var testCasesUnsafeSetConfig = [][]string{
// []string{"string", "key1", stringVal},
// []string{"int", "key2", fmt.Sprintf("%v", intVal)},
// []string{"bool", "key3", fmt.Sprintf("%v", boolVal)},
//}
//
//func TestURIUnsafeSetConfig(t *testing.T) {
// for _, testCase := range testCasesUnsafeSetConfig {
// tmResult := new(ctypes.TMResult)
// _, err := GetURIClient().Call("unsafe_set_config", map[string]interface{}{
// "type": testCase[0],
// "key": testCase[1],
// "value": testCase[2],
// }, tmResult)
// require.Nil(t, err)
// }
// testUnsafeSetConfig(t)
//}
//
//func TestJSONUnsafeSetConfig(t *testing.T) {
// for _, testCase := range testCasesUnsafeSetConfig {
// tmResult := new(ctypes.TMResult)
// _, err := GetJSONClient().Call("unsafe_set_config",
// map[string]interface{}{"type": testCase[0], "key": testCase[1], "value": testCase[2]},
// tmResult)
// require.Nil(t, err)
// }
// testUnsafeSetConfig(t)
//}
//
//func testUnsafeSetConfig(t *testing.T) {
// require := require.New(t)
// s := config.GetString("key1")
// require.Equal(stringVal, s)
//
// i := config.GetInt("key2")
// require.Equal(intVal, i)
//
// b := config.GetBool("key3")
// require.Equal(boolVal, b)
//}