test: use a queue of open ports for tests (#14893)

Co-authored-by: Marko <marbar3778@yahoo.com>
This commit is contained in:
Facundo Medica 2023-02-06 10:29:18 -03:00 committed by GitHub
parent ffde2b99da
commit 5e57be076e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 26 deletions

View File

@ -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

View File

@ -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

View File

@ -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")