You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
5.7 KiB
201 lines
5.7 KiB
// Copyright (c) 2020 Proton Technologies AG |
|
// |
|
// This file is part of ProtonMail Bridge.Bridge. |
|
// |
|
// ProtonMail 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. |
|
// |
|
// ProtonMail 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 ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>. |
|
|
|
package benchmarks |
|
|
|
import ( |
|
"strings" |
|
"testing" |
|
"time" |
|
|
|
"github.com/ProtonMail/proton-bridge/test/context" |
|
"github.com/ProtonMail/proton-bridge/test/mocks" |
|
) |
|
|
|
func benchTestContext() (*context.TestContext, *mocks.IMAPClient) { |
|
ctx := context.New() |
|
|
|
username := "user" |
|
account := ctx.GetTestAccount(username) |
|
if account == nil { |
|
panic("account " + username + " does not exist") |
|
} |
|
|
|
_ = ctx.GetPMAPIController().AddUser(account.User(), account.Addresses(), account.Password(), account.IsTwoFAEnabled()) |
|
if err := ctx.LoginUser(account.Username(), account.Password(), account.MailboxPassword()); err != nil { |
|
panic(err) |
|
} |
|
|
|
imapClient := ctx.GetIMAPClient("client") |
|
imapClient.Login(account.Address(), account.BridgePassword()) |
|
|
|
// waitForSync between bridge and API. There is no way to know precisely |
|
// from the outside when the bridge is synced. We could wait for first |
|
// response from any fetch, but we don't know how many messages should be |
|
// there. Unless we hard code the number of messages. |
|
// Please, check this time is enough when doing benchmarks and don't forget |
|
// to exclude this time from total time. |
|
time.Sleep(10 * time.Second) |
|
|
|
return ctx, imapClient |
|
} |
|
|
|
func BenchmarkIMAPFetch(b *testing.B) { |
|
tc, c := benchTestContext() |
|
defer tc.Cleanup() |
|
|
|
c.Select("All Mail").AssertOK() |
|
|
|
fetchBench := []struct{ ids, args string }{ |
|
{"1:10", "rfc822.size"}, |
|
{"1:100", "rfc822.size"}, |
|
{"1:1000", "rfc822.size"}, |
|
{"1:*", "rfc822.size"}, |
|
} |
|
|
|
for _, bd := range fetchBench { |
|
ids, args := bd.ids, bd.args // pin |
|
b.Run(ids+"-"+args, func(b *testing.B) { |
|
for i := 0; i < b.N; i++ { |
|
c.Fetch(ids, args) |
|
} |
|
}) |
|
} |
|
} |
|
|
|
func BenchmarkCachingFetch(b *testing.B) { |
|
tc, c := benchTestContext() |
|
defer tc.Cleanup() |
|
|
|
c.Select("\"All Mail\"").AssertOK() |
|
|
|
ids := "1:100" |
|
args := "body.peek[]" |
|
tries := []string{"long", "short"} |
|
|
|
for _, try := range tries { |
|
b.Run(strings.Join([]string{ids, args, try}, "-"), func(b *testing.B) { |
|
for i := 0; i < b.N; i++ { |
|
c.Fetch(ids, args) |
|
} |
|
}) |
|
} |
|
} |
|
|
|
func BenchmarkIMAPAppleMail(b *testing.B) { |
|
tc, c := benchTestContext() |
|
defer tc.Cleanup() |
|
|
|
// assume we have at least 50 messages in INBOX |
|
idRange := "1:50" |
|
newUID := "50" // assume that Apple mail don't know about this mail |
|
|
|
// I will use raw send command to completely reproduce the calls |
|
// (including quotation and case sensitivity) |
|
b.Run("default", func(b *testing.B) { |
|
for i := 0; i < b.N; i++ { |
|
for _, command := range []string{ |
|
"CAPABILITY", |
|
"ID (" + |
|
`"name" "Mac OS X Mail" ` + |
|
`"version" "11.5 (3445.9.1)" ` + |
|
`"os" "Mac OS X" ` + |
|
`"os-version" "10.13.6 (17G3025)" ` + |
|
`"vendor" "Apple Inc."` + |
|
")", |
|
`LIST "" ""`, |
|
`STATUS INBOX (MESSAGES UIDNEXT UIDVALIDITY UNSEEN)`, |
|
`SELECT INBOX`, |
|
`FETCH ` + idRange + ` (FLAGS UID)`, |
|
`FETCH ` + idRange + " " + |
|
`(` + |
|
`INTERNALDATE UID RFC822.SIZE FLAGS ` + |
|
`BODY.PEEK[` + |
|
`HEADER.FIELDS (` + |
|
`date subject from to cc message-id in-reply-to references ` + |
|
`x-priority x-uniform-type-identifier x-universally-unique-identifier ` + |
|
`list-id list-unsubscribe` + |
|
`)])`, |
|
`UID FETCH ` + newUID + ` (BODYSTRUCTURE BODY.PEEK[HEADER])`, |
|
// if email has attachment it is splitted to several fetches |
|
//`UID FETCH 133 (BODY.PEEK[3]<0.5877469> BODY.PEEK[1] BODY.PEEK[2])`, |
|
//`UID FETCH 133 BODY.PEEK[3]<5877469.2925661>`, |
|
// here I will just use section download, which is used by AppleMail |
|
`UID FETCH ` + newUID + ` BODY.PEEK[1]`, |
|
// here I will just use partial download, which is used by AppleMail |
|
`UID FETCH ` + newUID + ` BODY.PEEK[]<0.2000>`, |
|
} { |
|
c.SendCommand(command).AssertOK() |
|
} |
|
} |
|
}) |
|
} |
|
|
|
func BenchmarkIMAPOutlook(b *testing.B) { |
|
tc, c := benchTestContext() |
|
defer tc.Cleanup() |
|
|
|
// assume we have at least 50 messages in INBOX |
|
idRange := "1:50" |
|
|
|
// I will use raw send command to completely reproduce the calls |
|
// (including quotation and case sensitivity) |
|
b.Run("default", func(b *testing.B) { |
|
for i := 0; i < b.N; i++ { |
|
for _, command := range []string{ |
|
|
|
/* |
|
"ID ("+ |
|
`"name" "Mac OS X Mail" `+ |
|
`"version" "11.5 (3445.9.1)" `+ |
|
`"os" "Mac OS X" `+ |
|
`"os-version" "10.13.6 (17G3025)" `+ |
|
`"vendor" "Apple Inc."`+ |
|
")", |
|
*/ |
|
|
|
`SELECT "INBOX"`, |
|
`UID SEARCH ` + idRange + ` SINCE 01-Sep-2019`, |
|
`UID FETCH 1:* (UID FLAGS)`, |
|
`UID FETCH ` + idRange + ` (UID FLAGS RFC822.SIZE BODY.PEEK[] INTERNALDATE)`, |
|
} { |
|
c.SendCommand(command).AssertOK() |
|
} |
|
} |
|
}) |
|
} |
|
|
|
func BenchmarkIMAPThunderbird(b *testing.B) { |
|
tc, c := benchTestContext() |
|
defer tc.Cleanup() |
|
|
|
// I will use raw send command to completely reproduce the calls |
|
// (including quotation and case sensitivity) |
|
b.Run("default", func(b *testing.B) { |
|
for i := 0; i < b.N; i++ { |
|
for _, command := range []string{ |
|
`capability`, |
|
`ID ("name" "Thunderbird" "version" "68.2.0")`, |
|
`select "INBOX"`, |
|
`getquotaroot "INBOX"`, |
|
`UID fetch 1:* (FLAGS)`, |
|
} { |
|
c.SendCommand(command).AssertOK() |
|
} |
|
} |
|
}) |
|
}
|
|
|