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.

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