Clear separation of different message IDs in integration tests

This commit is contained in:
Michal Horejsek
2020-10-14 14:41:39 +02:00
parent 288ba11452
commit 43d54c8f4f
22 changed files with 261 additions and 220 deletions

View File

@ -9,6 +9,7 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
### Changed ### Changed
* Bump crypto version to v0.0.0-20200818122824-ed5d25e28db8 * Bump crypto version to v0.0.0-20200818122824-ed5d25e28db8
* GODT-785 Clear separation of different message IDs in integration tests.
## [IE 1.1.1] Danube (beta 2020-09-xx) [Bridge 1.4.1] Forth (beta 2020-09-xx) ## [IE 1.1.1] Danube (beta 2020-09-xx) [Bridge 1.4.1] Forth (beta 2020-09-xx)

View File

@ -73,6 +73,9 @@ type TestContext struct {
transferRemoteIMAPServer *mocks.IMAPServer transferRemoteIMAPServer *mocks.IMAPServer
transferProgress *transfer.Progress transferProgress *transfer.Progress
// Store releated variables.
bddMessageIDsToAPIIDs map[string]string
// These are the cleanup steps executed when Cleanup() is called. // These are the cleanup steps executed when Cleanup() is called.
cleanupSteps []*Cleaner cleanupSteps []*Cleaner
@ -89,18 +92,19 @@ func New(app string) *TestContext {
cm := pmapi.NewClientManager(cfg.GetAPIConfig()) cm := pmapi.NewClientManager(cfg.GetAPIConfig())
ctx := &TestContext{ ctx := &TestContext{
t: &bddT{}, t: &bddT{},
cfg: cfg, cfg: cfg,
listener: listener.New(), listener: listener.New(),
pmapiController: newPMAPIController(cm), pmapiController: newPMAPIController(cm),
clientManager: cm, clientManager: cm,
testAccounts: newTestAccounts(), testAccounts: newTestAccounts(),
credStore: newFakeCredStore(), credStore: newFakeCredStore(),
imapClients: make(map[string]*mocks.IMAPClient), imapClients: make(map[string]*mocks.IMAPClient),
imapLastResponses: make(map[string]*mocks.IMAPResponse), imapLastResponses: make(map[string]*mocks.IMAPResponse),
smtpClients: make(map[string]*mocks.SMTPClient), smtpClients: make(map[string]*mocks.SMTPClient),
smtpLastResponses: make(map[string]*mocks.SMTPResponse), smtpLastResponses: make(map[string]*mocks.SMTPResponse),
logger: logrus.StandardLogger(), bddMessageIDsToAPIIDs: make(map[string]string),
logger: logrus.StandardLogger(),
} }
// Ensure that the config is cleaned up after the test is over. // Ensure that the config is cleaned up after the test is over.

View File

@ -32,7 +32,6 @@ type PMAPIController interface {
AddUserLabel(username string, label *pmapi.Label) error AddUserLabel(username string, label *pmapi.Label) error
GetLabelIDs(username string, labelNames []string) ([]string, error) GetLabelIDs(username string, labelNames []string) ([]string, error)
AddUserMessage(username string, message *pmapi.Message) (string, error) AddUserMessage(username string, message *pmapi.Message) (string, error)
GetMessageID(username, messageIndex string) string
GetMessages(username, labelID string) ([]*pmapi.Message, error) GetMessages(username, labelID string) ([]*pmapi.Message, error)
ReorderAddresses(user *pmapi.User, addressIDs []string) error ReorderAddresses(user *pmapi.User, addressIDs []string) error
PrintCalls() PrintCalls()

39
test/context/store.go Normal file
View File

@ -0,0 +1,39 @@
// 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 context
import (
"errors"
)
// PairMessageID sets pairing between BDD message ID and API message ID.
func (ctx *TestContext) PairMessageID(username, bddMessageID, realMessageID string) {
if bddMessageID == "" {
return
}
ctx.bddMessageIDsToAPIIDs[username+":"+bddMessageID] = realMessageID
}
// GetAPIMessageID returns API message ID for given BDD message ID.
func (ctx *TestContext) GetAPIMessageID(username, bddMessageID string) (string, error) {
msgID, ok := ctx.bddMessageIDsToAPIIDs[username+":"+bddMessageID]
if !ok {
return "", errors.New("unknown bddMessageID")
}
return msgID, nil
}

View File

@ -156,10 +156,6 @@ func (ctl *Controller) resetUsers() {
} }
} }
func (ctl *Controller) GetMessageID(username, messageIndex string) string {
return messageIndex
}
func (ctl *Controller) GetMessages(username, labelID string) ([]*pmapi.Message, error) { func (ctl *Controller) GetMessages(username, labelID string) ([]*pmapi.Message, error) {
messages := []*pmapi.Message{} messages := []*pmapi.Message{}
for _, fakeAPI := range ctl.fakeAPIs { for _, fakeAPI := range ctl.fakeAPIs {

View File

@ -3,6 +3,7 @@ Feature: IMAP IDLE
Given there is connected user "user" Given there is connected user "user"
And there are 10 messages in mailbox "INBOX" for "user" And there are 10 messages in mailbox "INBOX" for "user"
# Those tests are ignored as currently our IMAP implementation is not responding with updates to all open connections.
@ignore @ignore
Scenario Outline: Mark as read Scenario Outline: Mark as read
Given there is IMAP client "active" logged in as "user" Given there is IMAP client "active" logged in as "user"
@ -10,15 +11,15 @@ Feature: IMAP IDLE
And there is IMAP client "idling" logged in as "user" And there is IMAP client "idling" logged in as "user"
And there is IMAP client "idling" selected in "INBOX" And there is IMAP client "idling" selected in "INBOX"
When IMAP client "idling" starts IDLE-ing When IMAP client "idling" starts IDLE-ing
And IMAP client "active" marks message "<message>" as read And IMAP client "active" marks message seq "<seq>" as read
Then IMAP client "idling" receives update marking message "<message>" as read within <seconds> seconds Then IMAP client "idling" receives update marking message seq "<seq>" as read within <seconds> seconds
Then message "<message>" in "INBOX" for "user" is marked as read Then message "<seq>" in "INBOX" for "user" is marked as read
Examples: Examples:
| message | seconds | | seq | seconds |
| 1 | 2 | | 1 | 2 |
| 1:5 | 2 | | 1:5 | 2 |
| 1:10 | 5 | | 1:10 | 5 |
@ignore @ignore
Scenario Outline: Mark as unread Scenario Outline: Mark as unread
@ -27,15 +28,15 @@ Feature: IMAP IDLE
And there is IMAP client "idling" logged in as "user" And there is IMAP client "idling" logged in as "user"
And there is IMAP client "idling" selected in "INBOX" And there is IMAP client "idling" selected in "INBOX"
When IMAP client "idling" starts IDLE-ing When IMAP client "idling" starts IDLE-ing
And IMAP client "active" marks message "<message>" as unread And IMAP client "active" marks message seq "<seq>" as unread
Then IMAP client "idling" receives update marking message "<message>" as unread within <seconds> seconds Then IMAP client "idling" receives update marking message seq "<seq>" as unread within <seconds> seconds
And message "<message>" in "INBOX" for "user" is marked as unread And message "<seq>" in "INBOX" for "user" is marked as unread
Examples: Examples:
| message | seconds | | seq | seconds |
| 1 | 2 | | 1 | 2 |
| 1:5 | 2 | | 1:5 | 2 |
| 1:10 | 5 | | 1:10 | 5 |
@ignore @ignore
Scenario Outline: Three IDLEing Scenario Outline: Three IDLEing
@ -50,13 +51,13 @@ Feature: IMAP IDLE
When IMAP client "idling1" starts IDLE-ing When IMAP client "idling1" starts IDLE-ing
And IMAP client "idling2" starts IDLE-ing And IMAP client "idling2" starts IDLE-ing
And IMAP client "idling3" starts IDLE-ing And IMAP client "idling3" starts IDLE-ing
And IMAP client "active" marks message "<message>" as read And IMAP client "active" marks message seq "<seq>" as read
Then IMAP client "idling1" receives update marking message "<message>" as read within <seconds> seconds Then IMAP client "idling1" receives update marking message seq "<seq>" as read within <seconds> seconds
Then IMAP client "idling2" receives update marking message "<message>" as read within <seconds> seconds Then IMAP client "idling2" receives update marking message seq "<seq>" as read within <seconds> seconds
Then IMAP client "idling3" receives update marking message "<message>" as read within <seconds> seconds Then IMAP client "idling3" receives update marking message seq "<seq>" as read within <seconds> seconds
Examples: Examples:
| message | seconds | | seq | seconds |
| 1 | 2 | | 1 | 2 |
| 1:5 | 2 | | 1:5 | 2 |
| 1:10 | 5 | | 1:10 | 5 |

View File

@ -8,8 +8,8 @@ Feature: IMAP IDLE with two users
And there is IMAP client "idling" logged in as "userMoreAddresses" And there is IMAP client "idling" logged in as "userMoreAddresses"
And there is IMAP client "idling" selected in "INBOX" And there is IMAP client "idling" selected in "INBOX"
When IMAP client "idling" starts IDLE-ing When IMAP client "idling" starts IDLE-ing
And IMAP client "active" marks message "1" as read And IMAP client "active" marks message seq "1" as read
Then IMAP client "idling" does not receive update for message "1" within 5 seconds Then IMAP client "idling" does not receive update for message seq "1" within 5 seconds
Scenario: IDLE statements are not leaked to other alias Scenario: IDLE statements are not leaked to other alias
Given there is connected user "userMoreAddresses" Given there is connected user "userMoreAddresses"
@ -24,5 +24,5 @@ Feature: IMAP IDLE with two users
And there is IMAP client "idling" logged in as "userMoreAddresses" with address "secondary" And there is IMAP client "idling" logged in as "userMoreAddresses" with address "secondary"
And there is IMAP client "idling" selected in "INBOX" And there is IMAP client "idling" selected in "INBOX"
When IMAP client "idling" starts IDLE-ing When IMAP client "idling" starts IDLE-ing
And IMAP client "active" marks message "1" as read And IMAP client "active" marks message seq "1" as read
Then IMAP client "idling" does not receive update for message "1" within 5 seconds Then IMAP client "idling" does not receive update for message seq "1" within 5 seconds

View File

@ -10,9 +10,6 @@ Feature: IMAP get mailbox info
Scenario: Mailbox info contains mailbox name Scenario: Mailbox info contains mailbox name
When IMAP client gets info of "INBOX" When IMAP client gets info of "INBOX"
Then IMAP response contains "2 EXISTS" Then IMAP response contains "2 EXISTS"
# Messages are inserted in opposite way to keep increasing UID. And IMAP response contains "UNSEEN 1"
# Sequence numbers are then opposite than listed above.
# Unseen should have first unseen message.
And IMAP response contains "UNSEEN 2"
And IMAP response contains "UIDNEXT 3" And IMAP response contains "UIDNEXT 3"
And IMAP response contains "UIDVALIDITY" And IMAP response contains "UIDVALIDITY"

View File

@ -12,9 +12,8 @@ Feature: IMAP get mailbox status
When IMAP client gets status of "INBOX" When IMAP client gets status of "INBOX"
Then IMAP response contains "INBOX" Then IMAP response contains "INBOX"
Scenario: Mailbox status contains Scenario: Mailbox status contains counts and UIDs
When IMAP client gets status of "INBOX" When IMAP client gets status of "INBOX"
Then IMAP response contains "INBOX"
And IMAP response contains "MESSAGES 2" And IMAP response contains "MESSAGES 2"
And IMAP response contains "UNSEEN 1" And IMAP response contains "UNSEEN 1"
And IMAP response contains "UIDNEXT 3" And IMAP response contains "UIDNEXT 3"

View File

@ -3,8 +3,6 @@ Feature: IMAP copy messages
Given there is connected user "user" Given there is connected user "user"
And there is "user" with mailbox "Folders/mbox" And there is "user" with mailbox "Folders/mbox"
And there is "user" with mailbox "Labels/label" And there is "user" with mailbox "Labels/label"
# Messages are inserted in opposite way to keep increasing ID.
# Sequence numbers are then opposite than listed above.
And there are messages in mailbox "INBOX" for "user" And there are messages in mailbox "INBOX" for "user"
| from | to | subject | body | read | deleted | | from | to | subject | body | read | deleted |
| john.doe@mail.com | user@pm.me | foo | hello | true | false | | john.doe@mail.com | user@pm.me | foo | hello | true | false |
@ -13,7 +11,7 @@ Feature: IMAP copy messages
And there is IMAP client selected in "INBOX" And there is IMAP client selected in "INBOX"
Scenario: Copy message to label Scenario: Copy message to label
When IMAP client copies messages "2" to "Labels/label" When IMAP client copies message seq "1" to "Labels/label"
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "INBOX" for "user" has messages And mailbox "INBOX" for "user" has messages
| from | to | subject | body | read | deleted | | from | to | subject | body | read | deleted |
@ -24,7 +22,7 @@ Feature: IMAP copy messages
| john.doe@mail.com | user@pm.me | foo | hello | true | false | | john.doe@mail.com | user@pm.me | foo | hello | true | false |
Scenario: Copy all messages to label Scenario: Copy all messages to label
When IMAP client copies messages "1:*" to "Labels/label" When IMAP client copies message seq "1:*" to "Labels/label"
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "INBOX" for "user" has messages And mailbox "INBOX" for "user" has messages
| from | to | subject | body | read | deleted | | from | to | subject | body | read | deleted |
@ -36,7 +34,7 @@ Feature: IMAP copy messages
| jane.doe@mail.com | name@pm.me | bar | world | false | true | | jane.doe@mail.com | name@pm.me | bar | world | false | true |
Scenario: Copy message to folder does move Scenario: Copy message to folder does move
When IMAP client copies messages "2" to "Folders/mbox" When IMAP client copies message seq "1" to "Folders/mbox"
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "INBOX" for "user" has messages And mailbox "INBOX" for "user" has messages
| from | to | subject | body | read | deleted | | from | to | subject | body | read | deleted |
@ -46,7 +44,7 @@ Feature: IMAP copy messages
| john.doe@mail.com | user@pm.me | foo | hello | true | false | | john.doe@mail.com | user@pm.me | foo | hello | true | false |
Scenario: Copy all messages to folder does move Scenario: Copy all messages to folder does move
When IMAP client copies messages "1:*" to "Folders/mbox" When IMAP client copies message seq "1:*" to "Folders/mbox"
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "INBOX" for "user" has 0 messages And mailbox "INBOX" for "user" has 0 messages
And mailbox "Folders/mbox" for "user" has messages And mailbox "Folders/mbox" for "user" has messages

View File

@ -34,7 +34,7 @@ Feature: IMAP create messages
Then IMAP response is "OK" Then IMAP response is "OK"
When the event loop of "userMoreAddresses" loops once When the event loop of "userMoreAddresses" loops once
Then mailbox "Sent" for "userMoreAddresses" has messages Then mailbox "Sent" for "userMoreAddresses" has messages
| from | to | subject | read | | from | to | subject | read |
| [secondary] | john.doe@email.com | foo | true | | [secondary] | john.doe@email.com | foo | true |
And mailbox "INBOX" for "userMoreAddresses" has no messages And mailbox "INBOX" for "userMoreAddresses" has no messages

View File

@ -8,10 +8,10 @@ Feature: IMAP remove messages from mailbox
Given there are 10 messages in mailbox "<mailbox>" for "user" Given there are 10 messages in mailbox "<mailbox>" for "user"
And there is IMAP client logged in as "user" And there is IMAP client logged in as "user"
And there is IMAP client selected in "<mailbox>" And there is IMAP client selected in "<mailbox>"
When IMAP client marks message "2" as deleted When IMAP client marks message seq "2" as deleted
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "<mailbox>" for "user" has 10 messages And mailbox "<mailbox>" for "user" has 10 messages
And message "9" in "<mailbox>" for "user" is marked as deleted And message "2" in "<mailbox>" for "user" is marked as deleted
And IMAP response contains "\* 2 FETCH[ (]*FLAGS \([^)]*\\Deleted" And IMAP response contains "\* 2 FETCH[ (]*FLAGS \([^)]*\\Deleted"
When IMAP client sends expunge When IMAP client sends expunge
Then IMAP response is "OK" Then IMAP response is "OK"
@ -30,7 +30,7 @@ Feature: IMAP remove messages from mailbox
Given there are 5 messages in mailbox "<mailbox>" for "user" Given there are 5 messages in mailbox "<mailbox>" for "user"
And there is IMAP client logged in as "user" And there is IMAP client logged in as "user"
And there is IMAP client selected in "<mailbox>" And there is IMAP client selected in "<mailbox>"
When IMAP client marks message "1:*" as deleted When IMAP client marks message seq "1:*" as deleted
Then IMAP response is "OK" Then IMAP response is "OK"
When IMAP client sends expunge When IMAP client sends expunge
Then IMAP response is "OK" Then IMAP response is "OK"
@ -53,9 +53,9 @@ Feature: IMAP remove messages from mailbox
Given there are 5 messages in mailbox "<mailbox>" for "user" Given there are 5 messages in mailbox "<mailbox>" for "user"
And there is IMAP client logged in as "user" And there is IMAP client logged in as "user"
And there is IMAP client selected in "<mailbox>" And there is IMAP client selected in "<mailbox>"
When IMAP client marks message "1:*" as deleted When IMAP client marks message seq "1:*" as deleted
Then IMAP response is "OK" Then IMAP response is "OK"
When IMAP client marks message "1:3" as undeleted When IMAP client marks message seq "1:3" as undeleted
Then IMAP response is "OK" Then IMAP response is "OK"
When IMAP client sends expunge When IMAP client sends expunge
Then IMAP response is "OK" Then IMAP response is "OK"
@ -75,10 +75,10 @@ Feature: IMAP remove messages from mailbox
Given there are 10 messages in mailbox "INBOX" for "user" Given there are 10 messages in mailbox "INBOX" for "user"
And there is IMAP client logged in as "user" And there is IMAP client logged in as "user"
And there is IMAP client selected in "INBOX" And there is IMAP client selected in "INBOX"
When IMAP client marks message "2" as deleted When IMAP client marks message seq "2" as deleted
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "INBOX" for "user" has 10 messages And mailbox "INBOX" for "user" has 10 messages
And message "9" in "INBOX" for "user" is marked as deleted And message "2" in "INBOX" for "user" is marked as deleted
When IMAP client sends command "<leave>" When IMAP client sends command "<leave>"
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "INBOX" for "user" has <n> messages And mailbox "INBOX" for "user" has <n> messages
@ -97,5 +97,5 @@ Feature: IMAP remove messages from mailbox
Given there are 1 messages in mailbox "INBOX" for "user" Given there are 1 messages in mailbox "INBOX" for "user"
And there is IMAP client logged in as "user" And there is IMAP client logged in as "user"
And there is IMAP client selected in "All Mail" And there is IMAP client selected in "All Mail"
When IMAP client marks message "1" as deleted When IMAP client marks message seq "1" as deleted
Then IMAP response is "IMAP error: NO operation not allowed for 'All Mail' folder" Then IMAP response is "IMAP error: NO operation not allowed for 'All Mail' folder"

View File

@ -6,14 +6,14 @@ Feature: IMAP remove messages from Trash
Scenario Outline: Message in Trash/Spam and some other label is not permanently deleted Scenario Outline: Message in Trash/Spam and some other label is not permanently deleted
Given there are messages in mailbox "<mailbox>" for "user" Given there are messages in mailbox "<mailbox>" for "user"
| from | to | subject | body | | id | from | to | subject | body |
| john.doe@mail.com | user@pm.me | foo | hello | | 1 | john.doe@mail.com | user@pm.me | foo | hello |
| jane.doe@mail.com | name@pm.me | bar | world | | 2 | jane.doe@mail.com | name@pm.me | bar | world |
And there is IMAP client logged in as "user" And there is IMAP client logged in as "user"
And there is IMAP client selected in "<mailbox>" And there is IMAP client selected in "<mailbox>"
When IMAP client copies messages "2" to "Labels/label" When IMAP client copies message seq "2" to "Labels/label"
Then IMAP response is "OK" Then IMAP response is "OK"
When IMAP client marks message "2" as deleted When IMAP client marks message seq "2" as deleted
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "<mailbox>" for "user" has 2 messages And mailbox "<mailbox>" for "user" has 2 messages
And mailbox "All Mail" for "user" has 2 messages And mailbox "All Mail" for "user" has 2 messages
@ -31,12 +31,12 @@ Feature: IMAP remove messages from Trash
Scenario Outline: Message in Trash/Spam only is permanently deleted Scenario Outline: Message in Trash/Spam only is permanently deleted
Given there are messages in mailbox "<mailbox>" for "user" Given there are messages in mailbox "<mailbox>" for "user"
| from | to | subject | body | | id | from | to | subject | body |
| john.doe@mail.com | user@pm.me | foo | hello | | 1 | john.doe@mail.com | user@pm.me | foo | hello |
| jane.doe@mail.com | name@pm.me | bar | world | | 2 | jane.doe@mail.com | name@pm.me | bar | world |
And there is IMAP client logged in as "user" And there is IMAP client logged in as "user"
And there is IMAP client selected in "<mailbox>" And there is IMAP client selected in "<mailbox>"
When IMAP client marks message "2" as deleted When IMAP client marks message seq "2" as deleted
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "<mailbox>" for "user" has 2 messages And mailbox "<mailbox>" for "user" has 2 messages
And mailbox "All Mail" for "user" has 2 messages And mailbox "All Mail" for "user" has 2 messages

View File

@ -2,8 +2,6 @@ Feature: IMAP move messages
Background: Background:
Given there is connected user "user" Given there is connected user "user"
And there is "user" with mailbox "Folders/mbox" And there is "user" with mailbox "Folders/mbox"
# Messages are inserted in opposite way to keep increasing ID.
# Sequence numbers are then opposite than listed above.
And there are messages in mailbox "INBOX" for "user" And there are messages in mailbox "INBOX" for "user"
| from | to | subject | body | | from | to | subject | body |
| john.doe@mail.com | user@pm.me | foo | hello | | john.doe@mail.com | user@pm.me | foo | hello |
@ -12,7 +10,7 @@ Feature: IMAP move messages
And there is IMAP client selected in "INBOX" And there is IMAP client selected in "INBOX"
Scenario: Move message Scenario: Move message
When IMAP client moves messages "2" to "Folders/mbox" When IMAP client moves message seq "1" to "Folders/mbox"
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "INBOX" for "user" has messages And mailbox "INBOX" for "user" has messages
| from | to | subject | | from | to | subject |
@ -22,7 +20,7 @@ Feature: IMAP move messages
| john.doe@mail.com | user@pm.me | foo | | john.doe@mail.com | user@pm.me | foo |
Scenario: Move all messages Scenario: Move all messages
When IMAP client moves messages "1:*" to "Folders/mbox" When IMAP client moves message seq "1:*" to "Folders/mbox"
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "INBOX" for "user" has 0 messages And mailbox "INBOX" for "user" has 0 messages
And mailbox "Folders/mbox" for "user" has messages And mailbox "Folders/mbox" for "user" has messages
@ -31,7 +29,7 @@ Feature: IMAP move messages
| jane.doe@mail.com | name@pm.me | bar | | jane.doe@mail.com | name@pm.me | bar |
Scenario: Move message from All Mail is not possible Scenario: Move message from All Mail is not possible
When IMAP client moves messages "2" to "Folders/mbox" When IMAP client moves message seq "1" to "Folders/mbox"
Then IMAP response is "OK" Then IMAP response is "OK"
And mailbox "All Mail" for "user" has messages And mailbox "All Mail" for "user" has messages
| from | to | subject | | from | to | subject |

View File

@ -6,15 +6,13 @@ Feature: IMAP move messages by append and delete (without MOVE support, e.g., Ou
And there is IMAP client "target" logged in as "user" And there is IMAP client "target" logged in as "user"
Scenario Outline: Move message from INBOX to mailbox by append and delete Scenario Outline: Move message from INBOX to mailbox by append and delete
# Messages are inserted in opposite way to keep increasing ID.
# Sequence numbers are then opposite than listed below.
Given there are messages in mailbox "INBOX" for "user" Given there are messages in mailbox "INBOX" for "user"
| from | to | subject | body | | id | from | to | subject | body |
| john.doe@mail.com | user@pm.me | foo | hello | | 1 | john.doe@mail.com | user@pm.me | foo | hello |
| jane.doe@mail.com | name@pm.me | bar | world | | 2 | jane.doe@mail.com | name@pm.me | bar | world |
And there is IMAP client "source" selected in "INBOX" And there is IMAP client "source" selected in "INBOX"
And there is IMAP client "target" selected in "<mailbox>" And there is IMAP client "target" selected in "<mailbox>"
When IMAP clients "source" and "target" move message "1" of "user" from "INBOX" to "<mailbox>" by append and delete When IMAP clients "source" and "target" move message seq "2" of "user" from "INBOX" to "<mailbox>" by append and delete
Then IMAP response to "source" is "OK" Then IMAP response to "source" is "OK"
Then IMAP response to "target" is "OK" Then IMAP response to "target" is "OK"
When IMAP client "source" sends expunge When IMAP client "source" sends expunge
@ -34,15 +32,13 @@ Feature: IMAP move messages by append and delete (without MOVE support, e.g., Ou
| Trash | | Trash |
Scenario Outline: Move message from Trash/Spam to INBOX by append and delete Scenario Outline: Move message from Trash/Spam to INBOX by append and delete
# Messages are inserted in opposite way to keep increasing ID.
# Sequence numbers are then opposite than listed below.
Given there are messages in mailbox "<mailbox>" for "user" Given there are messages in mailbox "<mailbox>" for "user"
| from | to | subject | body | | id | from | to | subject | body |
| john.doe@mail.com | user@pm.me | foo | hello | | 1 | john.doe@mail.com | user@pm.me | foo | hello |
| jane.doe@mail.com | name@pm.me | bar | world | | 2 | jane.doe@mail.com | name@pm.me | bar | world |
And there is IMAP client "source" selected in "<mailbox>" And there is IMAP client "source" selected in "<mailbox>"
And there is IMAP client "target" selected in "INBOX" And there is IMAP client "target" selected in "INBOX"
When IMAP clients "source" and "target" move message "1" of "user" from "<mailbox>" to "INBOX" by append and delete When IMAP clients "source" and "target" move message seq "2" of "user" from "<mailbox>" to "INBOX" by append and delete
Then IMAP response to "source" is "OK" Then IMAP response to "source" is "OK"
Then IMAP response to "target" is "OK" Then IMAP response to "target" is "OK"
When IMAP client "source" sends expunge When IMAP client "source" sends expunge

View File

@ -1,8 +1,6 @@
Feature: IMAP search messages Feature: IMAP search messages
Background: Background:
Given there is connected user "user" Given there is connected user "user"
# Messages are inserted in opposite way to keep increasing ID.
# Sequence numbers are then opposite than listed above.
Given there are messages in mailbox "INBOX" for "user" Given there are messages in mailbox "INBOX" for "user"
| from | to | cc | subject | read | starred | deleted | body | | from | to | cc | subject | read | starred | deleted | body |
| john.doe@email.com | user@pm.me | | foo | false | false | false | hello | | john.doe@email.com | user@pm.me | | foo | false | false | false | hello |
@ -34,17 +32,17 @@ Feature: IMAP search messages
Scenario: Search by Subject Scenario: Search by Subject
When IMAP client searches for "SUBJECT foo" When IMAP client searches for "SUBJECT foo"
Then IMAP response is "OK" Then IMAP response is "OK"
And IMAP response contains "SEARCH 3[^0-9]*$" And IMAP response contains "SEARCH 1[^0-9]*$"
Scenario: Search by From Scenario: Search by From
When IMAP client searches for "FROM jane.doe@email.com" When IMAP client searches for "FROM jane.doe@email.com"
Then IMAP response is "OK" Then IMAP response is "OK"
And IMAP response contains "SEARCH 1 2[^0-9]*$" And IMAP response contains "SEARCH 2 3[^0-9]*$"
Scenario: Search by To Scenario: Search by To
When IMAP client searches for "TO user@pm.me" When IMAP client searches for "TO user@pm.me"
Then IMAP response is "OK" Then IMAP response is "OK"
And IMAP response contains "SEARCH 2 3[^0-9]*$" And IMAP response contains "SEARCH 1 2[^0-9]*$"
Scenario: Search by CC Scenario: Search by CC
When IMAP client searches for "CC name@pm.me" When IMAP client searches for "CC name@pm.me"
@ -64,22 +62,22 @@ Feature: IMAP search messages
Scenario: Search seen messages Scenario: Search seen messages
When IMAP client searches for "SEEN" When IMAP client searches for "SEEN"
Then IMAP response is "OK" Then IMAP response is "OK"
And IMAP response contains "SEARCH 1 2[^0-9]*$" And IMAP response contains "SEARCH 2 3[^0-9]*$"
Scenario: Search unseen messages Scenario: Search unseen messages
When IMAP client searches for "UNSEEN" When IMAP client searches for "UNSEEN"
Then IMAP response is "OK" Then IMAP response is "OK"
And IMAP response contains "SEARCH 3[^0-9]*$" And IMAP response contains "SEARCH 1[^0-9]*$"
Scenario: Search deleted messages Scenario: Search deleted messages
When IMAP client searches for "DELETED" When IMAP client searches for "DELETED"
Then IMAP response is "OK" Then IMAP response is "OK"
And IMAP response contains "SEARCH 1[^0-9]*$" And IMAP response contains "SEARCH 3[^0-9]*$"
Scenario: Search undeleted messages Scenario: Search undeleted messages
When IMAP client searches for "UNDELETED" When IMAP client searches for "UNDELETED"
Then IMAP response is "OK" Then IMAP response is "OK"
And IMAP response contains "SEARCH 2 3[^0-9]*$" And IMAP response contains "SEARCH 1 2[^0-9]*$"
Scenario: Search recent messages Scenario: Search recent messages
When IMAP client searches for "RECENT" When IMAP client searches for "RECENT"
@ -89,4 +87,4 @@ Feature: IMAP search messages
Scenario: Search by more criterias Scenario: Search by more criterias
When IMAP client searches for "SUBJECT baz TO name@pm.me SEEN UNFLAGGED" When IMAP client searches for "SUBJECT baz TO name@pm.me SEEN UNFLAGGED"
Then IMAP response is "OK" Then IMAP response is "OK"
And IMAP response contains "SEARCH 1[^0-9]*$" And IMAP response contains "SEARCH 3[^0-9]*$"

View File

@ -1,23 +1,21 @@
Feature: IMAP update messages Feature: IMAP update messages
Background: Background:
Given there is connected user "user" Given there is connected user "user"
# Messages are inserted in opposite way to keep increasing ID.
# Sequence numbers are then opposite than listed above.
And there are messages in mailbox "INBOX" for "user" And there are messages in mailbox "INBOX" for "user"
| from | to | subject | body | read | starred | deleted | | id | from | to | subject | body | read | starred | deleted |
| john.doe@mail.com | user@pm.me | foo | hello | false | false | false | | 1 | john.doe@mail.com | user@pm.me | foo | hello | false | false | false |
| jane.doe@mail.com | name@pm.me | bar | world | true | true | false | | 2 | jane.doe@mail.com | name@pm.me | bar | world | true | true | false |
And there is IMAP client logged in as "user" And there is IMAP client logged in as "user"
And there is IMAP client selected in "INBOX" And there is IMAP client selected in "INBOX"
Scenario: Mark message as read Scenario: Mark message as read
When IMAP client marks message "2" as read When IMAP client marks message seq "1" as read
Then IMAP response is "OK" Then IMAP response is "OK"
And message "1" in "INBOX" for "user" is marked as read And message "1" in "INBOX" for "user" is marked as read
And message "1" in "INBOX" for "user" is marked as unstarred And message "1" in "INBOX" for "user" is marked as unstarred
Scenario: Mark message as unread Scenario: Mark message as unread
When IMAP client marks message "1" as unread When IMAP client marks message seq "2" as unread
Then IMAP response is "OK" Then IMAP response is "OK"
And message "2" in "INBOX" for "user" is marked as unread And message "2" in "INBOX" for "user" is marked as unread
And message "2" in "INBOX" for "user" is marked as starred And message "2" in "INBOX" for "user" is marked as starred
@ -25,32 +23,32 @@ Feature: IMAP update messages
Scenario: Mark message as starred Scenario: Mark message as starred
Then message "1" in "INBOX" for "user" is marked as unread Then message "1" in "INBOX" for "user" is marked as unread
And message "1" in "INBOX" for "user" is marked as unstarred And message "1" in "INBOX" for "user" is marked as unstarred
When IMAP client marks message "2" as starred When IMAP client marks message seq "1" as starred
Then IMAP response is "OK" Then IMAP response is "OK"
And message "1" in "INBOX" for "user" is marked as unread And message "1" in "INBOX" for "user" is marked as unread
And message "1" in "INBOX" for "user" is marked as starred And message "1" in "INBOX" for "user" is marked as starred
Scenario: Mark message as unstarred Scenario: Mark message as unstarred
When IMAP client marks message "1" as unstarred When IMAP client marks message seq "2" as unstarred
Then IMAP response is "OK" Then IMAP response is "OK"
And message "2" in "INBOX" for "user" is marked as read And message "2" in "INBOX" for "user" is marked as read
And message "2" in "INBOX" for "user" is marked as unstarred And message "2" in "INBOX" for "user" is marked as unstarred
Scenario: Mark message as read and starred Scenario: Mark message as read and starred
When IMAP client marks message "2" with "\Seen \Flagged" When IMAP client marks message seq "1" with "\Seen \Flagged"
Then IMAP response is "OK" Then IMAP response is "OK"
And message "1" in "INBOX" for "user" is marked as read And message "1" in "INBOX" for "user" is marked as read
And message "1" in "INBOX" for "user" is marked as starred And message "1" in "INBOX" for "user" is marked as starred
Scenario: Mark message as read only Scenario: Mark message as read only
When IMAP client marks message "1" with "\Seen" When IMAP client marks message seq "2" with "\Seen"
Then IMAP response is "OK" Then IMAP response is "OK"
And message "2" in "INBOX" for "user" is marked as read And message "2" in "INBOX" for "user" is marked as read
# Unstarred because we set flags without \Starred. # Unstarred because we set flags without \Starred.
And message "2" in "INBOX" for "user" is marked as unstarred And message "2" in "INBOX" for "user" is marked as unstarred
Scenario: Mark message as spam only Scenario: Mark message as spam only
When IMAP client marks message "1" with "Junk" When IMAP client marks message seq "2" with "Junk"
Then IMAP response is "OK" Then IMAP response is "OK"
# Unread and unstarred because we set flags without \Seen and \Starred. # Unread and unstarred because we set flags without \Seen and \Starred.
And message "1" in "Spam" for "user" is marked as unread And message "1" in "Spam" for "user" is marked as unread
@ -59,23 +57,23 @@ Feature: IMAP update messages
Scenario: Mark message as deleted Scenario: Mark message as deleted
# Mark message as Starred so we can check that mark as Deleted is not # Mark message as Starred so we can check that mark as Deleted is not
# tempering with Starred flag # tempering with Starred flag
When IMAP client marks message "1" as starred When IMAP client marks message seq "2" as starred
Then IMAP response is "OK" Then IMAP response is "OK"
When IMAP client marks message "1" as deleted When IMAP client marks message seq "2" as deleted
Then IMAP response is "OK" Then IMAP response is "OK"
And message "2" in "INBOX" for "user" is marked as read And message "2" in "INBOX" for "user" is marked as read
And message "2" in "INBOX" for "user" is marked as starred And message "2" in "INBOX" for "user" is marked as starred
And message "2" in "INBOX" for "user" is marked as deleted And message "2" in "INBOX" for "user" is marked as deleted
Scenario: Mark message as undeleted Scenario: Mark message as undeleted
When IMAP client marks message "1" as undeleted When IMAP client marks message seq "2" as undeleted
Then IMAP response is "OK" Then IMAP response is "OK"
And message "2" in "INBOX" for "user" is marked as read And message "2" in "INBOX" for "user" is marked as read
And message "2" in "INBOX" for "user" is marked as starred And message "2" in "INBOX" for "user" is marked as starred
And message "2" in "INBOX" for "user" is marked as undeleted And message "2" in "INBOX" for "user" is marked as undeleted
Scenario: Mark message as deleted only Scenario: Mark message as deleted only
When IMAP client marks message "1" with "\Deleted" When IMAP client marks message seq "2" with "\Deleted"
Then IMAP response is "OK" Then IMAP response is "OK"
And message "2" in "INBOX" for "user" is marked as unread And message "2" in "INBOX" for "user" is marked as unread
And message "2" in "INBOX" for "user" is marked as unstarred And message "2" in "INBOX" for "user" is marked as unstarred

View File

@ -32,28 +32,28 @@ func IMAPActionsMessagesFeatureContext(s *godog.Suite) {
s.Step(`^IMAP client fetches "([^"]*)"$`, imapClientFetches) s.Step(`^IMAP client fetches "([^"]*)"$`, imapClientFetches)
s.Step(`^IMAP client fetches by UID "([^"]*)"$`, imapClientFetchesByUID) s.Step(`^IMAP client fetches by UID "([^"]*)"$`, imapClientFetchesByUID)
s.Step(`^IMAP client searches for "([^"]*)"$`, imapClientSearchesFor) s.Step(`^IMAP client searches for "([^"]*)"$`, imapClientSearchesFor)
s.Step(`^IMAP client copies messages "([^"]*)" to "([^"]*)"$`, imapClientCopiesMessagesTo) s.Step(`^IMAP client copies message seq "([^"]*)" to "([^"]*)"$`, imapClientCopiesMessagesTo)
s.Step(`^IMAP client moves messages "([^"]*)" to "([^"]*)"$`, imapClientMovesMessagesTo) s.Step(`^IMAP client moves message seq "([^"]*)" to "([^"]*)"$`, imapClientMovesMessagesTo)
s.Step(`^IMAP clients "([^"]*)" and "([^"]*)" move message "([^"]*)" of "([^"]*)" from "([^"]*)" to "([^"]*)" by append and delete$`, imapClientsMoveMessageOfUserFromToByAppendAndDelete) s.Step(`^IMAP clients "([^"]*)" and "([^"]*)" move message seq "([^"]*)" of "([^"]*)" from "([^"]*)" to "([^"]*)" by append and delete$`, imapClientsMoveMessageSeqOfUserFromToByAppendAndDelete)
s.Step(`^IMAP client imports message to "([^"]*)"$`, imapClientCreatesMessage) s.Step(`^IMAP client imports message to "([^"]*)"$`, imapClientCreatesMessage)
s.Step(`^IMAP client imports message to "([^"]*)" with encoding "([^"]*)"$`, imapClientCreatesMessageWithEncoding) s.Step(`^IMAP client imports message to "([^"]*)" with encoding "([^"]*)"$`, imapClientCreatesMessageWithEncoding)
s.Step(`^IMAP client creates message "([^"]*)" from "([^"]*)" to "([^"]*)" with body "([^"]*)" in "([^"]*)"$`, imapClientCreatesMessageFromToWithBody) s.Step(`^IMAP client creates message "([^"]*)" from "([^"]*)" to "([^"]*)" with body "([^"]*)" in "([^"]*)"$`, imapClientCreatesMessageFromToWithBody)
s.Step(`^IMAP client creates message "([^"]*)" from "([^"]*)" to address "([^"]*)" of "([^"]*)" with body "([^"]*)" in "([^"]*)"$`, imapClientCreatesMessageFromToAddressOfUserWithBody) s.Step(`^IMAP client creates message "([^"]*)" from "([^"]*)" to address "([^"]*)" of "([^"]*)" with body "([^"]*)" in "([^"]*)"$`, imapClientCreatesMessageFromToAddressOfUserWithBody)
s.Step(`^IMAP client creates message "([^"]*)" from address "([^"]*)" of "([^"]*)" to "([^"]*)" with body "([^"]*)" in "([^"]*)"$`, imapClientCreatesMessageFromAddressOfUserToWithBody) s.Step(`^IMAP client creates message "([^"]*)" from address "([^"]*)" of "([^"]*)" to "([^"]*)" with body "([^"]*)" in "([^"]*)"$`, imapClientCreatesMessageFromAddressOfUserToWithBody)
s.Step(`^IMAP client marks message "([^"]*)" with "([^"]*)"$`, imapClientMarksMessageWithFlags) s.Step(`^IMAP client marks message seq "([^"]*)" with "([^"]*)"$`, imapClientMarksMessageSeqWithFlags)
s.Step(`^IMAP client "([^"]*)" marks message "([^"]*)" with "([^"]*)"$`, imapClientNamedMarksMessageWithFlags) s.Step(`^IMAP client "([^"]*)" marks message seq "([^"]*)" with "([^"]*)"$`, imapClientNamedMarksMessageSeqWithFlags)
s.Step(`^IMAP client marks message "([^"]*)" as read$`, imapClientMarksMessageAsRead) s.Step(`^IMAP client marks message seq "([^"]*)" as read$`, imapClientMarksMessageSeqAsRead)
s.Step(`^IMAP client "([^"]*)" marks message "([^"]*)" as read$`, imapClientNamedMarksMessageAsRead) s.Step(`^IMAP client "([^"]*)" marks message seq "([^"]*)" as read$`, imapClientNamedMarksMessageSeqAsRead)
s.Step(`^IMAP client marks message "([^"]*)" as unread$`, imapClientMarksMessageAsUnread) s.Step(`^IMAP client marks message seq "([^"]*)" as unread$`, imapClientMarksMessageSeqAsUnread)
s.Step(`^IMAP client "([^"]*)" marks message "([^"]*)" as unread$`, imapClientNamedMarksMessageAsUnread) s.Step(`^IMAP client "([^"]*)" marks message seq "([^"]*)" as unread$`, imapClientNamedMarksMessageSeqAsUnread)
s.Step(`^IMAP client marks message "([^"]*)" as starred$`, imapClientMarksMessageAsStarred) s.Step(`^IMAP client marks message seq "([^"]*)" as starred$`, imapClientMarksMessageSeqAsStarred)
s.Step(`^IMAP client "([^"]*)" marks message "([^"]*)" as starred$`, imapClientNamedMarksMessageAsStarred) s.Step(`^IMAP client "([^"]*)" marks message seq "([^"]*)" as starred$`, imapClientNamedMarksMessageSeqAsStarred)
s.Step(`^IMAP client marks message "([^"]*)" as unstarred$`, imapClientMarksMessageAsUnstarred) s.Step(`^IMAP client marks message seq "([^"]*)" as unstarred$`, imapClientMarksMessageSeqAsUnstarred)
s.Step(`^IMAP client "([^"]*)" marks message "([^"]*)" as unstarred$`, imapClientNamedMarksMessageAsUnstarred) s.Step(`^IMAP client "([^"]*)" marks message seq "([^"]*)" as unstarred$`, imapClientNamedMarksMessageSeqAsUnstarred)
s.Step(`^IMAP client marks message "([^"]*)" as deleted$`, imapClientMarksMessageAsDeleted) s.Step(`^IMAP client marks message seq "([^"]*)" as deleted$`, imapClientMarksMessageSeqAsDeleted)
s.Step(`^IMAP client "([^"]*)" marks message "([^"]*)" as deleted$`, imapClientNamedMarksMessageAsDeleted) s.Step(`^IMAP client "([^"]*)" marks message seq "([^"]*)" as deleted$`, imapClientNamedMarksMessageSeqAsDeleted)
s.Step(`^IMAP client marks message "([^"]*)" as undeleted$`, imapClientMarksMessageAsUndeleted) s.Step(`^IMAP client marks message seq "([^"]*)" as undeleted$`, imapClientMarksMessageSeqAsUndeleted)
s.Step(`^IMAP client "([^"]*)" marks message "([^"]*)" as undeleted$`, imapClientNamedMarksMessageAsUndeleted) s.Step(`^IMAP client "([^"]*)" marks message seq "([^"]*)" as undeleted$`, imapClientNamedMarksMessageSeqAsUndeleted)
s.Step(`^IMAP client starts IDLE-ing$`, imapClientStartsIDLEing) s.Step(`^IMAP client starts IDLE-ing$`, imapClientStartsIDLEing)
s.Step(`^IMAP client "([^"]*)" starts IDLE-ing$`, imapClientNamedStartsIDLEing) s.Step(`^IMAP client "([^"]*)" starts IDLE-ing$`, imapClientNamedStartsIDLEing)
s.Step(`^IMAP client sends expunge$`, imapClientExpunge) s.Step(`^IMAP client sends expunge$`, imapClientExpunge)
@ -84,19 +84,19 @@ func imapClientSearchesFor(query string) error {
return nil return nil
} }
func imapClientCopiesMessagesTo(messageRange, newMailboxName string) error { func imapClientCopiesMessagesTo(messageSeq, newMailboxName string) error {
res := ctx.GetIMAPClient("imap").Copy(messageRange, newMailboxName) res := ctx.GetIMAPClient("imap").Copy(messageSeq, newMailboxName)
ctx.SetIMAPLastResponse("imap", res) ctx.SetIMAPLastResponse("imap", res)
return nil return nil
} }
func imapClientMovesMessagesTo(messageRange, newMailboxName string) error { func imapClientMovesMessagesTo(messageSeq, newMailboxName string) error {
res := ctx.GetIMAPClient("imap").Move(messageRange, newMailboxName) res := ctx.GetIMAPClient("imap").Move(messageSeq, newMailboxName)
ctx.SetIMAPLastResponse("imap", res) ctx.SetIMAPLastResponse("imap", res)
return nil return nil
} }
func imapClientsMoveMessageOfUserFromToByAppendAndDelete(sourceIMAPClient, targetIMAPClient, messageUID, bddUserID, sourceMailboxName, targetMailboxName string) error { func imapClientsMoveMessageSeqOfUserFromToByAppendAndDelete(sourceIMAPClient, targetIMAPClient, messageSeq, bddUserID, sourceMailboxName, targetMailboxName string) error {
account := ctx.GetTestAccount(bddUserID) account := ctx.GetTestAccount(bddUserID)
if account == nil { if account == nil {
return godog.ErrPending return godog.ErrPending
@ -105,7 +105,7 @@ func imapClientsMoveMessageOfUserFromToByAppendAndDelete(sourceIMAPClient, targe
if err != nil { if err != nil {
return internalError(err, "getting store mailbox") return internalError(err, "getting store mailbox")
} }
uid, err := strconv.ParseUint(messageUID, 10, 32) uid, err := strconv.ParseUint(messageSeq, 10, 32)
if err != nil { if err != nil {
return internalError(err, "parsing message UID") return internalError(err, "parsing message UID")
} }
@ -136,7 +136,7 @@ func imapClientsMoveMessageOfUserFromToByAppendAndDelete(sourceIMAPClient, targe
go func() { go func() {
defer wg.Done() defer wg.Done()
_ = imapClientNamedMarksMessageAsDeleted(sourceIMAPClient, messageUID) _ = imapClientNamedMarksMessageSeqAsDeleted(sourceIMAPClient, messageSeq)
}() }()
wg.Wait() wg.Wait()
@ -195,72 +195,72 @@ func imapClientCreatesMessageFromAddressOfUserToWithBody(subject, bddAddressID,
return imapClientCreatesMessageFromToWithBody(subject, account.Address(), to, body, mailboxName) return imapClientCreatesMessageFromToWithBody(subject, account.Address(), to, body, mailboxName)
} }
func imapClientMarksMessageWithFlags(messageRange, flags string) error { func imapClientMarksMessageSeqWithFlags(messageSeq, flags string) error {
return imapClientNamedMarksMessageWithFlags("imap", messageRange, flags) return imapClientNamedMarksMessageSeqWithFlags("imap", messageSeq, flags)
} }
func imapClientNamedMarksMessageWithFlags(imapClient, messageRange, flags string) error { func imapClientNamedMarksMessageSeqWithFlags(imapClient, messageSeq, flags string) error {
res := ctx.GetIMAPClient(imapClient).SetFlags(messageRange, flags) res := ctx.GetIMAPClient(imapClient).SetFlags(messageSeq, flags)
ctx.SetIMAPLastResponse(imapClient, res) ctx.SetIMAPLastResponse(imapClient, res)
return nil return nil
} }
func imapClientMarksMessageAsRead(messageRange string) error { func imapClientMarksMessageSeqAsRead(messageSeq string) error {
return imapClientNamedMarksMessageAsRead("imap", messageRange) return imapClientNamedMarksMessageSeqAsRead("imap", messageSeq)
} }
func imapClientNamedMarksMessageAsRead(imapClient, messageRange string) error { func imapClientNamedMarksMessageSeqAsRead(imapClient, messageSeq string) error {
res := ctx.GetIMAPClient(imapClient).MarkAsRead(messageRange) res := ctx.GetIMAPClient(imapClient).MarkAsRead(messageSeq)
ctx.SetIMAPLastResponse(imapClient, res) ctx.SetIMAPLastResponse(imapClient, res)
return nil return nil
} }
func imapClientMarksMessageAsUnread(messageRange string) error { func imapClientMarksMessageSeqAsUnread(messageSeq string) error {
return imapClientNamedMarksMessageAsUnread("imap", messageRange) return imapClientNamedMarksMessageSeqAsUnread("imap", messageSeq)
} }
func imapClientNamedMarksMessageAsUnread(imapClient, messageRange string) error { func imapClientNamedMarksMessageSeqAsUnread(imapClient, messageSeq string) error {
res := ctx.GetIMAPClient(imapClient).MarkAsUnread(messageRange) res := ctx.GetIMAPClient(imapClient).MarkAsUnread(messageSeq)
ctx.SetIMAPLastResponse(imapClient, res) ctx.SetIMAPLastResponse(imapClient, res)
return nil return nil
} }
func imapClientMarksMessageAsStarred(messageRange string) error { func imapClientMarksMessageSeqAsStarred(messageSeq string) error {
return imapClientNamedMarksMessageAsStarred("imap", messageRange) return imapClientNamedMarksMessageSeqAsStarred("imap", messageSeq)
} }
func imapClientNamedMarksMessageAsStarred(imapClient, messageRange string) error { func imapClientNamedMarksMessageSeqAsStarred(imapClient, messageSeq string) error {
res := ctx.GetIMAPClient(imapClient).MarkAsStarred(messageRange) res := ctx.GetIMAPClient(imapClient).MarkAsStarred(messageSeq)
ctx.SetIMAPLastResponse(imapClient, res) ctx.SetIMAPLastResponse(imapClient, res)
return nil return nil
} }
func imapClientMarksMessageAsUnstarred(messageRange string) error { func imapClientMarksMessageSeqAsUnstarred(messageSeq string) error {
return imapClientNamedMarksMessageAsUnstarred("imap", messageRange) return imapClientNamedMarksMessageSeqAsUnstarred("imap", messageSeq)
} }
func imapClientNamedMarksMessageAsUnstarred(imapClient, messageRange string) error { func imapClientNamedMarksMessageSeqAsUnstarred(imapClient, messageSeq string) error {
res := ctx.GetIMAPClient(imapClient).MarkAsUnstarred(messageRange) res := ctx.GetIMAPClient(imapClient).MarkAsUnstarred(messageSeq)
ctx.SetIMAPLastResponse(imapClient, res) ctx.SetIMAPLastResponse(imapClient, res)
return nil return nil
} }
func imapClientMarksMessageAsDeleted(messageRange string) error { func imapClientMarksMessageSeqAsDeleted(messageSeq string) error {
return imapClientNamedMarksMessageAsDeleted("imap", messageRange) return imapClientNamedMarksMessageSeqAsDeleted("imap", messageSeq)
} }
func imapClientNamedMarksMessageAsDeleted(imapClient, messageRange string) error { func imapClientNamedMarksMessageSeqAsDeleted(imapClient, messageSeq string) error {
res := ctx.GetIMAPClient(imapClient).MarkAsDeleted(messageRange) res := ctx.GetIMAPClient(imapClient).MarkAsDeleted(messageSeq)
ctx.SetIMAPLastResponse(imapClient, res) ctx.SetIMAPLastResponse(imapClient, res)
return nil return nil
} }
func imapClientMarksMessageAsUndeleted(messageRange string) error { func imapClientMarksMessageSeqAsUndeleted(messageSeq string) error {
return imapClientNamedMarksMessageAsUndeleted("imap", messageRange) return imapClientNamedMarksMessageSeqAsUndeleted("imap", messageSeq)
} }
func imapClientNamedMarksMessageAsUndeleted(imapClient, messageRange string) error { func imapClientNamedMarksMessageSeqAsUndeleted(imapClient, messageSeq string) error {
res := ctx.GetIMAPClient(imapClient).MarkAsUndeleted(messageRange) res := ctx.GetIMAPClient(imapClient).MarkAsUndeleted(messageSeq)
ctx.SetIMAPLastResponse(imapClient, res) ctx.SetIMAPLastResponse(imapClient, res)
return nil return nil
} }

View File

@ -32,11 +32,11 @@ func IMAPChecksFeatureContext(s *godog.Suite) {
s.Step(`^IMAP response to "([^"]*)" contains "([^"]*)"$`, imapResponseNamedContains) s.Step(`^IMAP response to "([^"]*)" contains "([^"]*)"$`, imapResponseNamedContains)
s.Step(`^IMAP response has (\d+) message(?:s)?$`, imapResponseHasNumberOfMessages) s.Step(`^IMAP response has (\d+) message(?:s)?$`, imapResponseHasNumberOfMessages)
s.Step(`^IMAP response to "([^"]*)" has (\d+) message(?:s)?$`, imapResponseNamedHasNumberOfMessages) s.Step(`^IMAP response to "([^"]*)" has (\d+) message(?:s)?$`, imapResponseNamedHasNumberOfMessages)
s.Step(`^IMAP client receives update marking message "([^"]*)" as read within (\d+) seconds$`, imapClientReceivesUpdateMarkingMessagesAsReadWithin) s.Step(`^IMAP client receives update marking message seq "([^"]*)" as read within (\d+) seconds$`, imapClientReceivesUpdateMarkingMessageSeqAsReadWithin)
s.Step(`^IMAP client "([^"]*)" receives update marking message "([^"]*)" as read within (\d+) seconds$`, imapClientNamedReceivesUpdateMarkingMessagesAsReadWithin) s.Step(`^IMAP client "([^"]*)" receives update marking message seq "([^"]*)" as read within (\d+) seconds$`, imapClientNamedReceivesUpdateMarkingMessageSeqAsReadWithin)
s.Step(`^IMAP client receives update marking message "([^"]*)" as unread within (\d+) seconds$`, imapClientReceivesUpdateMarkingMessagesAsUnreadWithin) s.Step(`^IMAP client receives update marking message seq "([^"]*)" as unread within (\d+) seconds$`, imapClientReceivesUpdateMarkingMessageSeqAsUnreadWithin)
s.Step(`^IMAP client "([^"]*)" receives update marking message "([^"]*)" as unread within (\d+) seconds$`, imapClientNamedReceivesUpdateMarkingMessagesAsUnreadWithin) s.Step(`^IMAP client "([^"]*)" receives update marking message seq "([^"]*)" as unread within (\d+) seconds$`, imapClientNamedReceivesUpdateMarkingMessageSeqAsUnreadWithin)
s.Step(`^IMAP client "([^"]*)" does not receive update for message "([^"]*)" within (\d+) seconds$`, imapClientDoesNotReceiveUpdateForMessageWithin) s.Step(`^IMAP client "([^"]*)" does not receive update for message seq "([^"]*)" within (\d+) seconds$`, imapClientDoesNotReceiveUpdateForMessageSeqWithin)
} }
func imapResponseIs(expectedResponse string) error { func imapResponseIs(expectedResponse string) error {
@ -73,26 +73,26 @@ func imapResponseNamedHasNumberOfMessages(clientID string, expectedCount int) er
return ctx.GetTestingError() return ctx.GetTestingError()
} }
func imapClientReceivesUpdateMarkingMessagesAsReadWithin(messageUIDs string, seconds int) error { func imapClientReceivesUpdateMarkingMessageSeqAsReadWithin(messageSeq string, seconds int) error {
return imapClientNamedReceivesUpdateMarkingMessagesAsReadWithin("imap", messageUIDs, seconds) return imapClientNamedReceivesUpdateMarkingMessageSeqAsReadWithin("imap", messageSeq, seconds)
} }
func imapClientNamedReceivesUpdateMarkingMessagesAsReadWithin(clientID, messageUIDs string, seconds int) error { func imapClientNamedReceivesUpdateMarkingMessageSeqAsReadWithin(clientID, messageSeq string, seconds int) error {
regexps := []string{} regexps := []string{}
iterateOverSeqSet(messageUIDs, func(messageUID string) { iterateOverSeqSet(messageSeq, func(messageUID string) {
regexps = append(regexps, `FETCH \(FLAGS \(.*\\Seen.*\) UID `+messageUID) regexps = append(regexps, `FETCH \(FLAGS \(.*\\Seen.*\) UID `+messageUID)
}) })
ctx.GetIMAPLastResponse(clientID).WaitForSections(time.Duration(seconds)*time.Second, regexps...) ctx.GetIMAPLastResponse(clientID).WaitForSections(time.Duration(seconds)*time.Second, regexps...)
return ctx.GetTestingError() return ctx.GetTestingError()
} }
func imapClientReceivesUpdateMarkingMessagesAsUnreadWithin(messageUIDs string, seconds int) error { func imapClientReceivesUpdateMarkingMessageSeqAsUnreadWithin(messageSeq string, seconds int) error {
return imapClientNamedReceivesUpdateMarkingMessagesAsUnreadWithin("imap", messageUIDs, seconds) return imapClientNamedReceivesUpdateMarkingMessageSeqAsUnreadWithin("imap", messageSeq, seconds)
} }
func imapClientNamedReceivesUpdateMarkingMessagesAsUnreadWithin(clientID, messageUIDs string, seconds int) error { func imapClientNamedReceivesUpdateMarkingMessageSeqAsUnreadWithin(clientID, messageSeq string, seconds int) error {
regexps := []string{} regexps := []string{}
iterateOverSeqSet(messageUIDs, func(messageUID string) { iterateOverSeqSet(messageSeq, func(messageUID string) {
// Golang does not support negative look ahead. Following complex regexp checks \Seen is not there. // Golang does not support negative look ahead. Following complex regexp checks \Seen is not there.
regexps = append(regexps, `FETCH \(FLAGS \(([^S]|S[^e]|Se[^e]|See[^n])*\) UID `+messageUID) regexps = append(regexps, `FETCH \(FLAGS \(([^S]|S[^e]|Se[^e]|See[^n])*\) UID `+messageUID)
}) })
@ -100,9 +100,9 @@ func imapClientNamedReceivesUpdateMarkingMessagesAsUnreadWithin(clientID, messag
return ctx.GetTestingError() return ctx.GetTestingError()
} }
func imapClientDoesNotReceiveUpdateForMessageWithin(clientID, messageUIDs string, seconds int) error { func imapClientDoesNotReceiveUpdateForMessageSeqWithin(clientID, messageSeq string, seconds int) error {
regexps := []string{} regexps := []string{}
iterateOverSeqSet(messageUIDs, func(messageUID string) { iterateOverSeqSet(messageSeq, func(messageUID string) {
regexps = append(regexps, `FETCH.*UID `+messageUID) regexps = append(regexps, `FETCH.*UID `+messageUID)
}) })
ctx.GetIMAPLastResponse(clientID).WaitForNotSections(time.Duration(seconds)*time.Second, regexps...) ctx.GetIMAPLastResponse(clientID).WaitForNotSections(time.Duration(seconds)*time.Second, regexps...)

View File

@ -23,7 +23,6 @@ import (
"io" "io"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"strconv"
messageUtils "github.com/ProtonMail/proton-bridge/pkg/message" messageUtils "github.com/ProtonMail/proton-bridge/pkg/message"
"github.com/ProtonMail/proton-bridge/pkg/pmapi" "github.com/ProtonMail/proton-bridge/pkg/pmapi"
@ -127,14 +126,6 @@ func buildMessageBody(message *pmapi.Message, body *bytes.Buffer) error {
return nil return nil
} }
func (ctl *Controller) GetMessageID(username, messageIndex string) string {
idx, err := strconv.Atoi(messageIndex)
if err != nil {
panic(fmt.Sprintf("message index %s not found", messageIndex))
}
return ctl.messageIDsByUsername[username][idx-1]
}
func (ctl *Controller) GetMessages(username, labelID string) ([]*pmapi.Message, error) { func (ctl *Controller) GetMessages(username, labelID string) ([]*pmapi.Message, error) {
client, ok := ctl.pmapiByUsername[username] client, ok := ctl.pmapiByUsername[username]
if !ok { if !ok {

View File

@ -28,6 +28,7 @@ import (
"github.com/ProtonMail/proton-bridge/test/accounts" "github.com/ProtonMail/proton-bridge/test/accounts"
"github.com/cucumber/godog" "github.com/cucumber/godog"
"github.com/cucumber/godog/gherkin" "github.com/cucumber/godog/gherkin"
"github.com/hashicorp/go-multierror"
) )
func StoreChecksFeatureContext(s *godog.Suite) { func StoreChecksFeatureContext(s *godog.Suite) {
@ -202,6 +203,14 @@ func messagesContainsMessageRow(account *accounts.TestAccount, allMessages []int
matches := true matches := true
for n, cell := range row.Cells { for n, cell := range row.Cells {
switch head[n].Value { switch head[n].Value {
case "id":
id, err := ctx.GetAPIMessageID(account.Username(), cell.Value)
if err != nil {
return false, fmt.Errorf("unknown BDD message ID: %s", cell.Value)
}
if message.ID != id {
matches = false
}
case "from": //nolint[goconst] case "from": //nolint[goconst]
address := ctx.EnsureAddress(account.Username(), cell.Value) address := ctx.EnsureAddress(account.Username(), cell.Value)
if !areAddressesSame(message.Sender.Address, address) { if !areAddressesSame(message.Sender.Address, address) {
@ -278,8 +287,8 @@ func areAddressesSame(first, second string) bool {
return firstAddress.Address == secondAddress.Address return firstAddress.Address == secondAddress.Address
} }
func messagesInMailboxForUserIsMarkedAsRead(messageIDs, mailboxName, bddUserID string) error { func messagesInMailboxForUserIsMarkedAsRead(bddMessageIDs, mailboxName, bddUserID string) error {
return checkMessages(bddUserID, mailboxName, messageIDs, func(message *store.Message) error { return checkMessages(bddUserID, mailboxName, bddMessageIDs, func(message *store.Message) error {
if message.Message().Unread == 0 { if message.Message().Unread == 0 {
return nil return nil
} }
@ -287,8 +296,8 @@ func messagesInMailboxForUserIsMarkedAsRead(messageIDs, mailboxName, bddUserID s
}) })
} }
func messagesInMailboxForUserIsMarkedAsUnread(messageIDs, mailboxName, bddUserID string) error { func messagesInMailboxForUserIsMarkedAsUnread(bddMessageIDs, mailboxName, bddUserID string) error {
return checkMessages(bddUserID, mailboxName, messageIDs, func(message *store.Message) error { return checkMessages(bddUserID, mailboxName, bddMessageIDs, func(message *store.Message) error {
if message.Message().Unread == 1 { if message.Message().Unread == 1 {
return nil return nil
} }
@ -296,8 +305,8 @@ func messagesInMailboxForUserIsMarkedAsUnread(messageIDs, mailboxName, bddUserID
}) })
} }
func messagesInMailboxForUserIsMarkedAsStarred(messageIDs, mailboxName, bddUserID string) error { func messagesInMailboxForUserIsMarkedAsStarred(bddMessageIDs, mailboxName, bddUserID string) error {
return checkMessages(bddUserID, mailboxName, messageIDs, func(message *store.Message) error { return checkMessages(bddUserID, mailboxName, bddMessageIDs, func(message *store.Message) error {
if hasItem(message.Message().LabelIDs, "10") { if hasItem(message.Message().LabelIDs, "10") {
return nil return nil
} }
@ -305,8 +314,8 @@ func messagesInMailboxForUserIsMarkedAsStarred(messageIDs, mailboxName, bddUserI
}) })
} }
func messagesInMailboxForUserIsMarkedAsUnstarred(messageIDs, mailboxName, bddUserID string) error { func messagesInMailboxForUserIsMarkedAsUnstarred(bddMessageIDs, mailboxName, bddUserID string) error {
return checkMessages(bddUserID, mailboxName, messageIDs, func(message *store.Message) error { return checkMessages(bddUserID, mailboxName, bddMessageIDs, func(message *store.Message) error {
if !hasItem(message.Message().LabelIDs, "10") { if !hasItem(message.Message().LabelIDs, "10") {
return nil return nil
} }
@ -314,8 +323,8 @@ func messagesInMailboxForUserIsMarkedAsUnstarred(messageIDs, mailboxName, bddUse
}) })
} }
func messagesInMailboxForUserIsMarkedAsDeleted(messageIDs, mailboxName, bddUserID string) error { func messagesInMailboxForUserIsMarkedAsDeleted(bddMessageIDs, mailboxName, bddUserID string) error {
return checkMessages(bddUserID, mailboxName, messageIDs, func(message *store.Message) error { return checkMessages(bddUserID, mailboxName, bddMessageIDs, func(message *store.Message) error {
if message.IsMarkedDeleted() { if message.IsMarkedDeleted() {
return nil return nil
} }
@ -323,8 +332,8 @@ func messagesInMailboxForUserIsMarkedAsDeleted(messageIDs, mailboxName, bddUserI
}) })
} }
func messagesInMailboxForUserIsMarkedAsUndeleted(messageIDs, mailboxName, bddUserID string) error { func messagesInMailboxForUserIsMarkedAsUndeleted(bddMessageIDs, mailboxName, bddUserID string) error {
return checkMessages(bddUserID, mailboxName, messageIDs, func(message *store.Message) error { return checkMessages(bddUserID, mailboxName, bddMessageIDs, func(message *store.Message) error {
if !message.IsMarkedDeleted() { if !message.IsMarkedDeleted() {
return nil return nil
} }
@ -332,14 +341,14 @@ func messagesInMailboxForUserIsMarkedAsUndeleted(messageIDs, mailboxName, bddUse
}) })
} }
func checkMessages(bddUserID, mailboxName, messageIDs string, callback func(*store.Message) error) error { func checkMessages(bddUserID, mailboxName, bddMessageIDs string, callback func(*store.Message) error) error {
account := ctx.GetTestAccount(bddUserID) account := ctx.GetTestAccount(bddUserID)
if account == nil { if account == nil {
return godog.ErrPending return godog.ErrPending
} }
messages, err := getMessages(account.Username(), account.AddressID(), mailboxName, messageIDs) messages, err := getMessages(account.Username(), account.AddressID(), mailboxName, bddMessageIDs)
if err != nil { if err != nil {
return internalError(err, "getting messages %s", messageIDs) return internalError(err, "getting messages %s", bddMessageIDs)
} }
for _, message := range messages { for _, message := range messages {
if err := callback(message); err != nil { if err := callback(message); err != nil {
@ -349,18 +358,23 @@ func checkMessages(bddUserID, mailboxName, messageIDs string, callback func(*sto
return nil return nil
} }
func getMessages(username, addressID, mailboxName, messageIDs string) ([]*store.Message, error) { func getMessages(username, addressID, mailboxName, bddMessageIDs string) ([]*store.Message, error) {
msgs := []*store.Message{} msgs := []*store.Message{}
var msg *store.Message var allErrs *multierror.Error
var err error iterateOverSeqSet(bddMessageIDs, func(bddMessageID string) {
iterateOverSeqSet(messageIDs, func(messageID string) { messageID, err := ctx.GetAPIMessageID(username, bddMessageID)
messageID = ctx.GetPMAPIController().GetMessageID(username, messageID) if err != nil {
msg, err = getMessage(username, addressID, mailboxName, messageID) allErrs = multierror.Append(allErrs, err)
if err == nil { return
msgs = append(msgs, msg)
} }
msg, err := getMessage(username, addressID, mailboxName, messageID)
if err != nil {
allErrs = multierror.Append(allErrs, err)
return
}
msgs = append(msgs, msg)
}) })
return msgs, err return msgs, allErrs.ErrorOrNil()
} }
func getMessage(username, addressID, mailboxName, messageID string) (*store.Message, error) { func getMessage(username, addressID, mailboxName, messageID string) (*store.Message, error) {

View File

@ -87,8 +87,11 @@ func thereAreMessagesInMailboxesForAddressOfUser(mailboxNames, bddAddressID, bdd
var markMessageIDsDeleted []string var markMessageIDsDeleted []string
// Inserting in the opposite order becase sync is done from newest to oldest.
// The goal is to have simply predictable IMAP sequence numbers if possible.
head := messages.Rows[0].Cells head := messages.Rows[0].Cells
for _, row := range messages.Rows[1:] { for i := len(messages.Rows) - 1; i > 0; i-- {
row := messages.Rows[i]
message := &pmapi.Message{ message := &pmapi.Message{
MIMEType: "text/plain", MIMEType: "text/plain",
LabelIDs: labelIDs, LabelIDs: labelIDs,
@ -99,10 +102,13 @@ func thereAreMessagesInMailboxesForAddressOfUser(mailboxNames, bddAddressID, bdd
message.Flags |= pmapi.FlagSent message.Flags |= pmapi.FlagSent
} }
bddMessageID := ""
hasDeletedFlag := false hasDeletedFlag := false
for n, cell := range row.Cells { for n, cell := range row.Cells {
switch head[n].Value { switch head[n].Value {
case "id":
bddMessageID = cell.Value
case "from": case "from":
message.Sender = &mail.Address{ message.Sender = &mail.Address{
Address: ctx.EnsureAddress(account.Username(), cell.Value), Address: ctx.EnsureAddress(account.Username(), cell.Value),
@ -147,6 +153,7 @@ func thereAreMessagesInMailboxesForAddressOfUser(mailboxNames, bddAddressID, bdd
if err != nil { if err != nil {
return internalError(err, "adding message") return internalError(err, "adding message")
} }
ctx.PairMessageID(account.Username(), bddMessageID, lastMessageID)
if hasDeletedFlag { if hasDeletedFlag {
markMessageIDsDeleted = append(markMessageIDsDeleted, lastMessageID) markMessageIDsDeleted = append(markMessageIDsDeleted, lastMessageID)
@ -223,7 +230,7 @@ func thereAreSomeMessagesInMailboxesForAddressOfUser(numberOfMessages int, mailb
if err != nil { if err != nil {
return internalError(err, "getting labels %s for %s", mailboxNames, account.Username()) return internalError(err, "getting labels %s for %s", mailboxNames, account.Username())
} }
_, err = ctx.GetPMAPIController().AddUserMessage(account.Username(), &pmapi.Message{ lastMessageID, err := ctx.GetPMAPIController().AddUserMessage(account.Username(), &pmapi.Message{
MIMEType: "text/plain", MIMEType: "text/plain",
LabelIDs: labelIDs, LabelIDs: labelIDs,
AddressID: account.AddressID(), AddressID: account.AddressID(),
@ -234,6 +241,11 @@ func thereAreSomeMessagesInMailboxesForAddressOfUser(numberOfMessages int, mailb
if err != nil { if err != nil {
return internalError(err, "adding message") return internalError(err, "adding message")
} }
// Generating IDs in the opposite order becase sync is done from newest to oldest.
// The goal is to have simply predictable IMAP sequence numbers if possible.
bddMessageID := fmt.Sprintf("%d", numberOfMessages-i+1)
ctx.PairMessageID(account.Username(), bddMessageID, lastMessageID)
} }
return internalError(ctx.WaitForSync(account.Username()), "waiting for sync") return internalError(ctx.WaitForSync(account.Username()), "waiting for sync")
} }