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.

400 lines
10 KiB

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