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.

371 lines
8.9 KiB

8 years ago
cleanup: Reduce and normalize import path aliasing. (#6975) The code in the Tendermint repository makes heavy use of import aliasing. This is made necessary by our extensive reuse of common base package names, and by repetition of similar names across different subdirectories. Unfortunately we have not been very consistent about which packages we alias in various circumstances, and the aliases we use vary. In the spirit of the advice in the style guide and https://github.com/golang/go/wiki/CodeReviewComments#imports, his change makes an effort to clean up and normalize import aliasing. This change makes no API or behavioral changes. It is a pure cleanup intended o help make the code more readable to developers (including myself) trying to understand what is being imported where. Only unexported names have been modified, and the changes were generated and applied mechanically with gofmt -r and comby, respecting the lexical and syntactic rules of Go. Even so, I did not fix every inconsistency. Where the changes would be too disruptive, I left it alone. The principles I followed in this cleanup are: - Remove aliases that restate the package name. - Remove aliases where the base package name is unambiguous. - Move overly-terse abbreviations from the import to the usage site. - Fix lexical issues (remove underscores, remove capitalization). - Fix import groupings to more closely match the style guide. - Group blank (side-effecting) imports and ensure they are commented. - Add aliases to multiple imports with the same base package name.
3 years ago
8 years ago
8 years ago
8 years ago
8 years ago
7 years ago
7 years ago
  1. package jsonrpc
  2. import (
  3. "bytes"
  4. "context"
  5. crand "crypto/rand"
  6. "encoding/json"
  7. "fmt"
  8. stdlog "log"
  9. mrand "math/rand"
  10. "net/http"
  11. "os"
  12. "os/exec"
  13. "testing"
  14. "time"
  15. "github.com/fortytw2/leaktest"
  16. "github.com/stretchr/testify/assert"
  17. "github.com/stretchr/testify/require"
  18. tmbytes "github.com/tendermint/tendermint/libs/bytes"
  19. "github.com/tendermint/tendermint/libs/log"
  20. "github.com/tendermint/tendermint/rpc/jsonrpc/client"
  21. "github.com/tendermint/tendermint/rpc/jsonrpc/server"
  22. )
  23. // Client and Server should work over tcp or unix sockets
  24. const (
  25. tcpAddr = "tcp://127.0.0.1:47768"
  26. unixSocket = "/tmp/rpc_test.sock"
  27. unixAddr = "unix://" + unixSocket
  28. websocketEndpoint = "/websocket/endpoint"
  29. testVal = "acbd"
  30. )
  31. type ResultEcho struct {
  32. Value string `json:"value"`
  33. }
  34. type ResultEchoInt struct {
  35. Value int `json:"value"`
  36. }
  37. type ResultEchoBytes struct {
  38. Value []byte `json:"value"`
  39. }
  40. type ResultEchoDataBytes struct {
  41. Value tmbytes.HexBytes `json:"value"`
  42. }
  43. // Define some routes
  44. var Routes = map[string]*server.RPCFunc{
  45. "echo": server.NewRPCFunc(EchoResult, "arg"),
  46. "echo_ws": server.NewWSRPCFunc(EchoWSResult, "arg"),
  47. "echo_bytes": server.NewRPCFunc(EchoBytesResult, "arg"),
  48. "echo_data_bytes": server.NewRPCFunc(EchoDataBytesResult, "arg"),
  49. "echo_int": server.NewRPCFunc(EchoIntResult, "arg"),
  50. }
  51. func EchoResult(ctx context.Context, v string) (*ResultEcho, error) {
  52. return &ResultEcho{v}, nil
  53. }
  54. func EchoWSResult(ctx context.Context, v string) (*ResultEcho, error) {
  55. return &ResultEcho{v}, nil
  56. }
  57. func EchoIntResult(ctx context.Context, v int) (*ResultEchoInt, error) {
  58. return &ResultEchoInt{v}, nil
  59. }
  60. func EchoBytesResult(ctx context.Context, v []byte) (*ResultEchoBytes, error) {
  61. return &ResultEchoBytes{v}, nil
  62. }
  63. func EchoDataBytesResult(ctx context.Context, v tmbytes.HexBytes) (*ResultEchoDataBytes, error) {
  64. return &ResultEchoDataBytes{v}, nil
  65. }
  66. func TestMain(m *testing.M) {
  67. ctx, cancel := context.WithCancel(context.Background())
  68. defer cancel()
  69. if err := setup(ctx); err != nil {
  70. stdlog.Fatal(err.Error())
  71. }
  72. code := m.Run()
  73. os.Exit(code)
  74. }
  75. // launch unix and tcp servers
  76. func setup(ctx context.Context) error {
  77. logger := log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo)
  78. cmd := exec.Command("rm", "-f", unixSocket)
  79. err := cmd.Start()
  80. if err != nil {
  81. return err
  82. }
  83. if err = cmd.Wait(); err != nil {
  84. return err
  85. }
  86. tcpLogger := logger.With("socket", "tcp")
  87. mux := http.NewServeMux()
  88. server.RegisterRPCFuncs(mux, Routes, tcpLogger)
  89. wm := server.NewWebsocketManager(tcpLogger, Routes, server.ReadWait(5*time.Second), server.PingPeriod(1*time.Second))
  90. mux.HandleFunc(websocketEndpoint, wm.WebsocketHandler)
  91. config := server.DefaultConfig()
  92. listener1, err := server.Listen(tcpAddr, config.MaxOpenConnections)
  93. if err != nil {
  94. return err
  95. }
  96. go func() {
  97. if err := server.Serve(ctx, listener1, mux, tcpLogger, config); err != nil {
  98. panic(err)
  99. }
  100. }()
  101. unixLogger := logger.With("socket", "unix")
  102. mux2 := http.NewServeMux()
  103. server.RegisterRPCFuncs(mux2, Routes, unixLogger)
  104. wm = server.NewWebsocketManager(unixLogger, Routes)
  105. mux2.HandleFunc(websocketEndpoint, wm.WebsocketHandler)
  106. listener2, err := server.Listen(unixAddr, config.MaxOpenConnections)
  107. if err != nil {
  108. return err
  109. }
  110. go func() {
  111. if err := server.Serve(ctx, listener2, mux2, unixLogger, config); err != nil {
  112. panic(err)
  113. }
  114. }()
  115. // wait for servers to start
  116. time.Sleep(time.Second * 2)
  117. return nil
  118. }
  119. func echoViaHTTP(ctx context.Context, cl client.Caller, val string) (string, error) {
  120. params := map[string]interface{}{
  121. "arg": val,
  122. }
  123. result := new(ResultEcho)
  124. if err := cl.Call(ctx, "echo", params, result); err != nil {
  125. return "", err
  126. }
  127. return result.Value, nil
  128. }
  129. func echoIntViaHTTP(ctx context.Context, cl client.Caller, val int) (int, error) {
  130. params := map[string]interface{}{
  131. "arg": val,
  132. }
  133. result := new(ResultEchoInt)
  134. if err := cl.Call(ctx, "echo_int", params, result); err != nil {
  135. return 0, err
  136. }
  137. return result.Value, nil
  138. }
  139. func echoBytesViaHTTP(ctx context.Context, cl client.Caller, bytes []byte) ([]byte, error) {
  140. params := map[string]interface{}{
  141. "arg": bytes,
  142. }
  143. result := new(ResultEchoBytes)
  144. if err := cl.Call(ctx, "echo_bytes", params, result); err != nil {
  145. return []byte{}, err
  146. }
  147. return result.Value, nil
  148. }
  149. func echoDataBytesViaHTTP(ctx context.Context, cl client.Caller, bytes tmbytes.HexBytes) (tmbytes.HexBytes, error) {
  150. params := map[string]interface{}{
  151. "arg": bytes,
  152. }
  153. result := new(ResultEchoDataBytes)
  154. if err := cl.Call(ctx, "echo_data_bytes", params, result); err != nil {
  155. return []byte{}, err
  156. }
  157. return result.Value, nil
  158. }
  159. func testWithHTTPClient(ctx context.Context, t *testing.T, cl client.Caller) {
  160. val := testVal
  161. got, err := echoViaHTTP(ctx, cl, val)
  162. require.NoError(t, err)
  163. assert.Equal(t, got, val)
  164. val2 := randBytes(t)
  165. got2, err := echoBytesViaHTTP(ctx, cl, val2)
  166. require.NoError(t, err)
  167. assert.Equal(t, got2, val2)
  168. val3 := tmbytes.HexBytes(randBytes(t))
  169. got3, err := echoDataBytesViaHTTP(ctx, cl, val3)
  170. require.NoError(t, err)
  171. assert.Equal(t, got3, val3)
  172. val4 := mrand.Intn(10000)
  173. got4, err := echoIntViaHTTP(ctx, cl, val4)
  174. require.NoError(t, err)
  175. assert.Equal(t, got4, val4)
  176. }
  177. func echoViaWS(ctx context.Context, cl *client.WSClient, val string) (string, error) {
  178. params := map[string]interface{}{
  179. "arg": val,
  180. }
  181. err := cl.Call(ctx, "echo", params)
  182. if err != nil {
  183. return "", err
  184. }
  185. msg := <-cl.ResponsesCh
  186. if msg.Error != nil {
  187. return "", err
  188. }
  189. result := new(ResultEcho)
  190. err = json.Unmarshal(msg.Result, result)
  191. if err != nil {
  192. return "", nil
  193. }
  194. return result.Value, nil
  195. }
  196. func echoBytesViaWS(ctx context.Context, cl *client.WSClient, bytes []byte) ([]byte, error) {
  197. params := map[string]interface{}{
  198. "arg": bytes,
  199. }
  200. err := cl.Call(ctx, "echo_bytes", params)
  201. if err != nil {
  202. return []byte{}, err
  203. }
  204. msg := <-cl.ResponsesCh
  205. if msg.Error != nil {
  206. return []byte{}, msg.Error
  207. }
  208. result := new(ResultEchoBytes)
  209. err = json.Unmarshal(msg.Result, result)
  210. if err != nil {
  211. return []byte{}, nil
  212. }
  213. return result.Value, nil
  214. }
  215. func testWithWSClient(ctx context.Context, t *testing.T, cl *client.WSClient) {
  216. val := testVal
  217. got, err := echoViaWS(ctx, cl, val)
  218. require.NoError(t, err)
  219. assert.Equal(t, got, val)
  220. val2 := randBytes(t)
  221. got2, err := echoBytesViaWS(ctx, cl, val2)
  222. require.NoError(t, err)
  223. assert.Equal(t, got2, val2)
  224. }
  225. //-------------
  226. func TestServersAndClientsBasic(t *testing.T) {
  227. // TODO: reenable the leak detector once the test fixture is
  228. // managed in the context of this test.
  229. //
  230. // t.Cleanup(leaktest.Check(t))
  231. bctx, bcancel := context.WithCancel(context.Background())
  232. defer bcancel()
  233. serverAddrs := [...]string{tcpAddr, unixAddr}
  234. for _, addr := range serverAddrs {
  235. t.Run(addr, func(t *testing.T) {
  236. ctx, cancel := context.WithCancel(bctx)
  237. defer cancel()
  238. logger := log.NewNopLogger()
  239. cl2, err := client.New(addr)
  240. require.NoError(t, err)
  241. fmt.Printf("=== testing server on %s using JSONRPC client", addr)
  242. testWithHTTPClient(ctx, t, cl2)
  243. opts := client.DefaultWSOptions()
  244. opts.SkipMetrics = true
  245. cl3, err := client.NewWSWithOptions(addr, websocketEndpoint, opts)
  246. require.NoError(t, err)
  247. cl3.Logger = logger
  248. err = cl3.Start(ctx)
  249. require.NoError(t, err)
  250. fmt.Printf("=== testing server on %s using WS client", addr)
  251. testWithWSClient(ctx, t, cl3)
  252. cancel()
  253. })
  254. }
  255. }
  256. func TestWSNewWSRPCFunc(t *testing.T) {
  257. t.Cleanup(leaktest.Check(t))
  258. ctx, cancel := context.WithCancel(context.Background())
  259. defer cancel()
  260. opts := client.DefaultWSOptions()
  261. opts.SkipMetrics = true
  262. cl, err := client.NewWSWithOptions(tcpAddr, websocketEndpoint, opts)
  263. require.NoError(t, err)
  264. cl.Logger = log.NewNopLogger()
  265. err = cl.Start(ctx)
  266. require.NoError(t, err)
  267. t.Cleanup(func() {
  268. if err := cl.Stop(); err != nil {
  269. t.Error(err)
  270. }
  271. })
  272. val := testVal
  273. params := map[string]interface{}{
  274. "arg": val,
  275. }
  276. err = cl.Call(ctx, "echo_ws", params)
  277. require.NoError(t, err)
  278. msg := <-cl.ResponsesCh
  279. if msg.Error != nil {
  280. t.Fatal(err)
  281. }
  282. result := new(ResultEcho)
  283. err = json.Unmarshal(msg.Result, result)
  284. require.NoError(t, err)
  285. got := result.Value
  286. assert.Equal(t, got, val)
  287. }
  288. // TestWSClientPingPong checks that a client & server exchange pings
  289. // & pongs so connection stays alive.
  290. func TestWSClientPingPong(t *testing.T) {
  291. t.Cleanup(leaktest.Check(t))
  292. ctx, cancel := context.WithCancel(context.Background())
  293. defer cancel()
  294. opts := client.DefaultWSOptions()
  295. opts.SkipMetrics = true
  296. cl, err := client.NewWSWithOptions(tcpAddr, websocketEndpoint, opts)
  297. require.NoError(t, err)
  298. cl.Logger = log.NewNopLogger()
  299. err = cl.Start(ctx)
  300. require.NoError(t, err)
  301. t.Cleanup(func() {
  302. if err := cl.Stop(); err != nil {
  303. t.Error(err)
  304. }
  305. })
  306. time.Sleep(6 * time.Second)
  307. }
  308. func randBytes(t *testing.T) []byte {
  309. n := mrand.Intn(10) + 2
  310. buf := make([]byte, n)
  311. _, err := crand.Read(buf)
  312. require.NoError(t, err)
  313. return bytes.ReplaceAll(buf, []byte("="), []byte{100})
  314. }