Other: Bump liteapi and clean up tests a bit

This commit is contained in:
James Houlahan
2022-10-20 02:41:43 +02:00
parent 04b6571cb8
commit c4343e0124
14 changed files with 259 additions and 89 deletions

View File

@ -231,9 +231,6 @@ bench:
coverage: test coverage: test
go tool cover -html=/tmp/coverage.out -o=coverage.html go tool cover -html=/tmp/coverage.out -o=coverage.html
integration-test-bridge:
${MAKE} -C test test-bridge
mocks: mocks:
mockgen --package mocks github.com/ProtonMail/proton-bridge/v2/internal/bridge TLSReporter,ProxyController,Autostarter > internal/bridge/mocks/mocks.go mockgen --package mocks github.com/ProtonMail/proton-bridge/v2/internal/bridge TLSReporter,ProxyController,Autostarter > internal/bridge/mocks/mocks.go
mockgen --package mocks github.com/ProtonMail/proton-bridge/v2/internal/updater Downloader,Installer > internal/updater/mocks/mocks.go mockgen --package mocks github.com/ProtonMail/proton-bridge/v2/internal/updater Downloader,Installer > internal/updater/mocks/mocks.go

2
go.mod
View File

@ -39,7 +39,7 @@ require (
github.com/sirupsen/logrus v1.9.0 github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.8.0
github.com/urfave/cli/v2 v2.16.3 github.com/urfave/cli/v2 v2.16.3
gitlab.protontech.ch/go/liteapi v0.34.4-0.20221019124718-218de25bbfd6 gitlab.protontech.ch/go/liteapi v0.34.4-0.20221020085018-bbcf03261c80
golang.org/x/exp v0.0.0-20220921164117-439092de6870 golang.org/x/exp v0.0.0-20220921164117-439092de6870
golang.org/x/net v0.1.0 golang.org/x/net v0.1.0
golang.org/x/sys v0.1.0 golang.org/x/sys v0.1.0

4
go.sum
View File

@ -401,8 +401,8 @@ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsr
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0= github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0=
github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA=
gitlab.protontech.ch/go/liteapi v0.34.4-0.20221019124718-218de25bbfd6 h1:D6tMRUg6C1VtnDVjqJkm10QHZJG5TLOPAslegS46nVg= gitlab.protontech.ch/go/liteapi v0.34.4-0.20221020085018-bbcf03261c80 h1:fxmLKxf1xsNAu6EBj+BPU1ChyZagXYhLHiqb7Jy1yOA=
gitlab.protontech.ch/go/liteapi v0.34.4-0.20221019124718-218de25bbfd6/go.mod h1:VCEA83UCi9f3XCP9W/XUIFnJKwokGB46lKUHBNzPWsQ= gitlab.protontech.ch/go/liteapi v0.34.4-0.20221020085018-bbcf03261c80/go.mod h1:VCEA83UCi9f3XCP9W/XUIFnJKwokGB46lKUHBNzPWsQ=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=

View File

@ -357,7 +357,7 @@ func TestBridge_MissingGluonDir(t *testing.T) {
// withEnv creates the full test environment and runs the tests. // withEnv creates the full test environment and runs the tests.
func withEnv(t *testing.T, tests func(context.Context, *server.Server, *liteapi.NetCtl, bridge.Locator, []byte)) { func withEnv(t *testing.T, tests func(context.Context, *server.Server, *liteapi.NetCtl, bridge.Locator, []byte)) {
server := server.NewTLS() server := server.New()
defer server.Close() defer server.Close()
withEnvServer(t, server, func(ctx context.Context, netCtl *liteapi.NetCtl, locator bridge.Locator, vaultKey []byte) { withEnvServer(t, server, func(ctx context.Context, netCtl *liteapi.NetCtl, locator bridge.Locator, vaultKey []byte) {

View File

@ -22,10 +22,13 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"testing" "testing"
"github.com/ProtonMail/proton-bridge/v2/internal/bridge" "github.com/ProtonMail/proton-bridge/v2/internal/bridge"
"github.com/ProtonMail/proton-bridge/v2/internal/events" "github.com/ProtonMail/proton-bridge/v2/internal/events"
"github.com/bradenaw/juniper/iterator"
"github.com/bradenaw/juniper/stream"
"github.com/emersion/go-imap/client" "github.com/emersion/go-imap/client"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gitlab.protontech.ch/go/liteapi" "gitlab.protontech.ch/go/liteapi"
@ -48,11 +51,44 @@ func TestBridge_Sync(t *testing.T) {
literal, err := os.ReadFile(filepath.Join("testdata", "text-plain.eml")) literal, err := os.ReadFile(filepath.Join("testdata", "text-plain.eml"))
require.NoError(t, err) require.NoError(t, err)
for i := 0; i < numMsg; i++ { c, _, err := liteapi.New(
messageID, err := s.CreateMessage(userID, addrID, literal, liteapi.MessageFlagReceived, false, false) liteapi.WithHostURL(s.GetHostURL()),
liteapi.WithTransport(liteapi.InsecureTransport()),
).NewClientWithLogin(ctx, "imap", password)
require.NoError(t, err) require.NoError(t, err)
require.NoError(t, s.LabelMessage(userID, messageID, labelID))
user, err := c.GetUser(ctx)
require.NoError(t, err)
addr, err := c.GetAddresses(ctx)
require.NoError(t, err)
require.Equal(t, addrID, addr[0].ID)
salt, err := c.GetSalts(ctx)
require.NoError(t, err)
keyPass, err := salt.SaltForKey(password, user.Keys.Primary().ID)
require.NoError(t, err)
_, addrKRs, err := liteapi.Unlock(user, addr, keyPass)
require.NoError(t, err)
require.NoError(t, getErr(stream.Collect(ctx, c.ImportMessages(
ctx,
addrKRs[addr[0].ID],
runtime.NumCPU(),
runtime.NumCPU(),
iterator.Collect(iterator.Map(iterator.Counter(numMsg), func(i int) liteapi.ImportReq {
return liteapi.ImportReq{
Metadata: liteapi.ImportMetadata{
AddressID: addr[0].ID,
LabelIDs: []string{labelID},
Flags: liteapi.MessageFlagReceived,
},
Message: literal,
} }
}))...,
))))
var read uint64 var read uint64

View File

@ -53,7 +53,7 @@ func TestTLSPinBackup(t *testing.T) {
} }
func TestTLSPinInvalid(t *testing.T) { func TestTLSPinInvalid(t *testing.T) {
s := server.NewTLS() s := server.New()
defer s.Close() defer s.Close()
called, _, _, _, cm := createClientWithPinningDialer(s.GetHostURL()) called, _, _, _, cm := createClientWithPinningDialer(s.GetHostURL())

View File

@ -213,13 +213,15 @@ func (conn *imapConnector) GetMessage(ctx context.Context, messageID imap.Messag
} }
// CreateMessage creates a new message on the remote. // CreateMessage creates a new message on the remote.
//
// nolint:funlen
func (conn *imapConnector) CreateMessage( func (conn *imapConnector) CreateMessage(
ctx context.Context, ctx context.Context,
mailboxID imap.MailboxID, mailboxID imap.MailboxID,
literal []byte, literal []byte,
flags imap.FlagSet, flags imap.FlagSet,
date time.Time, date time.Time,
) (imap.Message, []byte, error) { // nolint:funlen ) (imap.Message, []byte, error) {
var msgFlags liteapi.MessageFlag var msgFlags liteapi.MessageFlag
if mailboxID != liteapi.DraftsLabel { if mailboxID != liteapi.DraftsLabel {

View File

@ -100,7 +100,10 @@ func withAPI(_ *testing.T, ctx context.Context, fn func(context.Context, *server
server := server.New() server := server.New()
defer server.Close() defer server.Close()
fn(ctx, server, liteapi.New(liteapi.WithHostURL(server.GetHostURL()))) fn(ctx, server, liteapi.New(
liteapi.WithHostURL(server.GetHostURL()),
liteapi.WithTransport(liteapi.InsecureTransport()),
))
} }
func withAccount(t *testing.T, s *server.Server, username, password string, emails []string, fn func(string, []string)) { func withAccount(t *testing.T, s *server.Server, username, password string, emails []string, fn func(string, []string)) {

View File

@ -26,7 +26,6 @@ import (
"unicode/utf8" "unicode/utf8"
"github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/gluon/rfc822"
"github.com/emersion/go-message"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gitlab.protontech.ch/go/liteapi" "gitlab.protontech.ch/go/liteapi"
@ -38,7 +37,6 @@ import (
func init() { func init() {
rfc822.ParseMediaType = ParseMediaType rfc822.ParseMediaType = ParseMediaType
liteapi.CharsetReader = CharsetReader liteapi.CharsetReader = CharsetReader
message.CharsetReader = CharsetReader
} }
func CharsetReader(charset string, input io.Reader) (io.Reader, error) { func CharsetReader(charset string, input io.Reader) (io.Reader, error) {

View File

@ -19,7 +19,6 @@ package tests
import ( import (
"github.com/Masterminds/semver/v3" "github.com/Masterminds/semver/v3"
"gitlab.protontech.ch/go/liteapi"
"gitlab.protontech.ch/go/liteapi/server" "gitlab.protontech.ch/go/liteapi/server"
) )
@ -30,12 +29,10 @@ type API interface {
AddCallWatcher(func(server.Call), ...string) AddCallWatcher(func(server.Call), ...string)
CreateUser(username, address string, password []byte) (string, string, error) CreateUser(username, address string, password []byte) (string, string, error)
CreateAddress(userID, address string, password []byte) (string, error)
RemoveAddress(userID, addrID string) error
RevokeUser(userID string) error RevokeUser(userID string) error
GetLabels(userID string) ([]liteapi.Label, error) CreateAddress(userID, address string, password []byte) (string, error)
CreateLabel(userID, name string, labelType liteapi.LabelType) (string, error) RemoveAddress(userID, addrID string) error
Close() Close()
} }
@ -46,6 +43,6 @@ type fakeAPI struct {
func newFakeAPI() *fakeAPI { func newFakeAPI() *fakeAPI {
return &fakeAPI{ return &fakeAPI{
Server: server.NewTLS(), Server: server.New(),
} }
} }

87
tests/ctx_helper_test.go Normal file
View File

@ -0,0 +1,87 @@
// Copyright (c) 2022 Proton AG
//
// This file is part of Proton Mail Bridge.
//
// Proton Mail Bridge is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Proton Mail Bridge is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
package tests
import (
"context"
"runtime"
"github.com/bradenaw/juniper/stream"
"gitlab.protontech.ch/go/liteapi"
)
func (t *testCtx) withClient(ctx context.Context, username string, fn func(context.Context, *liteapi.Client) error) error {
c, _, err := liteapi.New(
liteapi.WithHostURL(t.api.GetHostURL()),
liteapi.WithTransport(liteapi.InsecureTransport()),
).NewClientWithLogin(ctx, username, []byte(t.getUserPass(t.getUserID(username))))
if err != nil {
return err
}
if err := fn(ctx, c); err != nil {
return err
}
if err := c.AuthDelete(ctx); err != nil {
return err
}
return c.Close()
}
func (t *testCtx) createMessages(ctx context.Context, username, addrID string, req []liteapi.ImportReq) error {
return t.withClient(ctx, username, func(ctx context.Context, c *liteapi.Client) error {
user, err := c.GetUser(ctx)
if err != nil {
return err
}
addr, err := c.GetAddresses(ctx)
if err != nil {
return err
}
salt, err := c.GetSalts(ctx)
if err != nil {
return err
}
keyPass, err := salt.SaltForKey([]byte(t.getUserPass(t.getUserID(username))), user.Keys.Primary().ID)
if err != nil {
return err
}
_, addrKRs, err := liteapi.Unlock(user, addr, keyPass)
if err != nil {
return err
}
if _, err := stream.Collect(ctx, c.ImportMessages(
ctx,
addrKRs[addrID],
runtime.NumCPU(),
runtime.NumCPU(),
req...,
)); err != nil {
return err
}
return nil
})
}

View File

@ -125,6 +125,16 @@ func (t *testCtx) beforeStep() {
t.errors = append(t.errors, nil) t.errors = append(t.errors, nil)
} }
func (t *testCtx) getName(wantUserID string) string {
for name, userID := range t.userIDByName {
if userID == wantUserID {
return name
}
}
panic(fmt.Sprintf("unknown user ID %q", wantUserID))
}
func (t *testCtx) getUserID(username string) string { func (t *testCtx) getUserID(username string) string {
return t.userIDByName[username] return t.userIDByName[username]
} }
@ -174,7 +184,13 @@ func (t *testCtx) setUserBridgePass(userID string, pass []byte) {
} }
func (t *testCtx) getMBoxID(userID string, name string) string { func (t *testCtx) getMBoxID(userID string, name string) string {
labels, err := t.api.GetLabels(userID) ctx, cancel := context.WithCancel(context.Background())
defer cancel()
var labelID string
if err := t.withClient(ctx, t.getName(userID), func(ctx context.Context, client *liteapi.Client) error {
labels, err := client.GetLabels(ctx, liteapi.LabelTypeLabel, liteapi.LabelTypeFolder, liteapi.LabelTypeSystem)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -187,7 +203,14 @@ func (t *testCtx) getMBoxID(userID string, name string) string {
panic(fmt.Errorf("label %q not found", name)) panic(fmt.Errorf("label %q not found", name))
} }
return labels[idx].ID labelID = labels[idx].ID
return nil
}); err != nil {
panic(err)
}
return labelID
} }
func (t *testCtx) getLastCall(method, path string) (server.Call, error) { func (t *testCtx) getLastCall(method, path string) (server.Call, error) {

View File

@ -68,9 +68,7 @@ func (msg Message) Build() []byte {
b = append(b, "Subject: "+msg.Subject+"\r\n"...) b = append(b, "Subject: "+msg.Subject+"\r\n"...)
} }
if msg.Body != "" {
b = append(b, "\r\n"+msg.Body+"\r\n"...) b = append(b, "\r\n"+msg.Body+"\r\n"...)
}
return b return b
} }

View File

@ -22,6 +22,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/bradenaw/juniper/iterator"
"github.com/bradenaw/juniper/xslices"
"github.com/cucumber/godog" "github.com/cucumber/godog"
"github.com/google/uuid" "github.com/google/uuid"
"gitlab.protontech.ch/go/liteapi" "gitlab.protontech.ch/go/liteapi"
@ -74,26 +76,45 @@ func (s *scenario) theAccountNoLongerHasAdditionalAddress(username, address stri
} }
func (s *scenario) theAccountHasCustomFolders(username string, count int) error { func (s *scenario) theAccountHasCustomFolders(username string, count int) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
return s.t.withClient(ctx, username, func(ctx context.Context, client *liteapi.Client) error {
for idx := 0; idx < count; idx++ { for idx := 0; idx < count; idx++ {
if _, err := s.t.api.CreateLabel(s.t.getUserID(username), uuid.NewString(), liteapi.LabelTypeFolder); err != nil { if _, err := client.CreateLabel(ctx, liteapi.CreateLabelReq{
Name: uuid.NewString(),
Type: liteapi.LabelTypeFolder,
}); err != nil {
return err return err
} }
} }
return nil return nil
})
} }
func (s *scenario) theAccountHasCustomLabels(username string, count int) error { func (s *scenario) theAccountHasCustomLabels(username string, count int) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
return s.t.withClient(ctx, username, func(ctx context.Context, client *liteapi.Client) error {
for idx := 0; idx < count; idx++ { for idx := 0; idx < count; idx++ {
if _, err := s.t.api.CreateLabel(s.t.getUserID(username), uuid.NewString(), liteapi.LabelTypeLabel); err != nil { if _, err := client.CreateLabel(ctx, liteapi.CreateLabelReq{
Name: uuid.NewString(),
Type: liteapi.LabelTypeLabel,
}); err != nil {
return err return err
} }
} }
return nil return nil
})
} }
func (s *scenario) theAccountHasTheFollowingCustomMailboxes(username string, table *godog.Table) error { func (s *scenario) theAccountHasTheFollowingCustomMailboxes(username string, table *godog.Table) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
type CustomMailbox struct { type CustomMailbox struct {
Name string `bdd:"name"` Name string `bdd:"name"`
Type string `bdd:"type"` Type string `bdd:"type"`
@ -104,6 +125,7 @@ func (s *scenario) theAccountHasTheFollowingCustomMailboxes(username string, tab
return err return err
} }
return s.t.withClient(ctx, username, func(ctx context.Context, client *liteapi.Client) error {
for _, wantMailbox := range wantMailboxes { for _, wantMailbox := range wantMailboxes {
var labelType liteapi.LabelType var labelType liteapi.LabelType
@ -115,15 +137,22 @@ func (s *scenario) theAccountHasTheFollowingCustomMailboxes(username string, tab
labelType = liteapi.LabelTypeLabel labelType = liteapi.LabelTypeLabel
} }
if _, err := s.t.api.CreateLabel(s.t.getUserID(username), wantMailbox.Name, labelType); err != nil { if _, err := client.CreateLabel(ctx, liteapi.CreateLabelReq{
Name: wantMailbox.Name,
Type: labelType,
}); err != nil {
return err return err
} }
} }
return nil return nil
})
} }
func (s *scenario) theAddressOfAccountHasTheFollowingMessagesInMailbox(address, username, mailbox string, table *godog.Table) error { func (s *scenario) theAddressOfAccountHasTheFollowingMessagesInMailbox(address, username, mailbox string, table *godog.Table) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
userID := s.t.getUserID(username) userID := s.t.getUserID(username)
addrID := s.t.getUserAddrID(userID, address) addrID := s.t.getUserAddrID(userID, address)
mboxID := s.t.getMBoxID(userID, mailbox) mboxID := s.t.getMBoxID(userID, mailbox)
@ -133,42 +162,42 @@ func (s *scenario) theAddressOfAccountHasTheFollowingMessagesInMailbox(address,
return err return err
} }
for _, wantMessage := range wantMessages { return s.t.createMessages(ctx, username, addrID, xslices.Map(wantMessages, func(message Message) liteapi.ImportReq {
messageID, err := s.t.api.CreateMessage(userID, addrID, wantMessage.Build(), liteapi.MessageFlagReceived, wantMessage.Unread, false) return liteapi.ImportReq{
if err != nil { Metadata: liteapi.ImportMetadata{
return err AddressID: addrID,
LabelIDs: []string{mboxID},
Unread: liteapi.Bool(message.Unread),
Flags: liteapi.MessageFlagReceived,
},
Message: message.Build(),
} }
}))
if err := s.t.api.LabelMessage(userID, messageID, mboxID); err != nil {
return err
}
}
return nil
} }
func (s *scenario) theAddressOfAccountHasMessagesInMailbox(address, username string, count int, mailbox string) error { func (s *scenario) theAddressOfAccountHasMessagesInMailbox(address, username string, count int, mailbox string) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
userID := s.t.getUserID(username) userID := s.t.getUserID(username)
addrID := s.t.getUserAddrID(userID, address) addrID := s.t.getUserAddrID(userID, address)
mboxID := s.t.getMBoxID(userID, mailbox) mboxID := s.t.getMBoxID(userID, mailbox)
for idx := 0; idx < count; idx++ { return s.t.createMessages(ctx, username, addrID, iterator.Collect(iterator.Map(iterator.Counter(count), func(idx int) liteapi.ImportReq {
messageID, err := s.t.api.CreateMessage(userID, addrID, Message{ return liteapi.ImportReq{
Metadata: liteapi.ImportMetadata{
AddressID: addrID,
LabelIDs: []string{mboxID},
Flags: liteapi.MessageFlagReceived,
},
Message: Message{
Subject: fmt.Sprintf("%d", idx), Subject: fmt.Sprintf("%d", idx),
To: fmt.Sprintf("%d@pm.me", idx), To: fmt.Sprintf("%d@pm.me", idx),
From: fmt.Sprintf("%d@pm.me", idx), From: fmt.Sprintf("%d@pm.me", idx),
Body: fmt.Sprintf("body %d", idx), Body: fmt.Sprintf("body %d", idx),
}.Build(), liteapi.MessageFlagReceived, idx%2 == 0, false) }.Build(),
if err != nil {
return err
} }
})))
if err := s.t.api.LabelMessage(userID, messageID, mboxID); err != nil {
return err
}
}
return nil
} }
func (s *scenario) userLogsInWithUsernameAndPassword(username, password string) error { func (s *scenario) userLogsInWithUsernameAndPassword(username, password string) error {