Skip to content

Commit

Permalink
test: use a queue of open ports for tests (#14893)
Browse files Browse the repository at this point in the history
Co-authored-by: Marko <marbar3778@yahoo.com>
  • Loading branch information
facundomedica and tac0turtle authored Feb 6, 2023
1 parent ffde2b9 commit 5e57be0
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 26 deletions.
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

0 comments on commit 5e57be0

Please sign in to comment.