refactor(tests): testutil.Network as an interface (#18389)

Co-authored-by: Anmol <anmol1696@gmail.com>
This commit is contained in:
Marko
2023-11-08 18:38:57 +00:00
committed by GitHub
co-authored by Anmol
parent 8fbf6166f6
commit 03c3f8e71f
28 changed files with 959 additions and 863 deletions
+2 -2
View File
@@ -13,7 +13,7 @@ import (
// CheckTxCode verifies that the transaction result returns a specific code
// Takes a network, wait for two blocks and fetch the transaction from its hash
func CheckTxCode(network *network.Network, clientCtx client.Context, txHash string, expectedCode uint32) error {
func CheckTxCode(network network.NetworkI, clientCtx client.Context, txHash string, expectedCode uint32) error {
// wait for 2 blocks
for i := 0; i < 2; i++ {
if err := network.WaitForNextBlock(); err != nil {
@@ -41,7 +41,7 @@ func CheckTxCode(network *network.Network, clientCtx client.Context, txHash stri
// GetTxResponse returns queries the transaction response of a transaction from its hash
// Takes a network, wait for two blocks and fetch the transaction from its hash
func GetTxResponse(network *network.Network, clientCtx client.Context, txHash string) (sdk.TxResponse, error) {
func GetTxResponse(network network.NetworkI, clientCtx client.Context, txHash string) (sdk.TxResponse, error) {
// wait for 2 blocks
for i := 0; i < 2; i++ {
if err := network.WaitForNextBlock(); err != nil {
+44
View File
@@ -0,0 +1,44 @@
package network
import (
"time"
"github.com/cosmos/cosmos-sdk/client"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/server"
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// NetworkI is an interface for a network of validators.
// It is used to abstract over the different network types (in-process, docker, etc.).
// if used there is a requirement to expose query and tx client for the nodes
type NetworkI interface {
// GetValidators returns the validators in the network
GetValidators() []ValidatorI
// WaitForNextBlock waits for the network to reach the next block
WaitForNextBlock() error
// WaitForHeight waits for the network to reach the given height
WaitForHeight(height int64) (int64, error)
// WaitForHeightWithTimeout waits for the network to reach the given height or times out
WaitForHeightWithTimeout(int64, time.Duration) (int64, error)
// RetryForBlocks retries the given function until it returns no error or the given number of blocks has passed
RetryForBlocks(retryFunc func() error, blocks int) error
// LatestHeight returns the latest height of the network
LatestHeight() (int64, error)
Cleanup()
}
// ValidatorI expose a validator's context and configuration
type ValidatorI interface {
GetCtx() *server.Context
GetAppConfig() *srvconfig.Config
GetAddress() sdk.AccAddress
GetValAddress() sdk.ValAddress
GetClientCtx() client.Context
GetAPIAddress() string
GetRPCAddress() string
GetPubKey() cryptotypes.PubKey
GetMoniker() string
}
+24 -64
View File
@@ -6,7 +6,6 @@ import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"os"
"os/signal"
@@ -17,12 +16,8 @@ import (
"testing"
"time"
"github.com/cometbft/cometbft/node"
cmtclient "github.com/cometbft/cometbft/rpc/client"
dbm "github.com/cosmos/cosmos-db"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
"cosmossdk.io/core/address"
"cosmossdk.io/depinject"
@@ -51,7 +46,6 @@ import (
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/api"
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/testutil"
@@ -274,39 +268,6 @@ type (
Config Config
}
// Validator defines an in-process CometBFT validator node. Through this object,
// a client can make RPC and API calls and interact with any client command
// or handler.
Validator struct {
AppConfig *srvconfig.Config
ClientCtx client.Context
Ctx *server.Context
Dir string
NodeID string
PubKey cryptotypes.PubKey
Moniker string
APIAddress string
RPCAddress string
P2PAddress string
Address sdk.AccAddress
ValAddress sdk.ValAddress
RPCClient cmtclient.Client
app servertypes.Application
tmNode *node.Node
api *api.Server
grpc *grpc.Server
grpcWeb *http.Server
errGroup *errgroup.Group
cancelFn context.CancelFunc
}
// ValidatorI expose a validator's context and configuration
ValidatorI interface {
GetCtx() *server.Context
GetAppConfig() *srvconfig.Config
}
// Logger is a network logger interface that exposes testnet-level Log() methods for an in-process testing network
// This is not to be confused with logging that may happen at an individual node or validator level
Logger interface {
@@ -316,19 +277,10 @@ type (
)
var (
_ Logger = (*testing.T)(nil)
_ Logger = (*CLILogger)(nil)
_ ValidatorI = Validator{}
_ Logger = (*testing.T)(nil)
_ Logger = (*CLILogger)(nil)
)
func (v Validator) GetCtx() *server.Context {
return v.Ctx
}
func (v Validator) GetAppConfig() *srvconfig.Config {
return v.AppConfig
}
// CLILogger wraps a cobra.Command and provides command logging methods.
type CLILogger struct {
cmd *cobra.Command
@@ -350,7 +302,7 @@ func NewCLILogger(cmd *cobra.Command) CLILogger {
}
// New creates a new Network for integration tests or in-process testnets run via the CLI
func New(l Logger, baseDir string, cfg Config) (*Network, error) {
func New(l Logger, baseDir string, cfg Config) (NetworkI, error) {
// only one caller/test can create and use a network at a time
l.Log("acquiring test network lock")
lock.Lock()
@@ -612,17 +564,17 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) {
network.Validators[i] = &Validator{
AppConfig: appCfg,
ClientCtx: clientCtx,
Ctx: ctx,
Dir: filepath.Join(network.BaseDir, nodeDirName),
NodeID: nodeID,
PubKey: pubKey,
Moniker: nodeDirName,
RPCAddress: cmtCfg.RPC.ListenAddress,
P2PAddress: cmtCfg.P2P.ListenAddress,
APIAddress: apiAddr,
Address: addr,
ValAddress: sdk.ValAddress(addr),
clientCtx: clientCtx,
ctx: ctx,
dir: filepath.Join(network.BaseDir, nodeDirName),
nodeID: nodeID,
pubKey: pubKey,
moniker: nodeDirName,
rPCAddress: cmtCfg.RPC.ListenAddress,
p2PAddress: cmtCfg.P2P.ListenAddress,
aPIAddress: apiAddr,
address: addr,
valAddress: sdk.ValAddress(addr),
}
}
@@ -696,7 +648,7 @@ func (n *Network) LatestHeight() (int64, error) {
var latestHeight int64
val := n.Validators[0]
queryClient := cmtservice.NewServiceClient(val.ClientCtx)
queryClient := cmtservice.NewServiceClient(val.clientCtx)
for {
select {
@@ -730,6 +682,14 @@ func (n *Network) WaitForHeight(h int64) (int64, error) {
return n.WaitForHeightWithTimeout(h, 10*time.Second)
}
func (n *Network) GetValidators() []ValidatorI {
var vals []ValidatorI
for _, val := range n.Validators {
vals = append(vals, val)
}
return vals
}
// WaitForHeightWithTimeout is the same as WaitForHeight except the caller can
// provide a custom timeout.
func (n *Network) WaitForHeightWithTimeout(h int64, t time.Duration) (int64, error) {
@@ -745,7 +705,7 @@ func (n *Network) WaitForHeightWithTimeout(h int64, t time.Duration) (int64, err
var latestHeight int64
val := n.Validators[0]
queryClient := cmtservice.NewServiceClient(val.ClientCtx)
queryClient := cmtservice.NewServiceClient(val.clientCtx)
for {
select {
+19 -19
View File
@@ -31,8 +31,8 @@ import (
)
func startInProcess(cfg Config, val *Validator) error {
logger := val.Ctx.Logger
cmtCfg := val.Ctx.Config
logger := val.ctx.Logger
cmtCfg := val.ctx.Config
cmtCfg.Instrumentation.Prometheus = false
if err := val.AppConfig.ValidateBasic(); err != nil {
@@ -44,7 +44,7 @@ func startInProcess(cfg Config, val *Validator) error {
return err
}
app := cfg.AppConstructor(*val)
app := cfg.AppConstructor(val)
val.app = app
appGenesisProvider := func() (*cmttypes.GenesisDoc, error) {
@@ -65,7 +65,7 @@ func startInProcess(cfg Config, val *Validator) error {
appGenesisProvider,
cmtcfg.DefaultDBProvider,
node.DefaultMetricsProvider(cmtCfg.Instrumentation),
servercmtlog.CometLoggerWrapper{Logger: logger.With("module", val.Moniker)},
servercmtlog.CometLoggerWrapper{Logger: logger.With("module", val.moniker)},
)
if err != nil {
return err
@@ -76,18 +76,18 @@ func startInProcess(cfg Config, val *Validator) error {
}
val.tmNode = tmNode
if val.RPCAddress != "" {
val.RPCClient = local.New(tmNode)
if val.rPCAddress != "" {
val.rPCClient = local.New(tmNode)
}
// We'll need a RPC client if the validator exposes a gRPC or REST endpoint.
if val.APIAddress != "" || val.AppConfig.GRPC.Enable {
val.ClientCtx = val.ClientCtx.
WithClient(val.RPCClient)
if val.aPIAddress != "" || val.AppConfig.GRPC.Enable {
val.clientCtx = val.clientCtx.
WithClient(val.rPCClient)
app.RegisterTxService(val.ClientCtx)
app.RegisterTendermintService(val.ClientCtx)
app.RegisterNodeService(val.ClientCtx, *val.AppConfig)
app.RegisterTxService(val.clientCtx)
app.RegisterTendermintService(val.clientCtx)
app.RegisterNodeService(val.clientCtx, *val.AppConfig)
}
ctx := context.Background()
@@ -97,7 +97,7 @@ func startInProcess(cfg Config, val *Validator) error {
grpcCfg := val.AppConfig.GRPC
if grpcCfg.Enable {
grpcSrv, err := servergrpc.NewGRPCServer(val.ClientCtx, app, grpcCfg)
grpcSrv, err := servergrpc.NewGRPCServer(val.clientCtx, app, grpcCfg)
if err != nil {
return err
}
@@ -111,8 +111,8 @@ func startInProcess(cfg Config, val *Validator) error {
val.grpc = grpcSrv
}
if val.APIAddress != "" {
apiSrv := api.New(val.ClientCtx, logger.With(log.ModuleKey, "api-server"), val.grpc)
if val.aPIAddress != "" {
apiSrv := api.New(val.clientCtx, logger.With(log.ModuleKey, "api-server"), val.grpc)
app.RegisterAPIRoutes(apiSrv, val.AppConfig.API)
val.errGroup.Go(func() error {
@@ -132,15 +132,15 @@ func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error {
}
for i := 0; i < cfg.NumValidators; i++ {
cmtCfg := vals[i].Ctx.Config
cmtCfg := vals[i].ctx.Config
nodeDir := filepath.Join(outputDir, vals[i].Moniker, "simd")
nodeDir := filepath.Join(outputDir, vals[i].moniker, "simd")
gentxsDir := filepath.Join(outputDir, "gentxs")
cmtCfg.Moniker = vals[i].Moniker
cmtCfg.Moniker = vals[i].moniker
cmtCfg.SetRoot(nodeDir)
initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].NodeID, vals[i].PubKey)
initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].nodeID, vals[i].pubKey)
genFile := cmtCfg.GenesisFile()
appGenesis, err := genutiltypes.AppGenesisFromFile(genFile)
+84
View File
@@ -0,0 +1,84 @@
package network
import (
"context"
"net/http"
"github.com/cometbft/cometbft/node"
cmtclient "github.com/cometbft/cometbft/rpc/client"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
"github.com/cosmos/cosmos-sdk/client"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/server/api"
srvconfig "github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Validator defines an in-process CometBFT validator node. Through this object,
// a client can make RPC and API calls and interact with any client command
// or handler.
type Validator struct {
AppConfig *srvconfig.Config
clientCtx client.Context
ctx *server.Context
dir string
nodeID string
pubKey cryptotypes.PubKey
moniker string
aPIAddress string
rPCAddress string
p2PAddress string
address sdk.AccAddress
valAddress sdk.ValAddress
rPCClient cmtclient.Client
app servertypes.Application
tmNode *node.Node
api *api.Server
grpc *grpc.Server
grpcWeb *http.Server
errGroup *errgroup.Group
cancelFn context.CancelFunc
}
var _ ValidatorI = &Validator{}
func (v *Validator) GetCtx() *server.Context {
return v.ctx
}
func (v *Validator) GetClientCtx() client.Context {
return v.clientCtx
}
func (v *Validator) GetAppConfig() *srvconfig.Config {
return v.AppConfig
}
func (v *Validator) GetAddress() sdk.AccAddress {
return v.address
}
func (v *Validator) GetValAddress() sdk.ValAddress {
return v.valAddress
}
func (v *Validator) GetAPIAddress() string {
return v.aPIAddress
}
func (v *Validator) GetRPCAddress() string {
return v.rPCAddress
}
func (v *Validator) GetPubKey() cryptotypes.PubKey {
return v.pubKey
}
func (v *Validator) GetMoniker() string {
return v.moniker
}