GODT-1159 SMTP server not restarting after restored internet

- [x] write tests to check that IMAP and SMTP servers are closed when there
  is no internet
- [x] always create new go-smtp instance during listenAndServe(int)
This commit is contained in:
Jakub
2021-05-04 13:50:26 +02:00
committed by James Houlahan
parent 0b95ed4dea
commit dd66b7f8d0
19 changed files with 519 additions and 227 deletions

View File

@ -26,7 +26,7 @@ import (
func APIActionsFeatureContext(s *godog.Suite) {
s.Step(`^the internet connection is lost$`, theInternetConnectionIsLost)
s.Step(`^the internet connection is restored$`, theInternetConnectionIsRestored)
s.Step(`^(\d+) seconds pass$`, secondsPass)
s.Step(`^(\d+) second[s]? pass$`, secondsPass)
}
func theInternetConnectionIsLost() error {

View File

@ -0,0 +1,28 @@
Feature: Servers are closed when no internet
Scenario: All connection are closed and then restored multiple times
Given there is connected user "user"
And there is IMAP client "i1" logged in as "user"
And there is SMTP client "s1" logged in as "user"
When there is no internet connection
And 1 second pass
Then IMAP client "i1" is logged out
And SMTP client "s1" is logged out
Given the internet connection is restored
And there is IMAP client "i2" logged in as "user"
And there is SMTP client "s2" logged in as "user"
When IMAP client "i2" gets info of "INBOX"
When SMTP client "s2" sends "HELO example.com"
Then IMAP response to "i2" is "OK"
Then SMTP response to "s2" is "OK"
When there is no internet connection
And 1 second pass
Then IMAP client "i2" is logged out
And SMTP client "s2" is logged out
Given the internet connection is restored
And there is IMAP client "i3" logged in as "user"
And there is SMTP client "s3" logged in as "user"
When IMAP client "i3" gets info of "INBOX"
When SMTP client "s3" sends "HELO example.com"
Then IMAP response to "i3" is "OK"
Then SMTP response to "s3" is "OK"

View File

@ -30,6 +30,7 @@ func IMAPActionsMailboxFeatureContext(s *godog.Suite) {
s.Step(`^IMAP client lists mailboxes$`, imapClientListsMailboxes)
s.Step(`^IMAP client selects "([^"]*)"$`, imapClientSelects)
s.Step(`^IMAP client gets info of "([^"]*)"$`, imapClientGetsInfoOf)
s.Step(`^IMAP client "([^"]*)" gets info of "([^"]*)"$`, imapClientNamedGetsInfoOf)
s.Step(`^IMAP client gets status of "([^"]*)"$`, imapClientGetsStatusOf)
}
@ -74,8 +75,12 @@ func imapClientSelects(mailboxName string) error {
}
func imapClientGetsInfoOf(mailboxName string) error {
res := ctx.GetIMAPClient("imap").GetMailboxInfo(mailboxName)
ctx.SetIMAPLastResponse("imap", res)
return imapClientNamedGetsInfoOf("imap", mailboxName)
}
func imapClientNamedGetsInfoOf(clientName, mailboxName string) error {
res := ctx.GetIMAPClient(clientName).GetMailboxInfo(mailboxName)
ctx.SetIMAPLastResponse(clientName, res)
return nil
}

View File

@ -40,6 +40,8 @@ func IMAPChecksFeatureContext(s *godog.Suite) {
s.Step(`^IMAP client receives update marking message seq "([^"]*)" as unread within (\d+) seconds$`, imapClientReceivesUpdateMarkingMessageSeqAsUnreadWithin)
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 seq "([^"]*)" within (\d+) seconds$`, imapClientDoesNotReceiveUpdateForMessageSeqWithin)
s.Step(`^IMAP client is logged out$`, imapClientIsLoggedOut)
s.Step(`^IMAP client "([^"]*)" is logged out$`, imapClientNamedIsLoggedOut)
}
func imapResponseIs(expectedResponse string) error {
@ -136,3 +138,13 @@ func iterateOverSeqSet(seqSet string, callback func(string)) {
}
}
}
func imapClientIsLoggedOut() error {
return imapClientNamedIsLoggedOut("imap")
}
func imapClientNamedIsLoggedOut(clientName string) error {
res := ctx.GetIMAPClient(clientName).SendCommand("CAPABILITY")
res.AssertError("read response failed:")
return ctx.GetTestingError()
}

View File

@ -43,6 +43,9 @@ type IMAPClient struct {
func NewIMAPClient(t TestingT, tag string, imapAddr string) *IMAPClient {
conn, err := net.Dial("tcp", imapAddr)
require.NoError(t, err)
if err != nil {
return &IMAPClient{}
}
response := bufio.NewReader(conn)
// Read first response to opening connection.

View File

@ -117,7 +117,7 @@ func (ir *IMAPResponse) AssertResult(wantResult string) *IMAPResponse {
func (ir *IMAPResponse) AssertError(wantErrMsg string) *IMAPResponse {
ir.wait()
if ir.err == nil {
a.Fail(ir.t, "Expected error %s", wantErrMsg)
a.Fail(ir.t, "Error is nil", "Expected to have %q", wantErrMsg)
} else {
a.Regexp(ir.t, wantErrMsg, ir.err.Error(), "Expected error %s but got %s", wantErrMsg, ir.err)
}

View File

@ -30,6 +30,7 @@ import (
"github.com/ProtonMail/go-rfc5322"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -46,6 +47,12 @@ type SMTPClient struct {
func NewSMTPClient(t TestingT, tag, smtpAddr string) *SMTPClient {
conn, err := net.Dial("tcp", smtpAddr)
require.NoError(t, err)
if err != nil {
return &SMTPClient{}
}
logrus.WithField("addr", conn.LocalAddr().String()).
WithField("tag", tag).
Debug("SMTP Dialed")
response := bufio.NewReader(conn)
// Read first response to opening connection.
@ -85,6 +92,7 @@ func (c *SMTPClient) SendCommands(commands ...string) *SMTPResponse {
message, err := c.response.ReadString('\n')
if err != nil {
smtpResponse.err = fmt.Errorf("read response failed: %v", err)
c.debug.printErr(smtpResponse.err.Error() + "\n")
return smtpResponse
}

View File

@ -34,7 +34,7 @@ func (sr *SMTPResponse) AssertOK() *SMTPResponse {
func (sr *SMTPResponse) AssertError(wantErrMsg string) *SMTPResponse {
if sr.err == nil {
a.Fail(sr.t, "Expected error %s", wantErrMsg)
a.Fail(sr.t, "Error is nil", "Expected to have %q", wantErrMsg)
} else {
a.Regexp(sr.t, wantErrMsg, sr.err.Error(), "Expected error %s but got %s", wantErrMsg, sr.err)
}

View File

@ -37,6 +37,7 @@ func SMTPActionsAuthFeatureContext(s *godog.Suite) {
s.Step(`^SMTP client sends message with bcc "([^"]*)"$`, smtpClientSendsMessageWithBCC)
s.Step(`^SMTP client "([^"]*)" sends message with bcc "([^"]*)"$`, smtpClientNamedSendsMessageWithBCC)
s.Step(`^SMTP client sends "([^"]*)"$`, smtpClientSendsCommand)
s.Step(`^SMTP client "([^"]*)" sends "([^"]*)"$`, smtpClientNamedSendsCommand)
}
func smtpClientAuthenticates(bddUserID string) error {
@ -108,9 +109,12 @@ func smtpClientNamedSendsMessageWithBCC(clientID, bcc string, message *gherkin.D
}
func smtpClientSendsCommand(command string) error {
return smtpClientNamedSendsCommand("smtp", command)
}
func smtpClientNamedSendsCommand(clientName, command string) error {
command = strings.ReplaceAll(command, "\\r", "\r")
command = strings.ReplaceAll(command, "\\n", "\n")
res := ctx.GetSMTPClient("smtp").SendCommands(command)
ctx.SetSMTPLastResponse("smtp", res)
res := ctx.GetSMTPClient(clientName).SendCommands(command)
ctx.SetSMTPLastResponse(clientName, res)
return nil
}

View File

@ -24,6 +24,8 @@ import (
func SMTPChecksFeatureContext(s *godog.Suite) {
s.Step(`^SMTP response is "([^"]*)"$`, smtpResponseIs)
s.Step(`^SMTP response to "([^"]*)" is "([^"]*)"$`, smtpResponseNamedIs)
s.Step(`^SMTP client is logged out`, smtpClientIsLoggedOut)
s.Step(`^SMTP client "([^"]*)" is logged out`, smtpClientNamedIsLoggedOut)
}
func smtpResponseIs(expectedResponse string) error {
@ -39,3 +41,13 @@ func smtpResponseNamedIs(clientID, expectedResponse string) error {
}
return ctx.GetTestingError()
}
func smtpClientIsLoggedOut() error {
return smtpClientNamedIsLoggedOut("smtp")
}
func smtpClientNamedIsLoggedOut(clientName string) error {
res := ctx.GetSMTPClient(clientName).SendCommands("HELO loggedOut.com")
res.AssertError("read response failed:")
return ctx.GetTestingError()
}