github.com/okex/exchain@v1.8.0/libs/tendermint/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/okex/exchain/libs/tendermint/abci/types" 12 "github.com/okex/exchain/libs/tendermint/libs/log" 13 14 cfg "github.com/okex/exchain/libs/tendermint/config" 15 tmnet "github.com/okex/exchain/libs/tendermint/libs/net" 16 nm "github.com/okex/exchain/libs/tendermint/node" 17 "github.com/okex/exchain/libs/tendermint/p2p" 18 "github.com/okex/exchain/libs/tendermint/privval" 19 "github.com/okex/exchain/libs/tendermint/proxy" 20 ctypes "github.com/okex/exchain/libs/tendermint/rpc/core/types" 21 core_grpc "github.com/okex/exchain/libs/tendermint/rpc/grpc" 22 rpcclient "github.com/okex/exchain/libs/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 ctypes.RegisterAmino(client.Codec()) 45 result := new(ctypes.ResultStatus) 46 for { 47 _, err := client.Call("status", map[string]interface{}{}, result) 48 if err == nil { 49 return 50 } 51 52 fmt.Println("error", err) 53 time.Sleep(time.Millisecond) 54 } 55 } 56 57 func waitForGRPC() { 58 client := GetGRPCClient() 59 for { 60 _, err := client.Ping(context.Background(), &core_grpc.RequestPing{}) 61 if err == nil { 62 return 63 } 64 } 65 } 66 67 // f**ing long, but unique for each test 68 func makePathname() string { 69 // get path 70 p, err := os.Getwd() 71 if err != nil { 72 panic(err) 73 } 74 // fmt.Println(p) 75 sep := string(filepath.Separator) 76 return strings.Replace(p, sep, "_", -1) 77 } 78 79 func randPort() int { 80 port, err := tmnet.GetFreePort() 81 if err != nil { 82 panic(err) 83 } 84 return port 85 } 86 87 func makeAddrs() (string, string, string) { 88 return fmt.Sprintf("tcp://127.0.0.1:%d", randPort()), 89 fmt.Sprintf("tcp://127.0.0.1:%d", randPort()), 90 fmt.Sprintf("tcp://127.0.0.1:%d", randPort()) 91 } 92 93 func createConfig() *cfg.Config { 94 pathname := makePathname() 95 c := cfg.ResetTestRoot(pathname) 96 97 // and we use random ports to run in parallel 98 tm, rpc, grpc := makeAddrs() 99 c.P2P.ListenAddress = tm 100 c.RPC.ListenAddress = rpc 101 c.RPC.CORSAllowedOrigins = []string{"https://tendermint.com/"} 102 c.RPC.GRPCListenAddress = grpc 103 c.TxIndex.IndexKeys = "app.creator,tx.height" // see kvstore application 104 return c 105 } 106 107 // GetConfig returns a config for the test cases as a singleton 108 func GetConfig(forceCreate ...bool) *cfg.Config { 109 if globalConfig == nil || (len(forceCreate) > 0 && forceCreate[0]) { 110 globalConfig = createConfig() 111 } 112 return globalConfig 113 } 114 115 func GetGRPCClient() core_grpc.BroadcastAPIClient { 116 grpcAddr := globalConfig.RPC.GRPCListenAddress 117 return core_grpc.StartGRPCClient(grpcAddr) 118 } 119 120 // StartTendermint starts a test tendermint server in a go routine and returns when it is initialized 121 func StartTendermint(app abci.Application, opts ...func(*Options)) *nm.Node { 122 nodeOpts := defaultOptions 123 for _, opt := range opts { 124 opt(&nodeOpts) 125 } 126 node := NewTendermint(app, &nodeOpts) 127 err := node.Start() 128 if err != nil { 129 panic(err) 130 } 131 132 // wait for rpc 133 waitForRPC() 134 waitForGRPC() 135 136 if !nodeOpts.suppressStdout { 137 fmt.Println("Tendermint running!") 138 } 139 140 return node 141 } 142 143 // StopTendermint stops a test tendermint server, waits until it's stopped and 144 // cleans up test/config files. 145 func StopTendermint(node *nm.Node) { 146 node.Stop() 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 config.Instrumentation.Prometheus = false 171 node, err := nm.NewNode(config, pv, nodeKey, papp, 172 nm.DefaultGenesisDocProviderFunc(config), 173 nm.DefaultDBProvider, 174 nm.DefaultMetricsProvider(config.Instrumentation), 175 logger) 176 if err != nil { 177 panic(err) 178 } 179 return node 180 } 181 182 // SuppressStdout is an option that tries to make sure the RPC test Tendermint 183 // node doesn't log anything to stdout. 184 func SuppressStdout(o *Options) { 185 o.suppressStdout = true 186 } 187 188 // RecreateConfig instructs the RPC test to recreate the configuration each 189 // time, instead of treating it as a global singleton. 190 func RecreateConfig(o *Options) { 191 o.recreateConfig = true 192 }