feat(GODT-2538): implement smart picking of default IMAP/SMTP ports

This commit is contained in:
Xavier Michelon
2023-04-06 15:08:41 +02:00
parent 54b209f9e1
commit 3ddd88e127
9 changed files with 182 additions and 12 deletions

View File

@ -107,7 +107,10 @@ func TestFeatures(testingT *testing.T) {
ctx.Step(`^the header in the "([^"]*)" request to "([^"]*)" has "([^"]*)" set to "([^"]*)"$`, s.theHeaderInTheRequestToHasSetTo)
ctx.Step(`^the body in the "([^"]*)" request to "([^"]*)" is:$`, s.theBodyInTheRequestToIs)
ctx.Step(`^the API requires bridge version at least "([^"]*)"$`, s.theAPIRequiresBridgeVersion)
ctx.Step(`^the network port (\d+) is busy$`, s.networkPortIsBusy)
ctx.Step(`^the network port range (\d+)-(\d+) is busy$`, s.networkPortRangeIsBusy)
ctx.Step(`^bridge IMAP port is (\d+)`, s.bridgeIMAPPortIs)
ctx.Step(`^bridge SMTP port is (\d+)`, s.bridgeSMTPPortIs)
// ==== SETUP ====
ctx.Step(`^there exists an account with username "([^"]*)" and password "([^"]*)"$`, s.thereExistsAnAccountWithUsernameAndPassword)
ctx.Step(`^there exists a disabled account with username "([^"]*)" and password "([^"]*)"$`, s.thereExistsAnAccountWithUsernameAndPasswordWithDisablePrimary)

View File

@ -21,7 +21,9 @@ import (
"context"
"errors"
"fmt"
"net"
"os"
"strconv"
"time"
"github.com/Masterminds/semver/v3"
@ -307,3 +309,37 @@ func (s *scenario) theUserHidesAllMail() error {
func (s *scenario) theUserShowsAllMail() error {
return s.t.bridge.SetShowAllMail(true)
}
func (s *scenario) networkPortIsBusy(port int) {
if listener, err := net.Listen("tcp", "127.0.0.1:"+strconv.Itoa(port)); err == nil { // we ignore errors. Most likely port is already busy.
s.t.dummyListeners = append(s.t.dummyListeners, listener)
}
}
func (s *scenario) networkPortRangeIsBusy(startPort, endPort int) {
if startPort > endPort {
startPort, endPort = endPort, startPort
}
for port := startPort; port <= endPort; port++ {
s.networkPortIsBusy(port)
}
}
func (s *scenario) bridgeIMAPPortIs(expectedPort int) error {
actualPort := s.t.bridge.GetIMAPPort()
if actualPort != expectedPort {
return fmt.Errorf("expected IMAP port to be %v but got %v", expectedPort, actualPort)
}
return nil
}
func (s *scenario) bridgeSMTPPortIs(expectedPort int) error {
actualPort := s.t.bridge.GetSMTPPort()
if actualPort != expectedPort {
return fmt.Errorf("expected SMTP port to be %v but got %v", expectedPort, actualPort)
}
return nil
}

View File

@ -20,6 +20,7 @@ package tests
import (
"context"
"fmt"
"net"
"net/smtp"
"net/url"
"regexp"
@ -160,6 +161,9 @@ type testCtx struct {
// errors holds test-related errors encountered while running test steps.
errors [][]error
errorsLock sync.RWMutex
// This slice contains the dummy listeners that are intended to block network ports.
dummyListeners []net.Listener
}
type imapClient struct {
@ -437,6 +441,12 @@ func (t *testCtx) close(ctx context.Context) {
}
}
for _, listener := range t.dummyListeners {
if err := listener.Close(); err != nil {
logrus.WithError(err).Errorf("Failed to close dummy listener %v", listener.Addr())
}
}
t.api.Close()
t.events.close()
t.reporter.close()

View File

@ -0,0 +1,24 @@
Feature: Bridge picks default ports wisely
Scenario: bridge picks ports for IMAP and SMTP using default values.
When bridge starts
Then bridge IMAP port is 1143
Then bridge SMTP port is 1025
Scenario: bridge picks ports for IMAP wisely when default port is busy.
When the network port 1143 is busy
And bridge starts
Then bridge IMAP port is 1144
Then bridge SMTP port is 1025
Scenario: bridge picks ports for SMTP wisely when default port is busy.
When the network port range 1025-1030 is busy
And bridge starts
Then bridge IMAP port is 1143
Then bridge SMTP port is 1031
Scenario: bridge picks ports for IMAP SMTP wisely when default ports are busy.
When the network port range 1025-1200 is busy
And bridge starts
Then bridge IMAP port is 1201
Then bridge SMTP port is 1202