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.

178 lines
4.7 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
  1. package rpctest
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "math/rand"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "testing"
  10. "time"
  11. "github.com/stretchr/testify/require"
  12. "github.com/tendermint/tmlibs/log"
  13. abci "github.com/tendermint/abci/types"
  14. cfg "github.com/tendermint/tendermint/config"
  15. nm "github.com/tendermint/tendermint/node"
  16. "github.com/tendermint/tendermint/proxy"
  17. ctypes "github.com/tendermint/tendermint/rpc/core/types"
  18. core_grpc "github.com/tendermint/tendermint/rpc/grpc"
  19. client "github.com/tendermint/tendermint/rpc/lib/client"
  20. "github.com/tendermint/tendermint/types"
  21. )
  22. var config *cfg.Config
  23. // f**ing long, but unique for each test
  24. func makePathname() string {
  25. // get path
  26. p, err := os.Getwd()
  27. if err != nil {
  28. panic(err)
  29. }
  30. fmt.Println(p)
  31. sep := string(filepath.Separator)
  32. return strings.Replace(p, sep, "_", -1)
  33. }
  34. func randPort() int {
  35. // returns between base and base + spread
  36. base, spread := 20000, 20000
  37. return base + rand.Intn(spread)
  38. }
  39. func makeAddrs() (string, string, string) {
  40. start := randPort()
  41. return fmt.Sprintf("tcp://0.0.0.0:%d", start),
  42. fmt.Sprintf("tcp://0.0.0.0:%d", start+1),
  43. fmt.Sprintf("tcp://0.0.0.0:%d", start+2)
  44. }
  45. // GetConfig returns a config for the test cases as a singleton
  46. func GetConfig() *cfg.Config {
  47. if config == nil {
  48. pathname := makePathname()
  49. config = cfg.ResetTestRoot(pathname)
  50. // and we use random ports to run in parallel
  51. tm, rpc, grpc := makeAddrs()
  52. config.P2P.ListenAddress = tm
  53. config.RPCListenAddress = rpc
  54. config.GRPCListenAddress = grpc
  55. }
  56. return config
  57. }
  58. // GetURIClient gets a uri client pointing to the test tendermint rpc
  59. func GetURIClient() *client.URIClient {
  60. rpcAddr := GetConfig().RPCListenAddress
  61. return client.NewURIClient(rpcAddr)
  62. }
  63. // GetJSONClient gets a http/json client pointing to the test tendermint rpc
  64. func GetJSONClient() *client.JSONRPCClient {
  65. rpcAddr := GetConfig().RPCListenAddress
  66. return client.NewJSONRPCClient(rpcAddr)
  67. }
  68. func GetGRPCClient() core_grpc.BroadcastAPIClient {
  69. grpcAddr := config.GRPCListenAddress
  70. return core_grpc.StartGRPCClient(grpcAddr)
  71. }
  72. func GetWSClient() *client.WSClient {
  73. rpcAddr := GetConfig().RPCListenAddress
  74. wsc := client.NewWSClient(rpcAddr, "/websocket")
  75. if _, err := wsc.Start(); err != nil {
  76. panic(err)
  77. }
  78. return wsc
  79. }
  80. // StartTendermint starts a test tendermint server in a go routine and returns when it is initialized
  81. func StartTendermint(app abci.Application) *nm.Node {
  82. node := NewTendermint(app)
  83. node.Start()
  84. fmt.Println("Tendermint running!")
  85. return node
  86. }
  87. // NewTendermint creates a new tendermint server and sleeps forever
  88. func NewTendermint(app abci.Application) *nm.Node {
  89. // Create & start node
  90. config := GetConfig()
  91. logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
  92. logger = log.NewFilter(logger, log.AllowError())
  93. privValidatorFile := config.PrivValidatorFile()
  94. privValidator := types.LoadOrGenPrivValidator(privValidatorFile, logger)
  95. papp := proxy.NewLocalClientCreator(app)
  96. node := nm.NewNode(config, privValidator, papp, logger)
  97. return node
  98. }
  99. //--------------------------------------------------------------------------------
  100. // Utilities for testing the websocket service
  101. // wait for an event; do things that might trigger events, and check them when they are received
  102. // the check function takes an event id and the byte slice read off the ws
  103. func waitForEvent(t *testing.T, wsc *client.WSClient, eventid string, dieOnTimeout bool, f func(), check func(string, interface{}) error) {
  104. // go routine to wait for webscoket msg
  105. goodCh := make(chan interface{})
  106. errCh := make(chan error)
  107. // Read message
  108. go func() {
  109. var err error
  110. LOOP:
  111. for {
  112. select {
  113. case r := <-wsc.ResultsCh:
  114. result := new(ctypes.ResultEvent)
  115. err = json.Unmarshal(r, result)
  116. if err != nil {
  117. // cant distinguish between error and wrong type ...
  118. continue
  119. }
  120. if result.Name == eventid {
  121. goodCh <- result.Data
  122. break LOOP
  123. }
  124. case err := <-wsc.ErrorsCh:
  125. errCh <- err
  126. break LOOP
  127. case <-wsc.Quit:
  128. break LOOP
  129. }
  130. }
  131. }()
  132. // do stuff (transactions)
  133. f()
  134. // wait for an event or timeout
  135. timeout := time.NewTimer(10 * time.Second)
  136. select {
  137. case <-timeout.C:
  138. if dieOnTimeout {
  139. wsc.Stop()
  140. require.True(t, false, "%s event was not received in time", eventid)
  141. }
  142. // else that's great, we didn't hear the event
  143. // and we shouldn't have
  144. case eventData := <-goodCh:
  145. if dieOnTimeout {
  146. // message was received and expected
  147. // run the check
  148. require.Nil(t, check(eventid, eventData))
  149. } else {
  150. wsc.Stop()
  151. require.True(t, false, "%s event was not expected", eventid)
  152. }
  153. case err := <-errCh:
  154. panic(err) // Show the stack trace.
  155. }
  156. }
  157. //--------------------------------------------------------------------------------