Skip to content

Commit

Permalink
fix(tests): make sure NATS port is open for unit tests (#16310)
Browse files Browse the repository at this point in the history
* fix(tests): make sure NATS port is open for unit tests

Fixes #10628 again

* chore: add comment re possible race
  • Loading branch information
Jacob Marble authored Jan 2, 2020
1 parent 8780bd2 commit 047afcf
Showing 1 changed file with 29 additions and 9 deletions.
38 changes: 29 additions & 9 deletions cmd/influxd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,34 +720,42 @@ func (m *Launcher) run(ctx context.Context) (err error) {

// NATS streaming server
natsOpts := nats.NewDefaultServerOptions()
nextPort := int64(4222)

// Welcome to ghetto land. It doesn't seem possible to tell NATS to initialise
// a random port. In some integration-style tests, this launcher gets initialised
// multiple times, and sometimes the port from the previous instantiation is
// still open.
//
// This atrocity checks if the port is free, and if it's not, moves on to the
// next one.
// next one. This best-effort approach may still fail occasionally when, for example,
// two tests race on isAddressPortAvailable.
var total int
for {
l, err := net.Listen("tcp", fmt.Sprintf(":%d", nextPort))
if err == nil {
if err := l.Close(); err != nil {
portAvailable, err := isAddressPortAvailable(natsOpts.Host, natsOpts.Port)
if err != nil {
return err
}
if portAvailable && natsOpts.Host == "" {
// Double-check localhost to accommodate tests
time.Sleep(100 * time.Millisecond)
portAvailable, err = isAddressPortAvailable("localhost", natsOpts.Port)
if err != nil {
return err
}
}
if portAvailable {
break
}
time.Sleep(time.Second)
nextPort++

time.Sleep(100 * time.Millisecond)
natsOpts.Port++
total++
if total > 50 {
return errors.New("unable to find free port for Nats server")
}
}
natsOpts.Port = int(nextPort)
m.natsServer = nats.NewServer(&natsOpts)
m.natsPort = int(nextPort)
m.natsPort = natsOpts.Port

if err := m.natsServer.Open(); err != nil {
m.log.Error("Failed to start nats streaming server", zap.Error(err))
Expand Down Expand Up @@ -925,6 +933,18 @@ func (m *Launcher) run(ctx context.Context) (err error) {
return nil
}

// isAddressPortAvailable checks whether the address:port is available to listen,
// by using net.Listen to verify that the port opens successfully, then closes the listener.
func isAddressPortAvailable(address string, port int) (bool, error) {
if l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", address, port)); err == nil {
if err := l.Close(); err != nil {
return false, err
}
return true, nil
}
return false, nil
}

// OrganizationService returns the internal organization service.
func (m *Launcher) OrganizationService() platform.OrganizationService {
return m.apibackend.OrganizationService
Expand Down

0 comments on commit 047afcf

Please sign in to comment.