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.

301 lines
8.4 KiB

  1. package rpc
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/gorilla/websocket"
  6. "github.com/tendermint/tendermint/account"
  7. "github.com/tendermint/tendermint/binary"
  8. "github.com/tendermint/tendermint/rpc"
  9. "github.com/tendermint/tendermint/types"
  10. "net/http"
  11. "testing"
  12. "time"
  13. )
  14. //--------------------------------------------------------------------------------
  15. // Utilities for testing the websocket service
  16. // create a new connection
  17. func newWSCon(t *testing.T) *websocket.Conn {
  18. dialer := websocket.DefaultDialer
  19. rHeader := http.Header{}
  20. con, r, err := dialer.Dial(websocketAddr, rHeader)
  21. fmt.Println("response", r)
  22. if err != nil {
  23. t.Fatal(err)
  24. }
  25. return con
  26. }
  27. // subscribe to an event
  28. func subscribe(t *testing.T, con *websocket.Conn, eventid string) {
  29. err := con.WriteJSON(rpc.WSRequest{
  30. Type: "subscribe",
  31. Event: eventid,
  32. })
  33. if err != nil {
  34. t.Fatal(err)
  35. }
  36. }
  37. // unsubscribe from an event
  38. func unsubscribe(t *testing.T, con *websocket.Conn, eventid string) {
  39. err := con.WriteJSON(rpc.WSRequest{
  40. Type: "unsubscribe",
  41. Event: eventid,
  42. })
  43. if err != nil {
  44. t.Fatal(err)
  45. }
  46. }
  47. // wait for an event; do things that might trigger events, and check them when they are received
  48. func waitForEvent(t *testing.T, con *websocket.Conn, eventid string, dieOnTimeout bool, f func(), check func(string, []byte) error) {
  49. // go routine to wait for webscoket msg
  50. gch := make(chan []byte) // good channel
  51. ech := make(chan error) // error channel
  52. go func() {
  53. for {
  54. _, p, err := con.ReadMessage()
  55. if err != nil {
  56. ech <- err
  57. break
  58. } else {
  59. // if the event id isnt what we're waiting on
  60. // ignore it
  61. var response struct {
  62. Event string `json:"event"`
  63. }
  64. if err := json.Unmarshal(p, &response); err != nil {
  65. ech <- err
  66. break
  67. }
  68. if response.Event == eventid {
  69. gch <- p
  70. break
  71. }
  72. }
  73. }
  74. }()
  75. // do stuff (transactions)
  76. f()
  77. // wait for an event or 10 seconds
  78. ticker := time.Tick(10 * time.Second)
  79. select {
  80. case <-ticker:
  81. if dieOnTimeout {
  82. con.Close()
  83. t.Fatalf("%s event was not received in time", eventid)
  84. }
  85. // else that's great, we didn't hear the event
  86. // and we shouldn't have
  87. case p := <-gch:
  88. if dieOnTimeout {
  89. // message was received and expected
  90. // run the check
  91. err := check(eventid, p)
  92. if err != nil {
  93. t.Fatal(err)
  94. }
  95. } else {
  96. con.Close()
  97. t.Fatalf("%s event was not expected", eventid)
  98. }
  99. case err := <-ech:
  100. t.Fatal(err)
  101. }
  102. }
  103. func unmarshalResponseNewBlock(b []byte) (*types.Block, error) {
  104. // unmarshall and assert somethings
  105. var response struct {
  106. Event string `json:"event"`
  107. Data *types.Block `json:"data"`
  108. Error string `json:"error"`
  109. }
  110. var err error
  111. binary.ReadJSON(&response, b, &err)
  112. if err != nil {
  113. return nil, err
  114. }
  115. if response.Error != "" {
  116. return nil, fmt.Errorf(response.Error)
  117. }
  118. block := response.Data
  119. return block, nil
  120. }
  121. //--------------------------------------------------------------------------------
  122. // Test the websocket service
  123. // make a simple connection to the server
  124. func TestWSConnect(t *testing.T) {
  125. con := newWSCon(t)
  126. con.Close()
  127. }
  128. // receive a new block message
  129. func _TestWSNewBlock(t *testing.T) {
  130. con := newWSCon(t)
  131. eid := types.EventStringNewBlock()
  132. subscribe(t, con, eid)
  133. defer func() {
  134. unsubscribe(t, con, eid)
  135. con.Close()
  136. }()
  137. waitForEvent(t, con, eid, true, func() {}, func(eid string, b []byte) error {
  138. fmt.Println("Check:", string(b))
  139. return nil
  140. })
  141. }
  142. // receive a few new block messages in a row, with increasing height
  143. func TestWSBlockchainGrowth(t *testing.T) {
  144. con := newWSCon(t)
  145. eid := types.EventStringNewBlock()
  146. subscribe(t, con, eid)
  147. defer func() {
  148. unsubscribe(t, con, eid)
  149. con.Close()
  150. }()
  151. // listen for NewBlock, ensure height increases by 1
  152. unmarshalValidateBlockchain(t, con, eid)
  153. }
  154. // send a transaction and validate the events from listening for both sender and receiver
  155. func TestWSSend(t *testing.T) {
  156. toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54}
  157. amt := uint64(100)
  158. con := newWSCon(t)
  159. eidInput := types.EventStringAccInput(userByteAddr)
  160. eidOutput := types.EventStringAccOutput(toAddr)
  161. subscribe(t, con, eidInput)
  162. subscribe(t, con, eidOutput)
  163. defer func() {
  164. unsubscribe(t, con, eidInput)
  165. unsubscribe(t, con, eidOutput)
  166. con.Close()
  167. }()
  168. waitForEvent(t, con, eidInput, true, func() {
  169. broadcastTx(t, "JSONRPC", userByteAddr, toAddr, nil, userBytePriv, amt, 0, 0)
  170. }, unmarshalValidateSend(amt, toAddr))
  171. waitForEvent(t, con, eidOutput, true, func() {}, unmarshalValidateSend(amt, toAddr))
  172. }
  173. // ensure events are only fired once for a given transaction
  174. func TestWSDoubleFire(t *testing.T) {
  175. con := newWSCon(t)
  176. eid := types.EventStringAccInput(userByteAddr)
  177. subscribe(t, con, eid)
  178. defer func() {
  179. unsubscribe(t, con, eid)
  180. con.Close()
  181. }()
  182. amt := uint64(100)
  183. toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54}
  184. // broadcast the transaction, wait to hear about it
  185. waitForEvent(t, con, eid, true, func() {
  186. broadcastTx(t, "JSONRPC", userByteAddr, toAddr, nil, userBytePriv, amt, 0, 0)
  187. }, func(eid string, b []byte) error {
  188. return nil
  189. })
  190. // but make sure we don't hear about it twice
  191. waitForEvent(t, con, eid, false, func() {
  192. }, func(eid string, b []byte) error {
  193. return nil
  194. })
  195. }
  196. // create a contract, wait for the event, and send it a msg, validate the return
  197. func TestWSCallWait(t *testing.T) {
  198. con := newWSCon(t)
  199. eid1 := types.EventStringAccInput(userByteAddr)
  200. subscribe(t, con, eid1)
  201. defer func() {
  202. unsubscribe(t, con, eid1)
  203. con.Close()
  204. }()
  205. amt := uint64(10000)
  206. code, returnCode, returnVal := simpleContract()
  207. var contractAddr []byte
  208. // wait for the contract to be created
  209. waitForEvent(t, con, eid1, true, func() {
  210. _, receipt := broadcastTx(t, "JSONRPC", userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
  211. contractAddr = receipt.ContractAddr
  212. }, unmarshalValidateCall(amt, returnCode))
  213. // susbscribe to the new contract
  214. amt = uint64(10001)
  215. eid2 := types.EventStringAccReceive(contractAddr)
  216. subscribe(t, con, eid2)
  217. defer func() {
  218. unsubscribe(t, con, eid2)
  219. }()
  220. // get the return value from a call
  221. data := []byte{0x1} // just needs to be non empty for this to be a CallTx
  222. waitForEvent(t, con, eid2, true, func() {
  223. broadcastTx(t, "JSONRPC", userByteAddr, contractAddr, data, userBytePriv, amt, 1000, 1000)
  224. }, unmarshalValidateCall(amt, returnVal))
  225. }
  226. // create a contract and send it a msg without waiting. wait for contract event
  227. // and validate return
  228. func TestWSCallNoWait(t *testing.T) {
  229. con := newWSCon(t)
  230. amt := uint64(10000)
  231. code, _, returnVal := simpleContract()
  232. _, receipt := broadcastTx(t, "JSONRPC", userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
  233. contractAddr := receipt.ContractAddr
  234. // susbscribe to the new contract
  235. amt = uint64(10001)
  236. eid := types.EventStringAccReceive(contractAddr)
  237. subscribe(t, con, eid)
  238. defer func() {
  239. unsubscribe(t, con, eid)
  240. con.Close()
  241. }()
  242. // get the return value from a call
  243. data := []byte{0x1} // just needs to be non empty for this to be a CallTx
  244. waitForEvent(t, con, eid, true, func() {
  245. broadcastTx(t, "JSONRPC", userByteAddr, contractAddr, data, userBytePriv, amt, 1000, 1000)
  246. }, unmarshalValidateCall(amt, returnVal))
  247. }
  248. // create two contracts, one of which calls the other
  249. func TestWSCallCall(t *testing.T) {
  250. con := newWSCon(t)
  251. amt := uint64(10000)
  252. code, _, returnVal := simpleContract()
  253. txid := new([]byte)
  254. // deploy the two contracts
  255. _, receipt := broadcastTx(t, "JSONRPC", userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
  256. contractAddr1 := receipt.ContractAddr
  257. code, _, _ = simpleCallContract(contractAddr1)
  258. _, receipt = broadcastTx(t, "JSONRPC", userByteAddr, nil, code, userBytePriv, amt, 1000, 1000)
  259. contractAddr2 := receipt.ContractAddr
  260. // susbscribe to the new contracts
  261. amt = uint64(10001)
  262. eid1 := types.EventStringAccReceive(contractAddr1)
  263. eid2 := types.EventStringAccReceive(contractAddr2)
  264. subscribe(t, con, eid1)
  265. subscribe(t, con, eid2)
  266. defer func() {
  267. unsubscribe(t, con, eid1)
  268. unsubscribe(t, con, eid2)
  269. con.Close()
  270. }()
  271. // call contract2, which should call contract1, and wait for ev1
  272. data := []byte{0x1} // just needs to be non empty for this to be a CallTx
  273. waitForEvent(t, con, eid1, true, func() {
  274. tx, _ := broadcastTx(t, "JSONRPC", userByteAddr, contractAddr2, data, userBytePriv, amt, 1000, 1000)
  275. *txid = account.HashSignBytes(tx)
  276. }, unmarshalValidateCallCall(userByteAddr, returnVal, txid))
  277. }