github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/rpc/test/helpers.go (about) 1 package rpctest 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strings" 9 "time" 10 11 abci "github.com/tendermint/tendermint/abci/types" 12 "github.com/tendermint/tendermint/libs/log" 13 14 cfg "github.com/tendermint/tendermint/config" 15 tmnet "github.com/tendermint/tendermint/libs/net" 16 nm "github.com/tendermint/tendermint/node" 17 "github.com/tendermint/tendermint/p2p" 18 "github.com/tendermint/tendermint/privval" 19 "github.com/tendermint/tendermint/proxy" 20 ctypes "github.com/tendermint/tendermint/rpc/core/types" 21 core_grpc "github.com/tendermint/tendermint/rpc/grpc" 22 rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client" 23 ) 24 25 // Options helps with specifying some parameters for our RPC testing for greater 26 // control. 27 type Options struct { 28 suppressStdout bool 29 recreateConfig bool 30 } 31 32 var globalConfig *cfg.Config 33 var defaultOptions = Options{ 34 suppressStdout: false, 35 recreateConfig: false, 36 } 37 38 func waitForRPC() { 39 laddr := GetConfig().RPC.ListenAddress 40 client, err := rpcclient.New(laddr) 41 if err != nil { 42 panic(err) 43 } 44 result := new(ctypes.ResultStatus) 45 for { 46 _, err := client.Call("status", map[string]interface{}{}, result) 47 if err == nil { 48 return 49 } 50 51 fmt.Println("error", err) 52 time.Sleep(time.Millisecond) 53 } 54 } 55 56 func waitForGRPC() { 57 client := GetGRPCClient() 58 for { 59 _, err := client.Ping(context.Background(), &core_grpc.RequestPing{}) 60 if err == nil { 61 return 62 } 63 } 64 } 65 66 // f**ing long, but unique for each test 67 func makePathname() string { 68 // get path 69 p, err := os.Getwd() 70 if err != nil { 71 panic(err) 72 } 73 // fmt.Println(p) 74 sep := string(filepath.Separator) 75 return strings.Replace(p, sep, "_", -1) 76 } 77 78 func randPort() int { 79 port, err := tmnet.GetFreePort() 80 if err != nil { 81 panic(err) 82 } 83 return port 84 } 85 86 func makeAddrs() (string, string, string) { 87 return fmt.Sprintf("tcp://127.0.0.1:%d", randPort()), 88 fmt.Sprintf("tcp://127.0.0.1:%d", randPort()), 89 fmt.Sprintf("tcp://127.0.0.1:%d", randPort()) 90 } 91 92 func createConfig() *cfg.Config { 93 pathname := makePathname() 94 c := cfg.ResetTestRoot(pathname) 95 96 // and we use random ports to run in parallel 97 tm, rpc, grpc := makeAddrs() 98 c.P2P.ListenAddress = tm 99 c.RPC.ListenAddress = rpc 100 c.RPC.CORSAllowedOrigins = []string{"https://tendermint.com/"} 101 c.RPC.GRPCListenAddress = grpc 102 return c 103 } 104 105 // GetConfig returns a config for the test cases as a singleton 106 func GetConfig(forceCreate ...bool) *cfg.Config { 107 if globalConfig == nil || (len(forceCreate) > 0 && forceCreate[0]) { 108 globalConfig = createConfig() 109 } 110 return globalConfig 111 } 112 113 func GetGRPCClient() core_grpc.BroadcastAPIClient { 114 grpcAddr := globalConfig.RPC.GRPCListenAddress 115 return core_grpc.StartGRPCClient(grpcAddr) 116 } 117 118 // StartTendermint starts a test tendermint server in a go routine and returns when it is initialized 119 func StartTendermint(app abci.Application, opts ...func(*Options)) *nm.Node { 120 nodeOpts := defaultOptions 121 for _, opt := range opts { 122 opt(&nodeOpts) 123 } 124 node := NewTendermint(app, &nodeOpts) 125 err := node.Start() 126 if err != nil { 127 panic(err) 128 } 129 130 // wait for rpc 131 waitForRPC() 132 waitForGRPC() 133 134 if !nodeOpts.suppressStdout { 135 fmt.Println("Tendermint running!") 136 } 137 138 return node 139 } 140 141 // StopTendermint stops a test tendermint server, waits until it's stopped and 142 // cleans up test/config files. 143 func StopTendermint(node *nm.Node) { 144 if err := node.Stop(); err != nil { 145 node.Logger.Error("Error when tryint to stop node", "err", err) 146 } 147 node.Wait() 148 os.RemoveAll(node.Config().RootDir) 149 } 150 151 // NewTendermint creates a new tendermint server and sleeps forever 152 func NewTendermint(app abci.Application, opts *Options) *nm.Node { 153 // Create & start node 154 config := GetConfig(opts.recreateConfig) 155 var logger log.Logger 156 if opts.suppressStdout { 157 logger = log.NewNopLogger() 158 } else { 159 logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) 160 logger = log.NewFilter(logger, log.AllowError()) 161 } 162 pvKeyFile := config.PrivValidatorKeyFile() 163 pvKeyStateFile := config.PrivValidatorStateFile() 164 pv := privval.LoadOrGenFilePV(pvKeyFile, pvKeyStateFile) 165 papp := proxy.NewLocalClientCreator(app) 166 nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) 167 if err != nil { 168 panic(err) 169 } 170 node, err := nm.NewNode(config, pv, nodeKey, papp, 171 nm.DefaultGenesisDocProviderFunc(config), 172 nm.DefaultDBProvider, 173 nm.DefaultMetricsProvider(config.Instrumentation), 174 logger) 175 if err != nil { 176 panic(err) 177 } 178 return node 179 } 180 181 // SuppressStdout is an option that tries to make sure the RPC test Tendermint 182 // node doesn't log anything to stdout. 183 func SuppressStdout(o *Options) { 184 o.suppressStdout = true 185 } 186 187 // RecreateConfig instructs the RPC test to recreate the configuration each 188 // time, instead of treating it as a global singleton. 189 func RecreateConfig(o *Options) { 190 o.recreateConfig = true 191 }