mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
* Move GenesisDocProvider and DefaultGenesisDocProviderFunc GenesisDocProvider, being a provider of *types.GenesisDoc, makes sense to be part of the types package. DefaultGenesisDocProviderFunc, which relies on *config.Config to produce a types.GenesisDocProvider, makes sense being part of the config package. * Add aliases to avoid breaking node package API * Revert to original structure After discussion, it appears as though the best place for the relocated structures is still in the node package. This means that for the v0.31.6 release and into the future, there will be no changes two these two entities' APIs.
189 lines
4.6 KiB
Go
189 lines
4.6 KiB
Go
package rpctest
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
|
|
cfg "github.com/tendermint/tendermint/config"
|
|
cmn "github.com/tendermint/tendermint/libs/common"
|
|
nm "github.com/tendermint/tendermint/node"
|
|
"github.com/tendermint/tendermint/p2p"
|
|
"github.com/tendermint/tendermint/privval"
|
|
"github.com/tendermint/tendermint/proxy"
|
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
|
core_grpc "github.com/tendermint/tendermint/rpc/grpc"
|
|
rpcclient "github.com/tendermint/tendermint/rpc/lib/client"
|
|
)
|
|
|
|
// Options helps with specifying some parameters for our RPC testing for greater
|
|
// control.
|
|
type Options struct {
|
|
suppressStdout bool
|
|
recreateConfig bool
|
|
}
|
|
|
|
var globalConfig *cfg.Config
|
|
var defaultOptions = Options{
|
|
suppressStdout: false,
|
|
recreateConfig: false,
|
|
}
|
|
|
|
func waitForRPC() {
|
|
laddr := GetConfig().RPC.ListenAddress
|
|
client := rpcclient.NewJSONRPCClient(laddr)
|
|
ctypes.RegisterAmino(client.Codec())
|
|
result := new(ctypes.ResultStatus)
|
|
for {
|
|
_, err := client.Call("status", map[string]interface{}{}, result)
|
|
if err == nil {
|
|
return
|
|
} else {
|
|
fmt.Println("error", err)
|
|
time.Sleep(time.Millisecond)
|
|
}
|
|
}
|
|
}
|
|
|
|
func waitForGRPC() {
|
|
client := GetGRPCClient()
|
|
for {
|
|
_, err := client.Ping(context.Background(), &core_grpc.RequestPing{})
|
|
if err == nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// f**ing long, but unique for each test
|
|
func makePathname() string {
|
|
// get path
|
|
p, err := os.Getwd()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
// fmt.Println(p)
|
|
sep := string(filepath.Separator)
|
|
return strings.Replace(p, sep, "_", -1)
|
|
}
|
|
|
|
func randPort() int {
|
|
port, err := cmn.GetFreePort()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return port
|
|
}
|
|
|
|
func makeAddrs() (string, string, string) {
|
|
return fmt.Sprintf("tcp://0.0.0.0:%d", randPort()),
|
|
fmt.Sprintf("tcp://0.0.0.0:%d", randPort()),
|
|
fmt.Sprintf("tcp://0.0.0.0:%d", randPort())
|
|
}
|
|
|
|
func createConfig() *cfg.Config {
|
|
pathname := makePathname()
|
|
c := cfg.ResetTestRoot(pathname)
|
|
|
|
// and we use random ports to run in parallel
|
|
tm, rpc, grpc := makeAddrs()
|
|
c.P2P.ListenAddress = tm
|
|
c.RPC.ListenAddress = rpc
|
|
c.RPC.CORSAllowedOrigins = []string{"https://tendermint.com/"}
|
|
c.RPC.GRPCListenAddress = grpc
|
|
c.TxIndex.IndexTags = "app.creator,tx.height" // see kvstore application
|
|
return c
|
|
}
|
|
|
|
// GetConfig returns a config for the test cases as a singleton
|
|
func GetConfig(forceCreate ...bool) *cfg.Config {
|
|
if globalConfig == nil || (len(forceCreate) > 0 && forceCreate[0]) {
|
|
globalConfig = createConfig()
|
|
}
|
|
return globalConfig
|
|
}
|
|
|
|
func GetGRPCClient() core_grpc.BroadcastAPIClient {
|
|
grpcAddr := globalConfig.RPC.GRPCListenAddress
|
|
return core_grpc.StartGRPCClient(grpcAddr)
|
|
}
|
|
|
|
// StartTendermint starts a test tendermint server in a go routine and returns when it is initialized
|
|
func StartTendermint(app abci.Application, opts ...func(*Options)) *nm.Node {
|
|
nodeOpts := defaultOptions
|
|
for _, opt := range opts {
|
|
opt(&nodeOpts)
|
|
}
|
|
node := NewTendermint(app, &nodeOpts)
|
|
err := node.Start()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// wait for rpc
|
|
waitForRPC()
|
|
waitForGRPC()
|
|
|
|
if !nodeOpts.suppressStdout {
|
|
fmt.Println("Tendermint running!")
|
|
}
|
|
|
|
return node
|
|
}
|
|
|
|
// StopTendermint stops a test tendermint server, waits until it's stopped and
|
|
// cleans up test/config files.
|
|
func StopTendermint(node *nm.Node) {
|
|
node.Stop()
|
|
node.Wait()
|
|
os.RemoveAll(node.Config().RootDir)
|
|
}
|
|
|
|
// NewTendermint creates a new tendermint server and sleeps forever
|
|
func NewTendermint(app abci.Application, opts *Options) *nm.Node {
|
|
// Create & start node
|
|
config := GetConfig(opts.recreateConfig)
|
|
var logger log.Logger
|
|
if opts.suppressStdout {
|
|
logger = log.NewNopLogger()
|
|
} else {
|
|
logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
|
logger = log.NewFilter(logger, log.AllowError())
|
|
}
|
|
pvKeyFile := config.PrivValidatorKeyFile()
|
|
pvKeyStateFile := config.PrivValidatorStateFile()
|
|
pv := privval.LoadOrGenFilePV(pvKeyFile, pvKeyStateFile)
|
|
papp := proxy.NewLocalClientCreator(app)
|
|
nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
node, err := nm.NewNode(config, pv, nodeKey, papp,
|
|
nm.DefaultGenesisDocProviderFunc(config),
|
|
nm.DefaultDBProvider,
|
|
nm.DefaultMetricsProvider(config.Instrumentation),
|
|
logger)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return node
|
|
}
|
|
|
|
// SuppressStdout is an option that tries to make sure the RPC test Tendermint
|
|
// node doesn't log anything to stdout.
|
|
func SuppressStdout(o *Options) {
|
|
o.suppressStdout = true
|
|
}
|
|
|
|
// RecreateConfig instructs the RPC test to recreate the configuration each
|
|
// time, instead of treating it as a global singleton.
|
|
func RecreateConfig(o *Options) {
|
|
o.recreateConfig = true
|
|
}
|