test: fix flaky tests.

This commit is contained in:
Romain Le Jeune
2023-05-22 11:16:56 +00:00
parent bb99695e68
commit 9c25f56fe6
57 changed files with 265 additions and 109 deletions

View File

@ -99,7 +99,7 @@ test-linux:
- .rules-branch-manual-MR-and-devel-always
- .after-script-code-coverage
tags:
- medium
- large
test-linux-race:
extends:

View File

@ -228,13 +228,13 @@ change-copyright-year:
./utils/missing_license.sh change-year
test: gofiles
go test -v -timeout=10m -p=1 -count=1 -coverprofile=/tmp/coverage.out -run=${TESTRUN} ./internal/... ./pkg/...
go test -v -timeout=20m -p=1 -count=1 -coverprofile=/tmp/coverage.out -run=${TESTRUN} ./internal/... ./pkg/...
test-race: gofiles
go test -v -timeout=30m -p=1 -count=1 -race -failfast -run=${TESTRUN} ./internal/... ./pkg/...
go test -v -timeout=40m -p=1 -count=1 -race -failfast -run=${TESTRUN} ./internal/... ./pkg/...
test-integration: gofiles
go test -v -timeout=30m -p=1 -count=1 github.com/ProtonMail/proton-bridge/v3/tests
go test -v -timeout=60m -p=1 -count=1 github.com/ProtonMail/proton-bridge/v3/tests
test-integration-debug: gofiles
dlv test github.com/ProtonMail/proton-bridge/v3/tests -- -test.v -test.timeout=10m -test.parallel=1 -test.count=1

View File

@ -50,7 +50,6 @@ import (
"github.com/ProtonMail/proton-bridge/v3/tests"
"github.com/bradenaw/juniper/xslices"
imapid "github.com/emersion/go-imap-id"
"github.com/emersion/go-imap/client"
"github.com/stretchr/testify/require"
)
@ -182,14 +181,18 @@ func TestBridge_UserAgent_Persistence(t *testing.T) {
imapWaiter := waitForIMAPServerReady(b)
defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(b)
defer smtpWaiter.Done()
require.NoError(t, getErr(b.LoginFull(ctx, otherUser, otherPassword, nil, nil)))
imapWaiter.Wait()
smtpWaiter.Wait()
currentUserAgent := b.GetCurrentUserAgent()
require.Contains(t, currentUserAgent, vault.DefaultUserAgent)
imapClient, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
imapClient, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
defer func() { _ = imapClient.Logout() }()
@ -241,11 +244,15 @@ func TestBridge_UserAgentFromIMAPID(t *testing.T) {
imapWaiter := waitForIMAPServerReady(b)
defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(b)
defer smtpWaiter.Done()
require.NoError(t, getErr(b.LoginFull(ctx, otherUser, otherPassword, nil, nil)))
imapWaiter.Wait()
smtpWaiter.Wait()
imapClient, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
imapClient, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
defer func() { _ = imapClient.Logout() }()
@ -619,6 +626,9 @@ func TestBridge_LoginFailed(t *testing.T) {
imapWaiter := waitForIMAPServerReady(bridge)
defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(bridge)
defer smtpWaiter.Done()
failCh, done := chToType[events.Event, events.IMAPLoginFailed](bridge.GetEvents(events.IMAPLoginFailed{}))
defer done()
@ -626,8 +636,9 @@ func TestBridge_LoginFailed(t *testing.T) {
require.NoError(t, err)
imapWaiter.Wait()
smtpWaiter.Wait()
imapClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
imapClient, err := eventuallyDial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
require.NoError(t, err)
require.Error(t, imapClient.Login("badUser", "badPass"))
@ -657,6 +668,9 @@ func TestBridge_ChangeCacheDirectory(t *testing.T) {
imapWaiter := waitForIMAPServerReady(b)
defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(b)
defer smtpWaiter.Done()
// Login the user.
syncCh, done := chToType[events.Event, events.SyncFinished](b.GetEvents(events.SyncFinished{}))
defer done()
@ -691,8 +705,9 @@ func TestBridge_ChangeCacheDirectory(t *testing.T) {
require.True(t, info.State == bridge.Connected)
imapWaiter.Wait()
smtpWaiter.Wait()
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
client, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
@ -732,7 +747,7 @@ func TestBridge_ChangeAddressOrder(t *testing.T) {
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
client, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
@ -753,7 +768,7 @@ func TestBridge_ChangeAddressOrder(t *testing.T) {
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
client, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
@ -990,6 +1005,14 @@ func waitForSMTPServerReady(b *bridge.Bridge) *eventWaiter {
}
}
func waitForSMTPServerStopped(b *bridge.Bridge) *eventWaiter {
evtCh, cancel := b.GetEvents(events.SMTPServerStopped{})
return &eventWaiter{
evtCh: evtCh,
cancel: cancel,
}
}
func waitForIMAPServerReady(b *bridge.Bridge) *eventWaiter {
evtCh, cancel := b.GetEvents(events.IMAPServerReady{})
return &eventWaiter{

View File

@ -28,7 +28,6 @@ import (
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/bradenaw/juniper/iterator"
"github.com/emersion/go-imap/client"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
)
@ -66,7 +65,7 @@ func TestBridge_Refresh(t *testing.T) {
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
client, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
@ -99,7 +98,7 @@ func TestBridge_Refresh(t *testing.T) {
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
client, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()

View File

@ -34,7 +34,6 @@ import (
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/emersion/go-sasl"
"github.com/emersion/go-smtp"
"github.com/stretchr/testify/require"
@ -96,13 +95,13 @@ func TestBridge_Send(t *testing.T) {
}
// Connect the sender IMAP client.
senderIMAPClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
senderIMAPClient, err := eventuallyDial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
require.NoError(t, err)
require.NoError(t, senderIMAPClient.Login(senderInfo.Addresses[0], string(senderInfo.BridgePass)))
defer senderIMAPClient.Logout() //nolint:errcheck
// Connect the recipient IMAP client.
recipientIMAPClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
recipientIMAPClient, err := eventuallyDial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
require.NoError(t, err)
require.NoError(t, recipientIMAPClient.Login(recipientInfo.Addresses[0], string(recipientInfo.BridgePass)))
defer recipientIMAPClient.Logout() //nolint:errcheck
@ -146,7 +145,7 @@ func TestBridge_SendDraftFlags(t *testing.T) {
require.NoError(t, err)
// Connect the sender IMAP client.
imapClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
imapClient, err := eventuallyDial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
require.NoError(t, err)
require.NoError(t, imapClient.Login(userInfo.Addresses[0], string(userInfo.BridgePass)))
defer imapClient.Logout() //nolint:errcheck
@ -256,7 +255,7 @@ func TestBridge_SendInvite(t *testing.T) {
require.NoError(t, err)
// Connect the sender IMAP client.
imapClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
imapClient, err := eventuallyDial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
require.NoError(t, err)
require.NoError(t, imapClient.Login(userInfo.Addresses[0], string(userInfo.BridgePass)))
defer imapClient.Logout() //nolint:errcheck
@ -454,13 +453,13 @@ SGVsbG8gd29ybGQK
}
// Connect the sender IMAP client.
senderIMAPClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
senderIMAPClient, err := eventuallyDial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
require.NoError(t, err)
require.NoError(t, senderIMAPClient.Login(senderInfo.Addresses[0], string(senderInfo.BridgePass)))
defer senderIMAPClient.Logout() //nolint:errcheck
// Connect the recipient IMAP client.
recipientIMAPClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
recipientIMAPClient, err := eventuallyDial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort())))
require.NoError(t, err)
require.NoError(t, recipientIMAPClient.Login(recipientInfo.Addresses[0], string(recipientInfo.BridgePass)))
defer recipientIMAPClient.Logout() //nolint:errcheck

View File

@ -27,14 +27,13 @@ import (
"github.com/ProtonMail/proton-bridge/v3/internal/bridge"
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/emersion/go-imap/client"
"github.com/stretchr/testify/require"
)
func TestServerManager_NoLoadedUsersNoServers(t *testing.T) {
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) {
withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) {
_, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
_, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
require.Error(t, err)
})
})
@ -113,7 +112,7 @@ func TestServerManager_ServersDoNotStopWhenThereIsStillOneActiveUser(t *testing.
waitForEvent(t, evtCh, events.UserDeauth{})
imapClient, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
imapClient, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, imapClient.Logout())
})
@ -138,7 +137,7 @@ func TestServerManager_ServersStartIfAtLeastOneUserIsLoggedIn(t *testing.T) {
require.NoError(t, s.RevokeUser(userIDOther))
withBridgeWaitForServers(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) {
imapClient, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
imapClient, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, imapClient.Logout())
})
@ -151,21 +150,30 @@ func TestServerManager_NetworkLossStopsServers(t *testing.T) {
imapWaiter := waitForIMAPServerReady(bridge)
defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(bridge)
defer smtpWaiter.Done()
imapWaiterStop := waitForIMAPServerStopped(bridge)
defer imapWaiterStop.Done()
smtpWaiterStop := waitForSMTPServerStopped(bridge)
defer smtpWaiterStop.Done()
_, err := bridge.LoginFull(ctx, username, password, nil, nil)
require.NoError(t, err)
imapWaiter.Wait()
smtpWaiter.Wait()
netCtl.Disable()
imapWaiterStop.Wait()
smtpWaiterStop.Wait()
netCtl.Enable()
imapWaiter.Wait()
smtpWaiter.Wait()
})
})
}

View File

@ -80,7 +80,7 @@ func TestBridge_Sync(t *testing.T) {
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
client, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
@ -127,7 +127,7 @@ func TestBridge_Sync(t *testing.T) {
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
client, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
@ -178,7 +178,7 @@ func _TestBridge_Sync_BadMessage(t *testing.T) { //nolint:unused,deadcode
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
client, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
@ -293,7 +293,7 @@ func TestBridge_SyncWithOngoingEvents(t *testing.T) {
require.NoError(t, err)
require.True(t, info.State == bridge.Connected)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
client, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()

View File

@ -444,14 +444,14 @@ func TestBridge_User_DropConn_NoBadEvent(t *testing.T) {
info, err := bridge.QueryUserInfo("user")
require.NoError(t, err)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
cli, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = cli.Logout() }()
// The IMAP client will eventually see 20 messages.
require.Eventually(t, func() bool {
status, err := client.Status("INBOX", []imap.StatusItem{imap.StatusMessages})
status, err := cli.Status("INBOX", []imap.StatusItem{imap.StatusMessages})
return err == nil && status.Messages == 20
}, 10*time.Second, 100*time.Millisecond)
})
@ -645,12 +645,12 @@ func TestBridge_User_SendDraftRemoveDraftFlag(t *testing.T) {
info, err := bridge.QueryUserInfo("user")
require.NoError(t, err)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
cli, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = cli.Logout() }()
messages, err := clientFetch(client, "Drafts")
messages, err := clientFetch(cli, "Drafts")
require.NoError(t, err)
require.Len(t, messages, 1)
require.Contains(t, messages[0].Flags, imap.DraftFlag)
@ -684,12 +684,12 @@ func TestBridge_User_SendDraftRemoveDraftFlag(t *testing.T) {
info, err := bridge.QueryUserInfo("user")
require.NoError(t, err)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
cli, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = cli.Logout() }()
messages, err := clientFetch(client, "Sent")
messages, err := clientFetch(cli, "Sent")
require.NoError(t, err)
require.Len(t, messages, 1)
require.NotContains(t, messages[0].Flags, imap.DraftFlag)
@ -781,17 +781,21 @@ func TestBridge_User_HandleParentLabelRename(t *testing.T) {
imapWaiter := waitForIMAPServerReady(bridge)
defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(bridge)
defer smtpWaiter.Done()
require.NoError(t, getErr(bridge.LoginFull(ctx, username, password, nil, nil)))
info, err := bridge.QueryUserInfo(username)
require.NoError(t, err)
imapWaiter.Wait()
smtpWaiter.Wait()
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
cli, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = cli.Logout() }()
withClient(ctx, t, s, username, password, func(ctx context.Context, c *proton.Client) {
parentName := uuid.NewString()
@ -807,7 +811,7 @@ func TestBridge_User_HandleParentLabelRename(t *testing.T) {
// Wait for the parent folder to be created.
require.Eventually(t, func() bool {
return xslices.IndexFunc(clientList(client), func(mailbox *imap.MailboxInfo) bool {
return xslices.IndexFunc(clientList(cli), func(mailbox *imap.MailboxInfo) bool {
return mailbox.Name == fmt.Sprintf("Folders/%v", parentName)
}) >= 0
}, 100*user.EventPeriod, user.EventPeriod)
@ -824,7 +828,7 @@ func TestBridge_User_HandleParentLabelRename(t *testing.T) {
// Wait for the parent folder to be created.
require.Eventually(t, func() bool {
return xslices.IndexFunc(clientList(client), func(mailbox *imap.MailboxInfo) bool {
return xslices.IndexFunc(clientList(cli), func(mailbox *imap.MailboxInfo) bool {
return mailbox.Name == fmt.Sprintf("Folders/%v/%v", parentName, childName)
}) >= 0
}, 100*user.EventPeriod, user.EventPeriod)
@ -839,14 +843,14 @@ func TestBridge_User_HandleParentLabelRename(t *testing.T) {
// Wait for the parent folder to be renamed.
require.Eventually(t, func() bool {
return xslices.IndexFunc(clientList(client), func(mailbox *imap.MailboxInfo) bool {
return xslices.IndexFunc(clientList(cli), func(mailbox *imap.MailboxInfo) bool {
return mailbox.Name == fmt.Sprintf("Folders/%v", newParentName)
}) >= 0
}, 100*user.EventPeriod, user.EventPeriod)
// Wait for the child folder to be renamed.
require.Eventually(t, func() bool {
return xslices.IndexFunc(clientList(client), func(mailbox *imap.MailboxInfo) bool {
return xslices.IndexFunc(clientList(cli), func(mailbox *imap.MailboxInfo) bool {
return mailbox.Name == fmt.Sprintf("Folders/%v/%v", newParentName, childName)
}) >= 0
}, 100*user.EventPeriod, user.EventPeriod)
@ -898,10 +902,10 @@ func userContinueEventProcess(
info, err := bridge.QueryUserInfo("user")
require.NoError(t, err)
client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
cli, err := eventuallyDial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort()))
require.NoError(t, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }()
require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = cli.Logout() }()
randomLabel := uuid.NewString()
@ -916,8 +920,21 @@ func userContinueEventProcess(
// Wait for the label to be created.
require.Eventually(t, func() bool {
return xslices.IndexFunc(clientList(client), func(mailbox *imap.MailboxInfo) bool {
return xslices.IndexFunc(clientList(cli), func(mailbox *imap.MailboxInfo) bool {
return mailbox.Name == "Labels/"+randomLabel
}) >= 0
}, 100*user.EventPeriod, user.EventPeriod)
}
func eventuallyDial(addr string) (cli *client.Client, err error) {
var sleep = 1 * time.Second
for i := 0; i < 5; i++ {
cli, err := client.Dial(addr)
if err == nil {
return cli, nil
}
time.Sleep(sleep)
sleep *= 2
}
return nil, fmt.Errorf("after 5 attempts, last error: %s", err)
}

View File

@ -19,6 +19,7 @@ package tests
import (
"fmt"
"time"
"github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/emersion/go-imap/client"
@ -29,14 +30,14 @@ func (t *testCtx) newIMAPClient(userID, clientID string) error {
}
func (t *testCtx) newIMAPClientOnPort(userID, clientID string, imapPort int) error {
client, err := client.Dial(fmt.Sprintf("%v:%d", constants.Host, imapPort))
cli, err := eventuallyDial(fmt.Sprintf("%v:%d", constants.Host, imapPort))
if err != nil {
return err
}
t.imapClients[clientID] = &imapClient{
userID: userID,
client: client,
client: cli,
}
return nil
@ -45,3 +46,16 @@ func (t *testCtx) newIMAPClientOnPort(userID, clientID string, imapPort int) err
func (t *testCtx) getIMAPClient(clientID string) (string, *client.Client) {
return t.imapClients[clientID].userID, t.imapClients[clientID].client
}
func eventuallyDial(addr string) (cli *client.Client, err error) {
var sleep = 1 * time.Second
for i := 0; i < 5; i++ {
cli, err := client.Dial(addr)
if err == nil {
return cli, nil
}
time.Sleep(sleep)
sleep *= 2
}
return nil, fmt.Errorf("after 5 attempts, last error: %s", err)
}

View File

@ -169,6 +169,7 @@ type testCtx struct {
dummyListeners []net.Listener
imapServerStarted bool
smtpServerStarted bool
}
type imapClient struct {

View File

@ -1,7 +1,9 @@
Feature: Send Telemetry Heartbeat
Background:
Given there exists an account with username "[user:user1]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
Then it succeeds
Scenario: Send at first start - one user default settings

View File

@ -4,9 +4,11 @@ Feature: A user can authenticate an IMAP client
And there exists an account with username "[user:user2]" and password "password2"
And the account "[user:user]" has additional address "[alias:alias]@[domain]"
And the account "[user:user2]" has additional disabled address "[alias:alias2]@[domain]"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user logs in with username "[user:user2]" and password "password2"
Then it succeeds
Scenario: IMAP client can authenticate successfully
When user "[user:user]" connects IMAP client "1"

View File

@ -1,8 +1,10 @@
Feature: The IMAP ID is propagated to bridge
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
Then it succeeds
Scenario: Initial user agent before an IMAP client announces its ID
When user "[user:user]" connects IMAP client "1"

View File

@ -7,10 +7,12 @@ Feature: IMAP create mailbox
| f2 | folder |
| l1 | label |
| l2 | label |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Create folder
When IMAP client "1" creates "Folders/mbox"

View File

@ -6,10 +6,12 @@ Feature: IMAP delete mailbox
| one | folder |
| two | folder |
| three | label |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Delete folder
When IMAP client "1" deletes "Folders/one"

View File

@ -1,10 +1,12 @@
Feature: IMAP Hide All Mail
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Hide All Mail Mailbox
Given IMAP client "1" eventually sees the following mailbox info:

View File

@ -8,9 +8,11 @@ Feature: IMAP get mailbox info
| from | to | subject | unread |
| a@example.com | a@example.com | one | true |
| b@example.com | b@example.com | two | false |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
Then it succeeds
Scenario: Mailbox status reports correct name, total and unread
When user "[user:user]" connects and authenticates IMAP client "1"

View File

@ -5,11 +5,13 @@ Feature: IMAP list mailboxes
| name | type |
| mbox1 | folder |
| mbox2 | label |
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then IMAP client "1" eventually sees the following mailbox info:
Then it succeeds
And IMAP client "1" eventually sees the following mailbox info:
| name |
| INBOX |
| Drafts |

View File

@ -5,10 +5,12 @@ Feature: IMAP get mailbox info
| name | type |
| f1 | folder |
| l1 | label |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Rename folder
When IMAP client "1" renames "Folders/f1" to "Folders/f2"

View File

@ -5,10 +5,12 @@ Feature: IMAP get mailbox info
| name | type |
| f1 | folder |
| f1/f2| folder |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Rename folder with subfolders
When IMAP client "1" renames "Folders/f1" to "Folders/f3"

View File

@ -5,10 +5,12 @@ Feature: IMAP select mailbox
| name | type |
| mbox | folder |
| label | label |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Select inbox
When IMAP client "1" selects "INBOX"

View File

@ -9,10 +9,12 @@ Feature: IMAP copy messages
| from | to | subject | unread |
| john.doe@mail.com | [user:user]@[domain] | foo | false |
| jane.doe@mail.com | name@[domain] | bar | true |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Copy message to label
When IMAP client "1" copies the message with subject "foo" from "INBOX" to "Labels/label"

View File

@ -2,10 +2,12 @@ Feature: IMAP create messages
Background:
Given there exists an account with username "[user:user]" and password "password"
And the account "[user:user]" has additional address "[alias:alias]@[domain]"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Creates message to user's primary address
When IMAP client "1" appends the following messages to "INBOX":

View File

@ -7,10 +7,12 @@ Feature: IMAP remove messages from mailbox
| label | label |
And the address "[user:user]@[domain]" of account "[user:user]" has 10 messages in "Folders/mbox"
And the address "[user:user]@[domain]" of account "[user:user]" has 1 messages in "Scheduled"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Mark message as deleted and EXPUNGE
When IMAP client "1" selects "Folders/mbox"

View File

@ -5,6 +5,7 @@ Feature: IMAP remove messages from Trash
| name | type |
| mbox | folder |
| label | label |
Then it succeeds
Scenario Outline: Message in Trash and some other label is not permanently deleted
Given the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Trash":

View File

@ -1,7 +1,8 @@
Feature: IMAP Draft messages
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
@ -11,12 +12,13 @@ Feature: IMAP Draft messages
This is a dra
"""
And it succeeds
Then IMAP client "1" eventually sees the following messages in "Drafts":
Then it succeeds
And IMAP client "1" eventually sees the following messages in "Drafts":
| body |
| This is a dra |
And IMAP client "1" eventually sees 1 messages in "Drafts"
Scenario: Draft edited locally
When IMAP client "1" marks message 1 as deleted
And IMAP client "1" expunges

View File

@ -7,10 +7,12 @@ Feature: IMAP Fetch
And the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Inbox":
| from | to | subject | date |
| john.doe@mail.com | [user:user]@[domain] | foo | 13 Jul 69 00:00 +0000 |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Fetch very old message
Given IMAP client "1" eventually sees the following messages in "INBOX":

View File

@ -1,10 +1,12 @@
Feature: IMAP import messages
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Basic message import
When IMAP client "1" appends the following message to "INBOX":

View File

@ -19,10 +19,12 @@ Feature: IMAP move messages
And the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Scheduled":
| from | to | subject | unread |
| john.doe@mail.com | [user:user]@[domain] | sch | false |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Move message from folder to label (keeps in folder)
When IMAP client "1" moves the message with subject "foo" from "INBOX" to "Labels/label"

View File

@ -4,11 +4,13 @@ Feature: IMAP move messages by append and delete (without MOVE support, e.g., Ou
And the account "[user:user]" has the following custom mailboxes:
| name | type |
| mbox | folder |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "source"
And user "[user:user]" connects and authenticates IMAP client "target"
Then it succeeds
Scenario Outline: Move message from <srcMailbox> to <dstMailbox> by <order>
When IMAP client "source" appends the following message to "<srcMailbox>":

View File

@ -7,10 +7,11 @@ Feature: Bridge can fully sync an account
| jane.doe@mail.com | name@[domain] | bar | true |
And the account "[user:user]" has 20 custom folders
And the account "[user:user]" has 60 custom labels
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
When user "[user:user]" connects and authenticates IMAP client "1"
And user "[user:user]" connects and authenticates IMAP client "1"
Then IMAP client "1" counts 20 mailboxes under "Folders"
And IMAP client "1" counts 60 mailboxes under "Labels"

View File

@ -1,9 +1,11 @@
Feature: A user can connect an IMAP client to custom ports
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user changes the IMAP port to 1144
Then it succeeds
Scenario: Authenticates successfully on custom port
When user "[user:user]" connects IMAP client "1" on port 1144

View File

@ -6,10 +6,12 @@ Feature: A user can authenticate an SMTP client
And the account "[user:user]" has additional address "[alias:alias]@[domain]"
And the account "[user:user2]" has additional disabled address "[alias:alias2]@[domain]"
And the account "[user:user3]" has additional address "[alias:alias3]@[domain]"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user logs in with username "[user:user2]" and password "password2"
And the user logs in with username "[user:user3]" and password "password3"
Then it succeeds
Scenario: SMTP client can authenticate successfully
When user "[user:user]" connects SMTP client "1"

View File

@ -1,9 +1,11 @@
Feature: SMTP initiation
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
When user "[user:user]" connects and authenticates SMTP client "1"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Send without first announcing FROM and TO
When SMTP client "1" sends DATA:

View File

@ -1,10 +1,12 @@
Feature: A user can connect an SMTP client to custom ports
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user changes the SMTP port to 1144
Then it succeeds
Scenario: Authenticates successfully on custom port
When the user changes the SMTP port to 1144
When user "[user:user]" connects SMTP client "1" on port 1144
Then SMTP client "1" can authenticate

View File

@ -1,12 +1,14 @@
Feature: SMTP with bcc
Background:
Given there exists an account with username "[user:user]" and password "password"
Given there exists an account with username "[user:to]" and password "password"
Given there exists an account with username "[user:bcc]" and password "password"
And bridge starts
And there exists an account with username "[user:to]" and password "password"
And there exists an account with username "[user:bcc]" and password "password"
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user logs in with username "[user:bcc]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Send message to address in to and bcc
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain], [user:bcc]@[domain]":

View File

@ -2,10 +2,12 @@ Feature: SMTP sending embedded message
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user logs in with username "[user:to]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
@long-black
Scenario: Send it

View File

@ -2,9 +2,11 @@ Feature: SMTP wrong messages
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Message with attachment and wrong boundaries
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]":

View File

@ -2,9 +2,11 @@ Feature: SMTP sending of plain messages
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: HTML message to external account
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "pm.bridge.qa@gmail.com":

View File

@ -2,9 +2,11 @@ Feature: SMTP sending of plain messages
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: HTML message with attachment to internal account
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]":

View File

@ -2,9 +2,11 @@ Feature: SMTP messages containing inlines
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: A message with inline attachment to internal account
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]":

View File

@ -2,9 +2,11 @@ Feature: SMTP sending with mixed case address
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Mixed sender case in sender address
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]":

View File

@ -2,9 +2,11 @@ Feature: SMTP sending two messages
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:recp]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user logs in with username "[user:recp]" and password "password"
Then it succeeds
@long-black

View File

@ -3,9 +3,11 @@ Feature: SMTP sending of plain messages
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And there exists an account with username "[user:cc]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Only from and to headers to internal account
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]":

View File

@ -2,9 +2,11 @@ Feature: SMTP sending of plain messages
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Basic message with attachment to internal account
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]":

View File

@ -2,7 +2,8 @@ Feature: SMTP sending the same message twice
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user logs in with username "[user:to]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"

View File

@ -2,10 +2,12 @@ Feature: SMTP sending with APPENDing to Sent
Background:
Given there exists an account with username "[user:user]" and password "password"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1"
And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Send message and append to Sent
# First do sending.

View File

@ -3,11 +3,13 @@ Feature: SMTP send reply
Background:
Given there exists an account with username "[user:user1]" and password "password"
And there exists an account with username "[user:user2]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user1]" and password "password"
And user "[user:user1]" finishes syncing
And user "[user:user1]" connects and authenticates SMTP client "1"
And user "[user:user1]" connects and authenticates IMAP client "1"
Then it succeeds
@long-black
Scenario: Reply with In-Reply-To but no References

View File

@ -4,10 +4,12 @@ Feature: SMTP sending two messages
And there exists an account with username "[user:multi]" and password "password"
And the account "[user:multi]" has additional address "[user:multi-alias]@[domain]"
And there exists an account with username "[user:to]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And the user logs in with username "[user:multi]" and password "password"
And the user sets the address mode of user "[user:multi]" to "split"
Then it succeeds
Scenario: Send two messages in one connection
When user "[user:user]" connects and authenticates SMTP client "1"

View File

@ -14,9 +14,11 @@ Feature: Address mode
| from | to | subject | unread |
| c@[domain] | c@[domain] | three | true |
| d@[domain] | d@[domain] | four | false |
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing
Then it succeeds
Scenario: The user is in combined mode
When user "[user:user]" connects and authenticates IMAP client "1" with address "[user:user]@[domain]"

View File

@ -1,8 +1,10 @@
Feature: A user can be deleted
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
Then it succeeds
Scenario: Delete a connected user
When user "[user:user]" is deleted

View File

@ -1,9 +1,11 @@
Feature: A user can login
Background:
Given there exists an account with username "[user:user]" and password "password"
Given there exists an account with username "[user:MixedCaps]" and password "password"
Given there exists a disabled account with username "[user:disabled]" and password "password"
And there exists an account with username "[user:MixedCaps]" and password "password"
And there exists a disabled account with username "[user:disabled]" and password "password"
Then it succeeds
And bridge starts
Then it succeeds
Scenario: Login to account
When the user logs in with username "[user:user]" and password "password"

View File

@ -1,8 +1,10 @@
Feature: A logged out user can login again
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
Then it succeeds
Scenario: Login to disconnected account
When user "[user:user]" logs out

View File

@ -1,8 +1,10 @@
Feature: A logged in user is logged out when its auth is revoked.
Background:
Given there exists an account with username "[user:user]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
And the user logs in with username "[user:user]" and password "password"
Then it succeeds
Scenario: The auth is revoked while bridge is running
When the auth of user "[user:user]" is revoked

View File

@ -14,7 +14,9 @@ Feature: Bridge can fully sync an account
| from | to | subject | unread |
| a@[domain] | a@[domain] | one | true |
| b@[domain] | b@[domain] | two | false |
And bridge starts
Then it succeeds
When bridge starts
Then it succeeds
Scenario: The account is synced when the user logs in and persists across bridge restarts
When the user logs in with username "[user:user]" and password "password"

View File

@ -2,7 +2,9 @@ Feature: Bridge send usage metrics
Background:
Given there exists an account with username "[user:user1]" and password "password"
And there exists an account with username "[user:user2]" and password "password"
And bridge starts
Then it succeeds
When bridge starts
Then it succeeds
Scenario: Telemetry availability - No user

View File

@ -332,8 +332,10 @@ func (s *scenario) drafAtIndexWasMovedToTrashForAddressOfAccount(draftIndex int,
}
func (s *scenario) userLogsInWithUsernameAndPassword(username, password string) error {
evtCh, cancel := s.t.bridge.GetEvents(events.SMTPServerReady{})
defer cancel()
smtpEvtCh, cancelSMTP := s.t.bridge.GetEvents(events.SMTPServerReady{})
defer cancelSMTP()
imapEvtCh, cancelIMAP := s.t.bridge.GetEvents(events.IMAPServerReady{})
defer cancelIMAP()
userID, err := s.t.bridge.LoginFull(context.Background(), username, []byte(password), nil, nil)
if err != nil {
@ -342,9 +344,13 @@ func (s *scenario) userLogsInWithUsernameAndPassword(username, password string)
// We need to wait for server to be up or we won't be able to connect. It should only happen once to avoid
// blocking on multiple Logins.
if !s.t.imapServerStarted {
<-evtCh
<-imapEvtCh
s.t.imapServerStarted = true
}
if !s.t.smtpServerStarted {
<-smtpEvtCh
s.t.smtpServerStarted = true
}
if userID != s.t.getUserByName(username).getUserID() {
return errors.New("user ID mismatch")