You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

402 lines
11 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. package rpctest
  2. import (
  3. "bytes"
  4. crand "crypto/rand"
  5. "fmt"
  6. "math/rand"
  7. "testing"
  8. "time"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/stretchr/testify/require"
  11. abci "github.com/tendermint/abci/types"
  12. . "github.com/tendermint/go-common"
  13. data "github.com/tendermint/go-data"
  14. rpc "github.com/tendermint/go-rpc/client"
  15. "github.com/tendermint/tendermint/rpc/core"
  16. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  17. "github.com/tendermint/tendermint/state/txindex/null"
  18. "github.com/tendermint/tendermint/types"
  19. )
  20. //--------------------------------------------------------------------------------
  21. // Test the HTTP client
  22. // These tests assume the dummy app
  23. //--------------------------------------------------------------------------------
  24. //--------------------------------------------------------------------------------
  25. // status
  26. func TestURIStatus(t *testing.T) {
  27. testStatus(t, GetURIClient())
  28. }
  29. func TestJSONStatus(t *testing.T) {
  30. testStatus(t, GetJSONClient())
  31. }
  32. func testStatus(t *testing.T, client rpc.HTTPClient) {
  33. chainID := GetConfig().GetString("chain_id")
  34. tmResult := new(ctypes.TMResult)
  35. _, err := client.Call("status", map[string]interface{}{}, tmResult)
  36. require.Nil(t, err)
  37. status := (*tmResult).(*ctypes.ResultStatus)
  38. assert.Equal(t, chainID, status.NodeInfo.Network)
  39. }
  40. //--------------------------------------------------------------------------------
  41. // broadcast tx sync
  42. // random bytes (excluding byte('='))
  43. func randBytes(t *testing.T) []byte {
  44. n := rand.Intn(10) + 2
  45. buf := make([]byte, n)
  46. _, err := crand.Read(buf)
  47. require.Nil(t, err)
  48. return bytes.Replace(buf, []byte("="), []byte{100}, -1)
  49. }
  50. func TestURIBroadcastTxSync(t *testing.T) {
  51. testBroadcastTxSync(t, GetURIClient())
  52. }
  53. func TestJSONBroadcastTxSync(t *testing.T) {
  54. testBroadcastTxSync(t, GetJSONClient())
  55. }
  56. func testBroadcastTxSync(t *testing.T, client rpc.HTTPClient) {
  57. config.Set("block_size", 0)
  58. defer config.Set("block_size", -1)
  59. tmResult := new(ctypes.TMResult)
  60. tx := randBytes(t)
  61. _, err := client.Call("broadcast_tx_sync", map[string]interface{}{"tx": tx}, tmResult)
  62. require.Nil(t, err)
  63. res := (*tmResult).(*ctypes.ResultBroadcastTx)
  64. require.Equal(t, abci.CodeType_OK, res.Code)
  65. mem := node.MempoolReactor().Mempool
  66. require.Equal(t, 1, mem.Size())
  67. txs := mem.Reap(1)
  68. require.EqualValues(t, tx, txs[0])
  69. mem.Flush()
  70. }
  71. //--------------------------------------------------------------------------------
  72. // query
  73. func testTxKV(t *testing.T) ([]byte, []byte, types.Tx) {
  74. k := randBytes(t)
  75. v := randBytes(t)
  76. return k, v, types.Tx(Fmt("%s=%s", k, v))
  77. }
  78. func sendTx(t *testing.T, client rpc.HTTPClient) ([]byte, []byte) {
  79. tmResult := new(ctypes.TMResult)
  80. k, v, tx := testTxKV(t)
  81. _, err := client.Call("broadcast_tx_commit", map[string]interface{}{"tx": tx}, tmResult)
  82. require.Nil(t, err)
  83. return k, v
  84. }
  85. func TestURIABCIQuery(t *testing.T) {
  86. testABCIQuery(t, GetURIClient())
  87. }
  88. func TestJSONABCIQuery(t *testing.T) {
  89. testABCIQuery(t, GetURIClient())
  90. }
  91. func testABCIQuery(t *testing.T, client rpc.HTTPClient) {
  92. k, _ := sendTx(t, client)
  93. time.Sleep(time.Millisecond * 100)
  94. tmResult := new(ctypes.TMResult)
  95. _, err := client.Call("abci_query",
  96. map[string]interface{}{"path": "", "data": k, "prove": false}, tmResult)
  97. require.Nil(t, err)
  98. require.EqualValues(t, 0, resQuery.Response.Code)
  99. // XXX: specific to value returned by the dummy
  100. require.NotEqual(t, 0, len(resQuery.Response.Value))
  101. }
  102. //--------------------------------------------------------------------------------
  103. // broadcast tx commit
  104. func TestURIBroadcastTxCommit(t *testing.T) {
  105. testBroadcastTxCommit(t, GetURIClient())
  106. }
  107. func TestJSONBroadcastTxCommit(t *testing.T) {
  108. testBroadcastTxCommit(t, GetJSONClient())
  109. }
  110. func testBroadcastTxCommit(t *testing.T, client rpc.HTTPClient) {
  111. require := require.New(t)
  112. tmResult := new(ctypes.TMResult)
  113. tx := randBytes(t)
  114. _, err := client.Call("broadcast_tx_commit", map[string]interface{}{"tx": tx}, tmResult)
  115. require.Nil(err)
  116. res := (*tmResult).(*ctypes.ResultBroadcastTxCommit)
  117. checkTx := res.CheckTx
  118. require.Equal(abci.CodeType_OK, checkTx.Code)
  119. deliverTx := res.DeliverTx
  120. require.Equal(abci.CodeType_OK, deliverTx.Code)
  121. mem := node.MempoolReactor().Mempool
  122. require.Equal(0, mem.Size())
  123. // TODO: find tx in block
  124. }
  125. //--------------------------------------------------------------------------------
  126. // query tx
  127. func TestURITx(t *testing.T) {
  128. testTx(t, GetURIClient(), true)
  129. core.SetTxIndexer(&null.TxIndex{})
  130. testTx(t, GetJSONClient(), false)
  131. core.SetTxIndexer(node.ConsensusState().GetState().TxIndexer)
  132. }
  133. func TestJSONTx(t *testing.T) {
  134. testTx(t, GetJSONClient(), true)
  135. core.SetTxIndexer(&null.TxIndex{})
  136. testTx(t, GetJSONClient(), false)
  137. core.SetTxIndexer(node.ConsensusState().GetState().TxIndexer)
  138. }
  139. func testTx(t *testing.T, client rpc.HTTPClient, withIndexer bool) {
  140. assert, require := assert.New(t), require.New(t)
  141. // first we broadcast a tx
  142. tmResult := new(ctypes.TMResult)
  143. txBytes := randBytes(t)
  144. tx := types.Tx(txBytes)
  145. _, err := client.Call("broadcast_tx_commit", map[string]interface{}{"tx": txBytes}, tmResult)
  146. require.Nil(err)
  147. res := (*tmResult).(*ctypes.ResultBroadcastTxCommit)
  148. checkTx := res.CheckTx
  149. require.Equal(abci.CodeType_OK, checkTx.Code)
  150. deliverTx := res.DeliverTx
  151. require.Equal(abci.CodeType_OK, deliverTx.Code)
  152. mem := node.MempoolReactor().Mempool
  153. require.Equal(0, mem.Size())
  154. txHash := tx.Hash()
  155. txHash2 := types.Tx("a different tx").Hash()
  156. cases := []struct {
  157. valid bool
  158. hash []byte
  159. prove bool
  160. }{
  161. // only valid if correct hash provided
  162. {true, txHash, false},
  163. {true, txHash, true},
  164. {false, txHash2, false},
  165. {false, txHash2, true},
  166. {false, nil, false},
  167. {false, nil, true},
  168. }
  169. for i, tc := range cases {
  170. idx := fmt.Sprintf("%d", i)
  171. // now we query for the tx.
  172. // since there's only one tx, we know index=0.
  173. tmResult = new(ctypes.TMResult)
  174. query := map[string]interface{}{
  175. "hash": tc.hash,
  176. "prove": tc.prove,
  177. }
  178. _, err = client.Call("tx", query, tmResult)
  179. valid := (withIndexer && tc.valid)
  180. if !valid {
  181. require.NotNil(err, idx)
  182. } else {
  183. require.Nil(err, idx)
  184. res2 := (*tmResult).(*ctypes.ResultTx)
  185. assert.Equal(tx, res2.Tx, idx)
  186. assert.Equal(res.Height, res2.Height, idx)
  187. assert.Equal(0, res2.Index, idx)
  188. assert.Equal(abci.CodeType_OK, res2.TxResult.Code, idx)
  189. // time to verify the proof
  190. proof := res2.Proof
  191. if tc.prove && assert.Equal(tx, proof.Data, idx) {
  192. assert.True(proof.Proof.Verify(proof.Index, proof.Total, tx.Hash(), proof.RootHash), idx)
  193. }
  194. }
  195. }
  196. }
  197. //--------------------------------------------------------------------------------
  198. // Test the websocket service
  199. var wsTyp = "JSONRPC"
  200. // make a simple connection to the server
  201. func TestWSConnect(t *testing.T) {
  202. wsc := GetWSClient()
  203. wsc.Stop()
  204. }
  205. // receive a new block message
  206. func TestWSNewBlock(t *testing.T) {
  207. wsc := GetWSClient()
  208. eid := types.EventStringNewBlock()
  209. require.Nil(t, wsc.Subscribe(eid))
  210. defer func() {
  211. require.Nil(t, wsc.Unsubscribe(eid))
  212. wsc.Stop()
  213. }()
  214. waitForEvent(t, wsc, eid, true, func() {}, func(eid string, b interface{}) error {
  215. // fmt.Println("Check:", b)
  216. return nil
  217. })
  218. }
  219. // receive a few new block messages in a row, with increasing height
  220. func TestWSBlockchainGrowth(t *testing.T) {
  221. if testing.Short() {
  222. t.Skip("skipping test in short mode.")
  223. }
  224. wsc := GetWSClient()
  225. eid := types.EventStringNewBlock()
  226. require.Nil(t, wsc.Subscribe(eid))
  227. defer func() {
  228. require.Nil(t, wsc.Unsubscribe(eid))
  229. wsc.Stop()
  230. }()
  231. // listen for NewBlock, ensure height increases by 1
  232. var initBlockN int
  233. for i := 0; i < 3; i++ {
  234. waitForEvent(t, wsc, eid, true, func() {}, func(eid string, eventData interface{}) error {
  235. block := eventData.(types.EventDataNewBlock).Block
  236. if i == 0 {
  237. initBlockN = block.Header.Height
  238. } else {
  239. if block.Header.Height != initBlockN+i {
  240. return fmt.Errorf("Expected block %d, got block %d", initBlockN+i, block.Header.Height)
  241. }
  242. }
  243. return nil
  244. })
  245. }
  246. }
  247. func TestWSTxEvent(t *testing.T) {
  248. require := require.New(t)
  249. wsc := GetWSClient()
  250. tx := randBytes(t)
  251. // listen for the tx I am about to submit
  252. eid := types.EventStringTx(types.Tx(tx))
  253. require.Nil(wsc.Subscribe(eid))
  254. defer func() {
  255. require.Nil(wsc.Unsubscribe(eid))
  256. wsc.Stop()
  257. }()
  258. // send an tx
  259. tmResult := new(ctypes.TMResult)
  260. _, err := GetJSONClient().Call("broadcast_tx_sync", map[string]interface{}{"tx": tx}, tmResult)
  261. require.Nil(err)
  262. waitForEvent(t, wsc, eid, true, func() {}, func(eid string, b interface{}) error {
  263. evt, ok := b.(types.EventDataTx)
  264. require.True(ok, "Got wrong event type: %#v", b)
  265. require.Equal(tx, []byte(evt.Tx), "Returned different tx")
  266. require.Equal(abci.CodeType_OK, evt.Code)
  267. return nil
  268. })
  269. }
  270. /* TODO: this with dummy app..
  271. func TestWSDoubleFire(t *testing.T) {
  272. if testing.Short() {
  273. t.Skip("skipping test in short mode.")
  274. }
  275. con := newWSCon(t)
  276. eid := types.EventStringAccInput(user[0].Address)
  277. subscribe(t, con, eid)
  278. defer func() {
  279. unsubscribe(t, con, eid)
  280. con.Close()
  281. }()
  282. amt := int64(100)
  283. toAddr := user[1].Address
  284. // broadcast the transaction, wait to hear about it
  285. waitForEvent(t, con, eid, true, func() {
  286. tx := makeDefaultSendTxSigned(t, wsTyp, toAddr, amt)
  287. broadcastTx(t, wsTyp, tx)
  288. }, func(eid string, b []byte) error {
  289. return nil
  290. })
  291. // but make sure we don't hear about it twice
  292. waitForEvent(t, con, eid, false, func() {
  293. }, func(eid string, b []byte) error {
  294. return nil
  295. })
  296. }*/
  297. //--------------------------------------------------------------------------------
  298. // unsafe_set_config
  299. var stringVal = "my string"
  300. var intVal = 987654321
  301. var boolVal = true
  302. // don't change these
  303. var testCasesUnsafeSetConfig = [][]string{
  304. []string{"string", "key1", stringVal},
  305. []string{"int", "key2", fmt.Sprintf("%v", intVal)},
  306. []string{"bool", "key3", fmt.Sprintf("%v", boolVal)},
  307. }
  308. func TestURIUnsafeSetConfig(t *testing.T) {
  309. for _, testCase := range testCasesUnsafeSetConfig {
  310. tmResult := new(ctypes.TMResult)
  311. _, err := GetURIClient().Call("unsafe_set_config", map[string]interface{}{
  312. "type": testCase[0],
  313. "key": testCase[1],
  314. "value": testCase[2],
  315. }, tmResult)
  316. require.Nil(t, err)
  317. }
  318. testUnsafeSetConfig(t)
  319. }
  320. func TestJSONUnsafeSetConfig(t *testing.T) {
  321. for _, testCase := range testCasesUnsafeSetConfig {
  322. tmResult := new(ctypes.TMResult)
  323. _, err := GetJSONClient().Call("unsafe_set_config",
  324. map[string]interface{}{"type": testCase[0], "key": testCase[1], "value": testCase[2]},
  325. tmResult)
  326. require.Nil(t, err)
  327. }
  328. testUnsafeSetConfig(t)
  329. }
  330. func testUnsafeSetConfig(t *testing.T) {
  331. require := require.New(t)
  332. s := config.GetString("key1")
  333. require.Equal(stringVal, s)
  334. i := config.GetInt("key2")
  335. require.Equal(intVal, i)
  336. b := config.GetBool("key3")
  337. require.Equal(boolVal, b)
  338. }