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 - .rules-branch-manual-MR-and-devel-always
- .after-script-code-coverage - .after-script-code-coverage
tags: tags:
- medium - large
test-linux-race: test-linux-race:
extends: extends:

View File

@ -228,13 +228,13 @@ change-copyright-year:
./utils/missing_license.sh change-year ./utils/missing_license.sh change-year
test: gofiles 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 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 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 test-integration-debug: gofiles
dlv test github.com/ProtonMail/proton-bridge/v3/tests -- -test.v -test.timeout=10m -test.parallel=1 -test.count=1 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/ProtonMail/proton-bridge/v3/tests"
"github.com/bradenaw/juniper/xslices" "github.com/bradenaw/juniper/xslices"
imapid "github.com/emersion/go-imap-id" imapid "github.com/emersion/go-imap-id"
"github.com/emersion/go-imap/client"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -182,14 +181,18 @@ func TestBridge_UserAgent_Persistence(t *testing.T) {
imapWaiter := waitForIMAPServerReady(b) imapWaiter := waitForIMAPServerReady(b)
defer imapWaiter.Done() defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(b)
defer smtpWaiter.Done()
require.NoError(t, getErr(b.LoginFull(ctx, otherUser, otherPassword, nil, nil))) require.NoError(t, getErr(b.LoginFull(ctx, otherUser, otherPassword, nil, nil)))
imapWaiter.Wait() imapWaiter.Wait()
smtpWaiter.Wait()
currentUserAgent := b.GetCurrentUserAgent() currentUserAgent := b.GetCurrentUserAgent()
require.Contains(t, currentUserAgent, vault.DefaultUserAgent) 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) require.NoError(t, err)
defer func() { _ = imapClient.Logout() }() defer func() { _ = imapClient.Logout() }()
@ -241,11 +244,15 @@ func TestBridge_UserAgentFromIMAPID(t *testing.T) {
imapWaiter := waitForIMAPServerReady(b) imapWaiter := waitForIMAPServerReady(b)
defer imapWaiter.Done() defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(b)
defer smtpWaiter.Done()
require.NoError(t, getErr(b.LoginFull(ctx, otherUser, otherPassword, nil, nil))) require.NoError(t, getErr(b.LoginFull(ctx, otherUser, otherPassword, nil, nil)))
imapWaiter.Wait() 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) require.NoError(t, err)
defer func() { _ = imapClient.Logout() }() defer func() { _ = imapClient.Logout() }()
@ -619,6 +626,9 @@ func TestBridge_LoginFailed(t *testing.T) {
imapWaiter := waitForIMAPServerReady(bridge) imapWaiter := waitForIMAPServerReady(bridge)
defer imapWaiter.Done() defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(bridge)
defer smtpWaiter.Done()
failCh, done := chToType[events.Event, events.IMAPLoginFailed](bridge.GetEvents(events.IMAPLoginFailed{})) failCh, done := chToType[events.Event, events.IMAPLoginFailed](bridge.GetEvents(events.IMAPLoginFailed{}))
defer done() defer done()
@ -626,8 +636,9 @@ func TestBridge_LoginFailed(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
imapWaiter.Wait() 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.NoError(t, err)
require.Error(t, imapClient.Login("badUser", "badPass")) require.Error(t, imapClient.Login("badUser", "badPass"))
@ -657,6 +668,9 @@ func TestBridge_ChangeCacheDirectory(t *testing.T) {
imapWaiter := waitForIMAPServerReady(b) imapWaiter := waitForIMAPServerReady(b)
defer imapWaiter.Done() defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(b)
defer smtpWaiter.Done()
// Login the user. // Login the user.
syncCh, done := chToType[events.Event, events.SyncFinished](b.GetEvents(events.SyncFinished{})) syncCh, done := chToType[events.Event, events.SyncFinished](b.GetEvents(events.SyncFinished{}))
defer done() defer done()
@ -691,8 +705,9 @@ func TestBridge_ChangeCacheDirectory(t *testing.T) {
require.True(t, info.State == bridge.Connected) require.True(t, info.State == bridge.Connected)
imapWaiter.Wait() 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = client.Logout() }()
@ -732,7 +747,7 @@ func TestBridge_ChangeAddressOrder(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, info.State == bridge.Connected) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = client.Logout() }()
@ -753,7 +768,7 @@ func TestBridge_ChangeAddressOrder(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, info.State == bridge.Connected) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() 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 { func waitForIMAPServerReady(b *bridge.Bridge) *eventWaiter {
evtCh, cancel := b.GetEvents(events.IMAPServerReady{}) evtCh, cancel := b.GetEvents(events.IMAPServerReady{})
return &eventWaiter{ return &eventWaiter{

View File

@ -28,7 +28,6 @@ import (
"github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/bradenaw/juniper/iterator" "github.com/bradenaw/juniper/iterator"
"github.com/emersion/go-imap/client"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -66,7 +65,7 @@ func TestBridge_Refresh(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, info.State == bridge.Connected) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = client.Logout() }()
@ -99,7 +98,7 @@ func TestBridge_Refresh(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, info.State == bridge.Connected) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() 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/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/emersion/go-imap" "github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/emersion/go-sasl" "github.com/emersion/go-sasl"
"github.com/emersion/go-smtp" "github.com/emersion/go-smtp"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -96,13 +95,13 @@ func TestBridge_Send(t *testing.T) {
} }
// Connect the sender IMAP client. // 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, err)
require.NoError(t, senderIMAPClient.Login(senderInfo.Addresses[0], string(senderInfo.BridgePass))) require.NoError(t, senderIMAPClient.Login(senderInfo.Addresses[0], string(senderInfo.BridgePass)))
defer senderIMAPClient.Logout() //nolint:errcheck defer senderIMAPClient.Logout() //nolint:errcheck
// Connect the recipient IMAP client. // 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, err)
require.NoError(t, recipientIMAPClient.Login(recipientInfo.Addresses[0], string(recipientInfo.BridgePass))) require.NoError(t, recipientIMAPClient.Login(recipientInfo.Addresses[0], string(recipientInfo.BridgePass)))
defer recipientIMAPClient.Logout() //nolint:errcheck defer recipientIMAPClient.Logout() //nolint:errcheck
@ -146,7 +145,7 @@ func TestBridge_SendDraftFlags(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Connect the sender IMAP client. // 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, err)
require.NoError(t, imapClient.Login(userInfo.Addresses[0], string(userInfo.BridgePass))) require.NoError(t, imapClient.Login(userInfo.Addresses[0], string(userInfo.BridgePass)))
defer imapClient.Logout() //nolint:errcheck defer imapClient.Logout() //nolint:errcheck
@ -256,7 +255,7 @@ func TestBridge_SendInvite(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// Connect the sender IMAP client. // 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, err)
require.NoError(t, imapClient.Login(userInfo.Addresses[0], string(userInfo.BridgePass))) require.NoError(t, imapClient.Login(userInfo.Addresses[0], string(userInfo.BridgePass)))
defer imapClient.Logout() //nolint:errcheck defer imapClient.Logout() //nolint:errcheck
@ -454,13 +453,13 @@ SGVsbG8gd29ybGQK
} }
// Connect the sender IMAP client. // 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, err)
require.NoError(t, senderIMAPClient.Login(senderInfo.Addresses[0], string(senderInfo.BridgePass))) require.NoError(t, senderIMAPClient.Login(senderInfo.Addresses[0], string(senderInfo.BridgePass)))
defer senderIMAPClient.Logout() //nolint:errcheck defer senderIMAPClient.Logout() //nolint:errcheck
// Connect the recipient IMAP client. // 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, err)
require.NoError(t, recipientIMAPClient.Login(recipientInfo.Addresses[0], string(recipientInfo.BridgePass))) require.NoError(t, recipientIMAPClient.Login(recipientInfo.Addresses[0], string(recipientInfo.BridgePass)))
defer recipientIMAPClient.Logout() //nolint:errcheck 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/bridge"
"github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/events"
"github.com/emersion/go-imap/client"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestServerManager_NoLoadedUsersNoServers(t *testing.T) { func TestServerManager_NoLoadedUsersNoServers(t *testing.T) {
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { 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) { 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) require.Error(t, err)
}) })
}) })
@ -113,7 +112,7 @@ func TestServerManager_ServersDoNotStopWhenThereIsStillOneActiveUser(t *testing.
waitForEvent(t, evtCh, events.UserDeauth{}) 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, err)
require.NoError(t, imapClient.Logout()) require.NoError(t, imapClient.Logout())
}) })
@ -138,7 +137,7 @@ func TestServerManager_ServersStartIfAtLeastOneUserIsLoggedIn(t *testing.T) {
require.NoError(t, s.RevokeUser(userIDOther)) require.NoError(t, s.RevokeUser(userIDOther))
withBridgeWaitForServers(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { 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, err)
require.NoError(t, imapClient.Logout()) require.NoError(t, imapClient.Logout())
}) })
@ -151,21 +150,30 @@ func TestServerManager_NetworkLossStopsServers(t *testing.T) {
imapWaiter := waitForIMAPServerReady(bridge) imapWaiter := waitForIMAPServerReady(bridge)
defer imapWaiter.Done() defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(bridge)
defer smtpWaiter.Done()
imapWaiterStop := waitForIMAPServerStopped(bridge) imapWaiterStop := waitForIMAPServerStopped(bridge)
defer imapWaiterStop.Done() defer imapWaiterStop.Done()
smtpWaiterStop := waitForSMTPServerStopped(bridge)
defer smtpWaiterStop.Done()
_, err := bridge.LoginFull(ctx, username, password, nil, nil) _, err := bridge.LoginFull(ctx, username, password, nil, nil)
require.NoError(t, err) require.NoError(t, err)
imapWaiter.Wait() imapWaiter.Wait()
smtpWaiter.Wait()
netCtl.Disable() netCtl.Disable()
imapWaiterStop.Wait() imapWaiterStop.Wait()
smtpWaiterStop.Wait()
netCtl.Enable() netCtl.Enable()
imapWaiter.Wait() imapWaiter.Wait()
smtpWaiter.Wait()
}) })
}) })
} }

View File

@ -80,7 +80,7 @@ func TestBridge_Sync(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, info.State == bridge.Connected) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = client.Logout() }()
@ -127,7 +127,7 @@ func TestBridge_Sync(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, info.State == bridge.Connected) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = client.Logout() }()
@ -178,7 +178,7 @@ func _TestBridge_Sync_BadMessage(t *testing.T) { //nolint:unused,deadcode
require.NoError(t, err) require.NoError(t, err)
require.True(t, info.State == bridge.Connected) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = client.Logout() }()
@ -293,7 +293,7 @@ func TestBridge_SyncWithOngoingEvents(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.True(t, info.State == bridge.Connected) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = client.Logout() }()

View File

@ -444,14 +444,14 @@ func TestBridge_User_DropConn_NoBadEvent(t *testing.T) {
info, err := bridge.QueryUserInfo("user") info, err := bridge.QueryUserInfo("user")
require.NoError(t, err) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = cli.Logout() }()
// The IMAP client will eventually see 20 messages. // The IMAP client will eventually see 20 messages.
require.Eventually(t, func() bool { 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 return err == nil && status.Messages == 20
}, 10*time.Second, 100*time.Millisecond) }, 10*time.Second, 100*time.Millisecond)
}) })
@ -645,12 +645,12 @@ func TestBridge_User_SendDraftRemoveDraftFlag(t *testing.T) {
info, err := bridge.QueryUserInfo("user") info, err := bridge.QueryUserInfo("user")
require.NoError(t, err) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = cli.Logout() }()
messages, err := clientFetch(client, "Drafts") messages, err := clientFetch(cli, "Drafts")
require.NoError(t, err) require.NoError(t, err)
require.Len(t, messages, 1) require.Len(t, messages, 1)
require.Contains(t, messages[0].Flags, imap.DraftFlag) require.Contains(t, messages[0].Flags, imap.DraftFlag)
@ -684,12 +684,12 @@ func TestBridge_User_SendDraftRemoveDraftFlag(t *testing.T) {
info, err := bridge.QueryUserInfo("user") info, err := bridge.QueryUserInfo("user")
require.NoError(t, err) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = cli.Logout() }()
messages, err := clientFetch(client, "Sent") messages, err := clientFetch(cli, "Sent")
require.NoError(t, err) require.NoError(t, err)
require.Len(t, messages, 1) require.Len(t, messages, 1)
require.NotContains(t, messages[0].Flags, imap.DraftFlag) require.NotContains(t, messages[0].Flags, imap.DraftFlag)
@ -781,17 +781,21 @@ func TestBridge_User_HandleParentLabelRename(t *testing.T) {
imapWaiter := waitForIMAPServerReady(bridge) imapWaiter := waitForIMAPServerReady(bridge)
defer imapWaiter.Done() defer imapWaiter.Done()
smtpWaiter := waitForSMTPServerReady(bridge)
defer smtpWaiter.Done()
require.NoError(t, getErr(bridge.LoginFull(ctx, username, password, nil, nil))) require.NoError(t, getErr(bridge.LoginFull(ctx, username, password, nil, nil)))
info, err := bridge.QueryUserInfo(username) info, err := bridge.QueryUserInfo(username)
require.NoError(t, err) require.NoError(t, err)
imapWaiter.Wait() 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = cli.Logout() }()
withClient(ctx, t, s, username, password, func(ctx context.Context, c *proton.Client) { withClient(ctx, t, s, username, password, func(ctx context.Context, c *proton.Client) {
parentName := uuid.NewString() parentName := uuid.NewString()
@ -807,7 +811,7 @@ func TestBridge_User_HandleParentLabelRename(t *testing.T) {
// Wait for the parent folder to be created. // Wait for the parent folder to be created.
require.Eventually(t, func() bool { 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) return mailbox.Name == fmt.Sprintf("Folders/%v", parentName)
}) >= 0 }) >= 0
}, 100*user.EventPeriod, user.EventPeriod) }, 100*user.EventPeriod, user.EventPeriod)
@ -824,7 +828,7 @@ func TestBridge_User_HandleParentLabelRename(t *testing.T) {
// Wait for the parent folder to be created. // Wait for the parent folder to be created.
require.Eventually(t, func() bool { 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) return mailbox.Name == fmt.Sprintf("Folders/%v/%v", parentName, childName)
}) >= 0 }) >= 0
}, 100*user.EventPeriod, user.EventPeriod) }, 100*user.EventPeriod, user.EventPeriod)
@ -839,14 +843,14 @@ func TestBridge_User_HandleParentLabelRename(t *testing.T) {
// Wait for the parent folder to be renamed. // Wait for the parent folder to be renamed.
require.Eventually(t, func() bool { 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) return mailbox.Name == fmt.Sprintf("Folders/%v", newParentName)
}) >= 0 }) >= 0
}, 100*user.EventPeriod, user.EventPeriod) }, 100*user.EventPeriod, user.EventPeriod)
// Wait for the child folder to be renamed. // Wait for the child folder to be renamed.
require.Eventually(t, func() bool { 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) return mailbox.Name == fmt.Sprintf("Folders/%v/%v", newParentName, childName)
}) >= 0 }) >= 0
}, 100*user.EventPeriod, user.EventPeriod) }, 100*user.EventPeriod, user.EventPeriod)
@ -898,10 +902,10 @@ func userContinueEventProcess(
info, err := bridge.QueryUserInfo("user") info, err := bridge.QueryUserInfo("user")
require.NoError(t, err) 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, err)
require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) require.NoError(t, cli.Login(info.Addresses[0], string(info.BridgePass)))
defer func() { _ = client.Logout() }() defer func() { _ = cli.Logout() }()
randomLabel := uuid.NewString() randomLabel := uuid.NewString()
@ -916,8 +920,21 @@ func userContinueEventProcess(
// Wait for the label to be created. // Wait for the label to be created.
require.Eventually(t, func() bool { 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 return mailbox.Name == "Labels/"+randomLabel
}) >= 0 }) >= 0
}, 100*user.EventPeriod, user.EventPeriod) }, 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 ( import (
"fmt" "fmt"
"time"
"github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/constants"
"github.com/emersion/go-imap/client" "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 { 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 { if err != nil {
return err return err
} }
t.imapClients[clientID] = &imapClient{ t.imapClients[clientID] = &imapClient{
userID: userID, userID: userID,
client: client, client: cli,
} }
return nil 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) { func (t *testCtx) getIMAPClient(clientID string) (string, *client.Client) {
return t.imapClients[clientID].userID, t.imapClients[clientID].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 dummyListeners []net.Listener
imapServerStarted bool imapServerStarted bool
smtpServerStarted bool
} }
type imapClient struct { type imapClient struct {

View File

@ -1,7 +1,9 @@
Feature: Send Telemetry Heartbeat Feature: Send Telemetry Heartbeat
Background: Background:
Given there exists an account with username "[user:user1]" and password "password" 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 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 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:user]" has additional address "[alias:alias]@[domain]"
And the account "[user:user2]" has additional disabled address "[alias:alias2]@[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:user]" and password "password"
And the user logs in with username "[user:user2]" and password "password2" And the user logs in with username "[user:user2]" and password "password2"
Then it succeeds
Scenario: IMAP client can authenticate successfully Scenario: IMAP client can authenticate successfully
When user "[user:user]" connects IMAP client "1" When user "[user:user]" connects IMAP client "1"

View File

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

View File

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

View File

@ -6,10 +6,12 @@ Feature: IMAP delete mailbox
| one | folder | | one | folder |
| two | folder | | two | folder |
| three | label | | three | label |
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:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Delete folder Scenario: Delete folder
When IMAP client "1" deletes "Folders/one" When IMAP client "1" deletes "Folders/one"

View File

@ -1,10 +1,12 @@
Feature: IMAP Hide All Mail Feature: IMAP Hide All Mail
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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 logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Hide All Mail Mailbox Scenario: Hide All Mail Mailbox
Given IMAP client "1" eventually sees the following mailbox info: 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 | | from | to | subject | unread |
| a@example.com | a@example.com | one | true | | a@example.com | a@example.com | one | true |
| b@example.com | b@example.com | two | false | | 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 the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
Then it succeeds
Scenario: Mailbox status reports correct name, total and unread Scenario: Mailbox status reports correct name, total and unread
When user "[user:user]" connects and authenticates IMAP client "1" When user "[user:user]" connects and authenticates IMAP client "1"

View File

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

View File

@ -5,10 +5,12 @@ Feature: IMAP get mailbox info
| name | type | | name | type |
| f1 | folder | | f1 | folder |
| l1 | label | | l1 | label |
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:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Rename folder Scenario: Rename folder
When IMAP client "1" renames "Folders/f1" to "Folders/f2" When IMAP client "1" renames "Folders/f1" to "Folders/f2"

View File

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

View File

@ -5,10 +5,12 @@ Feature: IMAP select mailbox
| name | type | | name | type |
| mbox | folder | | mbox | folder |
| label | label | | label | label |
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:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Select inbox Scenario: Select inbox
When IMAP client "1" selects "INBOX" When IMAP client "1" selects "INBOX"

View File

@ -9,10 +9,12 @@ Feature: IMAP copy messages
| from | to | subject | unread | | from | to | subject | unread |
| john.doe@mail.com | [user:user]@[domain] | foo | false | | john.doe@mail.com | [user:user]@[domain] | foo | false |
| jane.doe@mail.com | name@[domain] | bar | true | | 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 the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Copy message to label Scenario: Copy message to label
When IMAP client "1" copies the message with subject "foo" from "INBOX" to "Labels/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: Background:
Given there exists an account with username "[user:user]" and password "password" Given there exists an account with username "[user:user]" and password "password"
And the account "[user:user]" has additional address "[alias:alias]@[domain]" 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 the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Creates message to user's primary address Scenario: Creates message to user's primary address
When IMAP client "1" appends the following messages to "INBOX": When IMAP client "1" appends the following messages to "INBOX":

View File

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

View File

@ -5,6 +5,7 @@ Feature: IMAP remove messages from Trash
| name | type | | name | type |
| mbox | folder | | mbox | folder |
| label | label | | label | label |
Then it succeeds
Scenario Outline: Message in Trash and some other label is not permanently deleted 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": 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 Feature: IMAP Draft messages
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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 logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
@ -11,12 +12,13 @@ Feature: IMAP Draft messages
This is a dra This is a dra
""" """
And it succeeds Then it succeeds
Then IMAP client "1" eventually sees the following messages in "Drafts": And IMAP client "1" eventually sees the following messages in "Drafts":
| body | | body |
| This is a dra | | This is a dra |
And IMAP client "1" eventually sees 1 messages in "Drafts" And IMAP client "1" eventually sees 1 messages in "Drafts"
Scenario: Draft edited locally Scenario: Draft edited locally
When IMAP client "1" marks message 1 as deleted When IMAP client "1" marks message 1 as deleted
And IMAP client "1" expunges 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": And the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Inbox":
| from | to | subject | date | | from | to | subject | date |
| john.doe@mail.com | [user:user]@[domain] | foo | 13 Jul 69 00:00 +0000 | | 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 the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Fetch very old message Scenario: Fetch very old message
Given IMAP client "1" eventually sees the following messages in "INBOX": Given IMAP client "1" eventually sees the following messages in "INBOX":

View File

@ -1,10 +1,12 @@
Feature: IMAP import messages Feature: IMAP import messages
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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 logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Basic message import Scenario: Basic message import
When IMAP client "1" appends the following message to "INBOX": 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": And the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Scheduled":
| from | to | subject | unread | | from | to | subject | unread |
| john.doe@mail.com | [user:user]@[domain] | sch | false | | 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 the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Move message from folder to label (keeps in folder) 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" 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: And the account "[user:user]" has the following custom mailboxes:
| name | type | | name | type |
| mbox | folder | | mbox | folder |
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:user]" and password "password"
And user "[user:user]" finishes syncing 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 "source"
And user "[user:user]" connects and authenticates IMAP client "target" And user "[user:user]" connects and authenticates IMAP client "target"
Then it succeeds
Scenario Outline: Move message from <srcMailbox> to <dstMailbox> by <order> Scenario Outline: Move message from <srcMailbox> to <dstMailbox> by <order>
When IMAP client "source" appends the following message to "<srcMailbox>": 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 | | jane.doe@mail.com | name@[domain] | bar | true |
And the account "[user:user]" has 20 custom folders And the account "[user:user]" has 20 custom folders
And the account "[user:user]" has 60 custom labels And the account "[user:user]" has 60 custom labels
Then it succeeds
When bridge starts When bridge starts
And the user logs in with username "[user:user]" and password "password" And the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing 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" Then IMAP client "1" counts 20 mailboxes under "Folders"
And IMAP client "1" counts 60 mailboxes under "Labels" 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 Feature: A user can connect an IMAP client to custom ports
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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 logs in with username "[user:user]" and password "password"
And the user changes the IMAP port to 1144 And the user changes the IMAP port to 1144
Then it succeeds
Scenario: Authenticates successfully on custom port Scenario: Authenticates successfully on custom port
When user "[user:user]" connects IMAP client "1" on port 1144 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:user]" has additional address "[alias:alias]@[domain]"
And the account "[user:user2]" has additional disabled address "[alias:alias2]@[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 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:user]" and password "password"
And the user logs in with username "[user:user2]" and password "password2" And the user logs in with username "[user:user2]" and password "password2"
And the user logs in with username "[user:user3]" and password "password3" And the user logs in with username "[user:user3]" and password "password3"
Then it succeeds
Scenario: SMTP client can authenticate successfully Scenario: SMTP client can authenticate successfully
When user "[user:user]" connects SMTP client "1" When user "[user:user]" connects SMTP client "1"

View File

@ -1,9 +1,11 @@
Feature: SMTP initiation Feature: SMTP initiation
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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 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 Scenario: Send without first announcing FROM and TO
When SMTP client "1" sends DATA: When SMTP client "1" sends DATA:

View File

@ -1,10 +1,12 @@
Feature: A user can connect an SMTP client to custom ports Feature: A user can connect an SMTP client to custom ports
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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 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 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 When user "[user:user]" connects SMTP client "1" on port 1144
Then SMTP client "1" can authenticate Then SMTP client "1" can authenticate

View File

@ -1,12 +1,14 @@
Feature: SMTP with bcc Feature: SMTP with bcc
Background: Background:
Given there exists an account with username "[user:user]" and password "password" Given there exists an account with username "[user:user]" and password "password"
Given there exists an account with username "[user:to]" and password "password" And there exists an account with username "[user:to]" and password "password"
Given there exists an account with username "[user:bcc]" and password "password" And there exists an account with username "[user:bcc]" 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:user]" and password "password"
And the user logs in with username "[user:bcc]" 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" And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Send message to address in to and bcc 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]": 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: Background:
Given there exists an account with username "[user:user]" and password "password" 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: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:user]" and password "password"
And the user logs in with username "[user:to]" 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" And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
@long-black @long-black
Scenario: Send it Scenario: Send it

View File

@ -2,9 +2,11 @@ Feature: SMTP wrong messages
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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: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:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1" And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Message with attachment and wrong boundaries Scenario: Message with attachment and wrong boundaries
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]": 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: Background:
Given there exists an account with username "[user:user]" and password "password" 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: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:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1" And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: HTML message to external account Scenario: HTML message to external account
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "pm.bridge.qa@gmail.com": 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: Background:
Given there exists an account with username "[user:user]" and password "password" 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: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:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1" And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: HTML message with attachment to internal account Scenario: HTML message with attachment to internal account
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]": 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: Background:
Given there exists an account with username "[user:user]" and password "password" 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: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:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1" And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: A message with inline attachment to internal account 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]": 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: Background:
Given there exists an account with username "[user:user]" and password "password" 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: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:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1" And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Mixed sender case in sender address Scenario: Mixed sender case in sender address
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]": 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: Background:
Given there exists an account with username "[user:user]" and password "password" 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 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:user]" and password "password"
And the user logs in with username "[user:recp]" and password "password" And the user logs in with username "[user:recp]" and password "password"
Then it succeeds
@long-black @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" 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:to]" and password "password"
And there exists an account with username "[user:cc]" 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 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 SMTP client "1"
Then it succeeds
Scenario: Only from and to headers to internal account 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]": 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: Background:
Given there exists an account with username "[user:user]" and password "password" 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: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:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1" And user "[user:user]" connects and authenticates SMTP client "1"
Then it succeeds
Scenario: Basic message with attachment to internal account Scenario: Basic message with attachment to internal account
When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]": 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: Background:
Given there exists an account with username "[user:user]" and password "password" 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: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:user]" and password "password"
And the user logs in with username "[user:to]" 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" And user "[user:user]" connects and authenticates SMTP client "1"

View File

@ -2,10 +2,12 @@ Feature: SMTP sending with APPENDing to Sent
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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: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:user]" and password "password"
And user "[user:user]" connects and authenticates SMTP client "1" And user "[user:user]" connects and authenticates SMTP client "1"
And user "[user:user]" connects and authenticates IMAP client "1" And user "[user:user]" connects and authenticates IMAP client "1"
Then it succeeds
Scenario: Send message and append to Sent Scenario: Send message and append to Sent
# First do sending. # First do sending.

View File

@ -3,11 +3,13 @@ Feature: SMTP send reply
Background: Background:
Given there exists an account with username "[user:user1]" and password "password" 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 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 the user logs in with username "[user:user1]" and password "password"
And user "[user:user1]" finishes syncing And user "[user:user1]" finishes syncing
And user "[user:user1]" connects and authenticates SMTP client "1" And user "[user:user1]" connects and authenticates SMTP client "1"
And user "[user:user1]" connects and authenticates IMAP client "1" And user "[user:user1]" connects and authenticates IMAP client "1"
Then it succeeds
@long-black @long-black
Scenario: Reply with In-Reply-To but no References 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 there exists an account with username "[user:multi]" and password "password"
And the account "[user:multi]" has additional address "[user:multi-alias]@[domain]" 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 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:user]" and password "password"
And the user logs in with username "[user:multi]" 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" And the user sets the address mode of user "[user:multi]" to "split"
Then it succeeds
Scenario: Send two messages in one connection Scenario: Send two messages in one connection
When user "[user:user]" connects and authenticates SMTP client "1" When user "[user:user]" connects and authenticates SMTP client "1"

View File

@ -14,9 +14,11 @@ Feature: Address mode
| from | to | subject | unread | | from | to | subject | unread |
| c@[domain] | c@[domain] | three | true | | c@[domain] | c@[domain] | three | true |
| d@[domain] | d@[domain] | four | false | | 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 the user logs in with username "[user:user]" and password "password"
And user "[user:user]" finishes syncing And user "[user:user]" finishes syncing
Then it succeeds
Scenario: The user is in combined mode Scenario: The user is in combined mode
When user "[user:user]" connects and authenticates IMAP client "1" with address "[user:user]@[domain]" 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 Feature: A user can be deleted
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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 logs in with username "[user:user]" and password "password"
Then it succeeds
Scenario: Delete a connected user Scenario: Delete a connected user
When user "[user:user]" is deleted When user "[user:user]" is deleted

View File

@ -1,9 +1,11 @@
Feature: A user can login Feature: A user can login
Background: Background:
Given there exists an account with username "[user:user]" and password "password" Given there exists an account with username "[user:user]" and password "password"
Given there exists an account with username "[user:MixedCaps]" and password "password" And 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 a disabled account with username "[user:disabled]" and password "password"
Then it succeeds
And bridge starts And bridge starts
Then it succeeds
Scenario: Login to account Scenario: Login to account
When the user logs in with username "[user:user]" and password "password" 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 Feature: A logged out user can login again
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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 logs in with username "[user:user]" and password "password"
Then it succeeds
Scenario: Login to disconnected account Scenario: Login to disconnected account
When user "[user:user]" logs out 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. Feature: A logged in user is logged out when its auth is revoked.
Background: Background:
Given there exists an account with username "[user:user]" and password "password" 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 logs in with username "[user:user]" and password "password"
Then it succeeds
Scenario: The auth is revoked while bridge is running Scenario: The auth is revoked while bridge is running
When the auth of user "[user:user]" is revoked 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 | | from | to | subject | unread |
| a@[domain] | a@[domain] | one | true | | a@[domain] | a@[domain] | one | true |
| b@[domain] | b@[domain] | two | false | | 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 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" When the user logs in with username "[user:user]" and password "password"

View File

@ -2,7 +2,9 @@ Feature: Bridge send usage metrics
Background: Background:
Given there exists an account with username "[user:user1]" and password "password" 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 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 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 { func (s *scenario) userLogsInWithUsernameAndPassword(username, password string) error {
evtCh, cancel := s.t.bridge.GetEvents(events.SMTPServerReady{}) smtpEvtCh, cancelSMTP := s.t.bridge.GetEvents(events.SMTPServerReady{})
defer cancel() 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) userID, err := s.t.bridge.LoginFull(context.Background(), username, []byte(password), nil, nil)
if err != 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 // 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. // blocking on multiple Logins.
if !s.t.imapServerStarted { if !s.t.imapServerStarted {
<-evtCh <-imapEvtCh
s.t.imapServerStarted = true s.t.imapServerStarted = true
} }
if !s.t.smtpServerStarted {
<-smtpEvtCh
s.t.smtpServerStarted = true
}
if userID != s.t.getUserByName(username).getUserID() { if userID != s.t.getUserByName(username).getUserID() {
return errors.New("user ID mismatch") return errors.New("user ID mismatch")