From 5e57be076e6338829a7ec89ea182a77c8ba2dc77 Mon Sep 17 00:00:00 2001 From: Facundo Medica <14063057+facundomedica@users.noreply.github.com> Date: Mon, 6 Feb 2023 10:29:18 -0300 Subject: [PATCH] test: use a queue of open ports for tests (#14893) Co-authored-by: Marko --- testutil/network/network.go | 64 +++++++++++++++++++++---------- testutil/network/util.go | 9 ++--- x/genutil/client/cli/init_test.go | 3 +- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/testutil/network/network.go b/testutil/network/network.go index 9b729707cc..922078ce3d 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -59,7 +59,30 @@ import ( ) // package-wide network lock to only allow one test network at a time -var lock = new(sync.Mutex) +var ( + lock = new(sync.Mutex) + portPool = make(chan string, 200) +) + +func init() { + closeFns := []func() error{} + for i := 0; i < 200; i++ { + _, port, closeFn, err := FreeTCPAddr() + if err != nil { + panic(err) + } + + portPool <- port + closeFns = append(closeFns, closeFn) + } + + for _, closeFn := range closeFns { + err := closeFn() + if err != nil { + panic(err) + } + } +} // AppConstructor defines a function which accepts a network configuration and // creates an ABCI Application to provide to Tendermint. @@ -342,11 +365,11 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { if cfg.APIAddress != "" { apiListenAddr = cfg.APIAddress } else { - var err error - apiListenAddr, _, err = FreeTCPAddr() - if err != nil { - return nil, err + if len(portPool) == 0 { + return nil, fmt.Errorf("failed to get port for API server") } + port := <-portPool + apiListenAddr = fmt.Sprintf("tcp://0.0.0.0:%s", port) } appCfg.API.Address = apiListenAddr @@ -359,21 +382,21 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { if cfg.RPCAddress != "" { tmCfg.RPC.ListenAddress = cfg.RPCAddress } else { - rpcAddr, _, err := FreeTCPAddr() - if err != nil { - return nil, err + if len(portPool) == 0 { + return nil, fmt.Errorf("failed to get port for RPC server") } - tmCfg.RPC.ListenAddress = rpcAddr + port := <-portPool + tmCfg.RPC.ListenAddress = fmt.Sprintf("tcp://0.0.0.0:%s", port) } if cfg.GRPCAddress != "" { appCfg.GRPC.Address = cfg.GRPCAddress } else { - _, grpcPort, err := FreeTCPAddr() - if err != nil { - return nil, err + if len(portPool) == 0 { + return nil, fmt.Errorf("failed to get port for GRPC server") } - appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort) + port := <-portPool + appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", port) } appCfg.GRPC.Enable = true appCfg.GRPCWeb.Enable = true @@ -405,17 +428,18 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) { tmCfg.Moniker = nodeDirName monikers[i] = nodeDirName - proxyAddr, _, err := FreeTCPAddr() - if err != nil { - return nil, err + if len(portPool) == 0 { + return nil, fmt.Errorf("failed to get port for Proxy server") } + port := <-portPool + proxyAddr := fmt.Sprintf("tcp://0.0.0.0:%s", port) tmCfg.ProxyApp = proxyAddr - p2pAddr, _, err := FreeTCPAddr() - if err != nil { - return nil, err + if len(portPool) == 0 { + return nil, fmt.Errorf("failed to get port for Proxy server") } - + port = <-portPool + p2pAddr := fmt.Sprintf("tcp://0.0.0.0:%s", port) tmCfg.P2P.ListenAddress = p2pAddr tmCfg.P2P.AddrBookStrict = false tmCfg.P2P.AllowDuplicateIP = true diff --git a/testutil/network/util.go b/testutil/network/util.go index 6f6588e6dd..70cc8cc0b4 100644 --- a/testutil/network/util.go +++ b/testutil/network/util.go @@ -8,7 +8,6 @@ import ( "path/filepath" "time" - sdkerrors "cosmossdk.io/errors" "github.com/cometbft/cometbft/node" "github.com/cometbft/cometbft/p2p" pvm "github.com/cometbft/cometbft/privval" @@ -201,14 +200,14 @@ func writeFile(name string, dir string, contents []byte) error { // Get a free address for a test tendermint server // protocol is either tcp, http, etc -func FreeTCPAddr() (addr, port string, err error) { +func FreeTCPAddr() (addr, port string, closeFn func() error, err error) { l, err := net.Listen("tcp", "localhost:0") if err != nil { - return "", "", err + return "", "", nil, err } - if err := l.Close(); err != nil { - return "", "", sdkerrors.Wrap(err, "couldn't close the listener") + closeFn = func() error { + return l.Close() } portI := l.Addr().(*net.TCPAddr).Port diff --git a/x/genutil/client/cli/init_test.go b/x/genutil/client/cli/init_test.go index 1340630720..a648b55388 100644 --- a/x/genutil/client/cli/init_test.go +++ b/x/genutil/client/cli/init_test.go @@ -209,8 +209,9 @@ func TestStartStandAlone(t *testing.T) { app, err := mock.NewApp(home, logger) require.NoError(t, err) - svrAddr, _, err := network.FreeTCPAddr() + svrAddr, _, closeFn, err := network.FreeTCPAddr() require.NoError(t, err) + require.NoError(t, closeFn()) svr, err := abci_server.NewServer(svrAddr, "socket", app) require.NoError(t, err, "error creating listener")