Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 13 commits into from
Feb 6, 2023
64 changes: 44 additions & 20 deletions testutil/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 4 additions & 5 deletions testutil/network/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion x/genutil/client/cli/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down