GODT-1815: Start without internet, load users later

This commit is contained in:
James Houlahan
2022-09-27 12:02:28 +02:00
parent 1da1188351
commit 612fb7ad7b
16 changed files with 243 additions and 175 deletions

View File

@ -109,6 +109,7 @@ func TestFeatures(testingT *testing.T) {
ctx.Step(`^user "([^"]*)" is deleted$`, s.userIsDeleted)
ctx.Step(`^the auth of user "([^"]*)" is revoked$`, s.theAuthOfUserIsRevoked)
ctx.Step(`^user "([^"]*)" is listed and connected$`, s.userIsListedAndConnected)
ctx.Step(`^user "([^"]*)" is eventually listed and connected$`, s.userIsEventuallyListedAndConnected)
ctx.Step(`^user "([^"]*)" is listed but not connected$`, s.userIsListedButNotConnected)
ctx.Step(`^user "([^"]*)" is not listed$`, s.userIsNotListed)
ctx.Step(`^user "([^"]*)" finishes syncing$`, s.userFinishesSyncing)

View File

@ -9,7 +9,6 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/ProtonMail/proton-bridge/v2/internal/events"
"gitlab.protontech.ch/go/liteapi"
)
func (s *scenario) bridgeStarts() error {
@ -85,9 +84,9 @@ func (s *scenario) theUserReportsABug() error {
}
func (s *scenario) bridgeSendsAConnectionUpEvent() error {
return try(s.t.connStatusCh, 5*time.Second, func(event events.ConnStatus) error {
if event.Status != liteapi.StatusUp {
return fmt.Errorf("expected connection up event, got %v", event.Status)
return try(s.t.connStatusCh, 5*time.Second, func(event events.Event) error {
if event, ok := event.(events.ConnStatusUp); !ok {
return fmt.Errorf("expected connection up event, got %T", event)
}
return nil
@ -95,9 +94,9 @@ func (s *scenario) bridgeSendsAConnectionUpEvent() error {
}
func (s *scenario) bridgeSendsAConnectionDownEvent() error {
return try(s.t.connStatusCh, 5*time.Second, func(event events.ConnStatus) error {
if event.Status != liteapi.StatusDown {
return fmt.Errorf("expected connection down event, got %v", event.Status)
return try(s.t.connStatusCh, 5*time.Second, func(event events.Event) error {
if event, ok := event.(events.ConnStatusDown); !ok {
return fmt.Errorf("expected connection down event, got %T", event)
}
return nil

View File

@ -54,7 +54,6 @@ func (t *testCtx) startBridge() error {
t.bridge = bridge
// Connect the event channels.
t.connStatusCh = chToType[events.Event, events.ConnStatus](bridge.GetEvents(events.ConnStatus{}))
t.userLoginCh = chToType[events.Event, events.UserLoggedIn](bridge.GetEvents(events.UserLoggedIn{}))
t.userLogoutCh = chToType[events.Event, events.UserLoggedOut](bridge.GetEvents(events.UserLoggedOut{}))
t.userDeletedCh = chToType[events.Event, events.UserDeleted](bridge.GetEvents(events.UserDeleted{}))
@ -62,6 +61,7 @@ func (t *testCtx) startBridge() error {
t.syncStartedCh = chToType[events.Event, events.SyncStarted](bridge.GetEvents(events.SyncStarted{}))
t.syncFinishedCh = chToType[events.Event, events.SyncFinished](bridge.GetEvents(events.SyncFinished{}))
t.forcedUpdateCh = chToType[events.Event, events.UpdateForced](bridge.GetEvents(events.UpdateForced{}))
t.connStatusCh, _ = bridge.GetEvents(events.ConnStatusUp{}, events.ConnStatusDown{})
t.updateCh, _ = bridge.GetEvents(events.UpdateAvailable{}, events.UpdateNotAvailable{}, events.UpdateInstalled{}, events.UpdateForced{})
return nil

View File

@ -22,6 +22,7 @@ type testCtx struct {
// These are the objects supporting the test.
dir string
api API
dialer *bridge.TestDialer
locator *locations.Locations
storeKey []byte
version *semver.Version
@ -31,7 +32,6 @@ type testCtx struct {
bridge *bridge.Bridge
// These channels hold events of various types coming from bridge.
connStatusCh <-chan events.ConnStatus
userLoginCh <-chan events.UserLoggedIn
userLogoutCh <-chan events.UserLoggedOut
userDeletedCh <-chan events.UserDeleted
@ -39,6 +39,7 @@ type testCtx struct {
syncStartedCh <-chan events.SyncStarted
syncFinishedCh <-chan events.SyncFinished
forcedUpdateCh <-chan events.UpdateForced
connStatusCh <-chan events.Event
updateCh <-chan events.Event
// These maps hold expected userIDByName, their primary addresses and bridge passwords.
@ -69,12 +70,15 @@ type smtpClient struct {
}
func newTestCtx(tb testing.TB) *testCtx {
dialer := bridge.NewTestDialer()
ctx := &testCtx{
dir: tb.TempDir(),
api: newFakeAPI(),
dialer: dialer,
locator: locations.New(bridge.NewTestLocationsProvider(tb), "config-name"),
storeKey: []byte("super-secret-store-key"),
mocks: bridge.NewMocks(tb, defaultVersion, defaultVersion),
mocks: bridge.NewMocks(tb, dialer, defaultVersion, defaultVersion),
version: defaultVersion,
userIDByName: make(map[string]string),

View File

@ -35,12 +35,12 @@ func (s *scenario) itFailsWithError(wantErr string) error {
}
func (s *scenario) internetIsTurnedOff() error {
s.t.mocks.TLSDialer.SetCanDial(false)
s.t.dialer.SetCanDial(false)
return nil
}
func (s *scenario) internetIsTurnedOn() error {
s.t.mocks.TLSDialer.SetCanDial(true)
s.t.dialer.SetCanDial(true)
return nil
}

View File

@ -20,6 +20,14 @@ Feature: A user can login
When the user logs in with username "user@pm.me" and password "password"
Then user "user@pm.me" is not listed
Scenario: Login to account without internet but the connection is later restored
When the user logs in with username "user@pm.me" and password "password"
And bridge stops
And the internet is turned off
And bridge starts
And the internet is turned on
Then user "user@pm.me" is eventually listed and connected
Scenario: Login to multiple accounts
Given there exists an account with username "additional@pm.me" and password "other"
When the user logs in with username "user@pm.me" and password "password"

View File

@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"time"
"github.com/ProtonMail/gluon/rfc822"
"github.com/bradenaw/juniper/xslices"
@ -182,6 +183,14 @@ func (s *scenario) userIsListedAndConnected(username string) error {
return nil
}
func (s *scenario) userIsEventuallyListedAndConnected(username string) error {
return eventually(
func() error { return s.userIsListedAndConnected(username) },
5*time.Second,
100*time.Millisecond,
)
}
func (s *scenario) userIsListedButNotConnected(username string) error {
user, err := s.t.bridge.GetUserInfo(s.t.getUserID(username))
if err != nil {