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.

266 lines
5.5 KiB

  1. package rpc
  2. import (
  3. "bytes"
  4. crand "crypto/rand"
  5. "math/rand"
  6. "net/http"
  7. "os/exec"
  8. "testing"
  9. "time"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/stretchr/testify/require"
  12. client "github.com/tendermint/go-rpc/client"
  13. server "github.com/tendermint/go-rpc/server"
  14. types "github.com/tendermint/go-rpc/types"
  15. wire "github.com/tendermint/go-wire"
  16. )
  17. // Client and Server should work over tcp or unix sockets
  18. const (
  19. tcpAddr = "tcp://0.0.0.0:46657"
  20. unixSocket = "/tmp/go-rpc.sock"
  21. unixAddr = "unix:///tmp/go-rpc.sock"
  22. websocketEndpoint = "/websocket/endpoint"
  23. )
  24. // Define a type for results and register concrete versions
  25. type Result interface{}
  26. type ResultStatus struct {
  27. Value string
  28. }
  29. type ResultBytes struct {
  30. Value []byte
  31. }
  32. var _ = wire.RegisterInterface(
  33. struct{ Result }{},
  34. wire.ConcreteType{&ResultStatus{}, 0x1},
  35. wire.ConcreteType{&ResultBytes{}, 0x2},
  36. )
  37. // Define some routes
  38. var Routes = map[string]*server.RPCFunc{
  39. "status": server.NewRPCFunc(StatusResult, "arg"),
  40. "status_ws": server.NewWSRPCFunc(StatusWSResult, "arg"),
  41. "bytes": server.NewRPCFunc(BytesResult, "arg"),
  42. }
  43. // an rpc function
  44. func StatusResult(v string) (Result, error) {
  45. return &ResultStatus{v}, nil
  46. }
  47. func StatusWSResult(wsCtx types.WSRPCContext, v string) (Result, error) {
  48. return &ResultStatus{v}, nil
  49. }
  50. func BytesResult(v []byte) (Result, error) {
  51. return &ResultBytes{v}, nil
  52. }
  53. // launch unix and tcp servers
  54. func init() {
  55. cmd := exec.Command("rm", "-f", unixSocket)
  56. err := cmd.Start()
  57. if err != nil {
  58. panic(err)
  59. }
  60. err = cmd.Wait()
  61. mux := http.NewServeMux()
  62. server.RegisterRPCFuncs(mux, Routes)
  63. wm := server.NewWebsocketManager(Routes, nil)
  64. mux.HandleFunc(websocketEndpoint, wm.WebsocketHandler)
  65. go func() {
  66. _, err := server.StartHTTPServer(tcpAddr, mux)
  67. if err != nil {
  68. panic(err)
  69. }
  70. }()
  71. mux2 := http.NewServeMux()
  72. server.RegisterRPCFuncs(mux2, Routes)
  73. wm = server.NewWebsocketManager(Routes, nil)
  74. mux2.HandleFunc(websocketEndpoint, wm.WebsocketHandler)
  75. go func() {
  76. _, err := server.StartHTTPServer(unixAddr, mux2)
  77. if err != nil {
  78. panic(err)
  79. }
  80. }()
  81. // wait for servers to start
  82. time.Sleep(time.Second * 2)
  83. }
  84. func testURI(t *testing.T, cl *client.URIClient) {
  85. val := "acbd"
  86. params := map[string]interface{}{
  87. "arg": val,
  88. }
  89. var result Result
  90. _, err := cl.Call("status", params, &result)
  91. require.Nil(t, err)
  92. got := result.(*ResultStatus).Value
  93. assert.Equal(t, got, val)
  94. }
  95. func testJSONRPC(t *testing.T, cl *client.JSONRPCClient) {
  96. val := "acbd"
  97. params := map[string]interface{}{
  98. "arg": val,
  99. }
  100. var result Result
  101. _, err := cl.Call("status", params, &result)
  102. require.Nil(t, err)
  103. got := result.(*ResultStatus).Value
  104. assert.Equal(t, got, val)
  105. }
  106. func testWS(t *testing.T, cl *client.WSClient) {
  107. val := "acbd"
  108. params := map[string]interface{}{
  109. "arg": val,
  110. }
  111. err := cl.WriteJSON(types.RPCRequest{
  112. JSONRPC: "2.0",
  113. ID: "",
  114. Method: "status",
  115. Params: params,
  116. })
  117. require.Nil(t, err)
  118. select {
  119. case msg := <-cl.ResultsCh:
  120. result := new(Result)
  121. wire.ReadJSONPtr(result, msg, &err)
  122. require.Nil(t, err)
  123. got := (*result).(*ResultStatus).Value
  124. assert.Equal(t, got, val)
  125. case err := <-cl.ErrorsCh:
  126. t.Fatal(err)
  127. }
  128. }
  129. //-------------
  130. func TestURI_TCP(t *testing.T) {
  131. cl := client.NewURIClient(tcpAddr)
  132. testURI(t, cl)
  133. }
  134. func TestURI_UNIX(t *testing.T) {
  135. cl := client.NewURIClient(unixAddr)
  136. testURI(t, cl)
  137. }
  138. func TestJSONRPC_TCP(t *testing.T) {
  139. cl := client.NewJSONRPCClient(tcpAddr)
  140. testJSONRPC(t, cl)
  141. }
  142. func TestJSONRPC_UNIX(t *testing.T) {
  143. cl := client.NewJSONRPCClient(unixAddr)
  144. testJSONRPC(t, cl)
  145. }
  146. func TestWS_TCP(t *testing.T) {
  147. cl := client.NewWSClient(tcpAddr, websocketEndpoint)
  148. _, err := cl.Start()
  149. require.Nil(t, err)
  150. testWS(t, cl)
  151. }
  152. func TestWS_UNIX(t *testing.T) {
  153. cl := client.NewWSClient(unixAddr, websocketEndpoint)
  154. _, err := cl.Start()
  155. require.Nil(t, err)
  156. testWS(t, cl)
  157. }
  158. func TestHexStringArg(t *testing.T) {
  159. cl := client.NewURIClient(tcpAddr)
  160. // should NOT be handled as hex
  161. val := "0xabc"
  162. params := map[string]interface{}{
  163. "arg": val,
  164. }
  165. var result Result
  166. _, err := cl.Call("status", params, &result)
  167. require.Nil(t, err)
  168. got := result.(*ResultStatus).Value
  169. assert.Equal(t, got, val)
  170. }
  171. func TestQuotedStringArg(t *testing.T) {
  172. cl := client.NewURIClient(tcpAddr)
  173. // should NOT be unquoted
  174. val := "\"abc\""
  175. params := map[string]interface{}{
  176. "arg": val,
  177. }
  178. var result Result
  179. _, err := cl.Call("status", params, &result)
  180. require.Nil(t, err)
  181. got := result.(*ResultStatus).Value
  182. assert.Equal(t, got, val)
  183. }
  184. func randBytes(t *testing.T) []byte {
  185. n := rand.Intn(10) + 2
  186. buf := make([]byte, n)
  187. _, err := crand.Read(buf)
  188. require.Nil(t, err)
  189. return bytes.Replace(buf, []byte("="), []byte{100}, -1)
  190. }
  191. func TestByteSliceViaJSONRPC(t *testing.T) {
  192. cl := client.NewJSONRPCClient(unixAddr)
  193. val := randBytes(t)
  194. params := map[string]interface{}{
  195. "arg": val,
  196. }
  197. var result Result
  198. _, err := cl.Call("bytes", params, &result)
  199. require.Nil(t, err)
  200. got := result.(*ResultBytes).Value
  201. assert.Equal(t, got, val)
  202. }
  203. func TestWSNewWSRPCFunc(t *testing.T) {
  204. cl := client.NewWSClient(unixAddr, websocketEndpoint)
  205. _, err := cl.Start()
  206. require.Nil(t, err)
  207. defer cl.Stop()
  208. val := "acbd"
  209. params := map[string]interface{}{
  210. "arg": val,
  211. }
  212. err = cl.WriteJSON(types.RPCRequest{
  213. JSONRPC: "2.0",
  214. ID: "",
  215. Method: "status_ws",
  216. Params: params,
  217. })
  218. require.Nil(t, err)
  219. select {
  220. case msg := <-cl.ResultsCh:
  221. result := new(Result)
  222. wire.ReadJSONPtr(result, msg, &err)
  223. require.Nil(t, err)
  224. got := (*result).(*ResultStatus).Value
  225. assert.Equal(t, got, val)
  226. case err := <-cl.ErrorsCh:
  227. t.Fatal(err)
  228. }
  229. }