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