test: use smtplib.SMTP[_SSL] timeout = notifications.smtp-timeout

A new option has been added for configuration of SMTP timeout:
- notifications.smtp-timeout

During tests, we can change this timeout to be small, so we aren't
depending on hardware-based RNG to pass the timeout.

Without a timeout, users can run into a long-running test for no
particular reason.

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2022-03-08 17:51:44 -08:00
parent 13217be939
commit e00cf5f124
No known key found for this signature in database
GPG key ID: F7E46DED420788F3
4 changed files with 37 additions and 21 deletions

View file

@ -104,7 +104,10 @@ class Notification:
False: smtplib.SMTP,
True: smtplib.SMTP_SSL,
}
server = classes[use_ssl](server_addr, server_port)
smtp_timeout = aurweb.config.getint("notifications",
"smtp-timeout")
server = classes[use_ssl](server_addr, server_port,
timeout=smtp_timeout)
if use_starttls:
server.ehlo()

View file

@ -36,6 +36,9 @@ class FakeSMTP:
def quit(self) -> None:
self.quit_count += 1
def __call__(self, *args, **kwargs) -> "FakeSMTP":
return self
class FakeSMTP_SSL(FakeSMTP):
""" A fake version of smtplib.SMTP_SSL used for testing. """

View file

@ -65,6 +65,7 @@ smtp-use-ssl = 0
smtp-use-starttls = 0
smtp-user =
smtp-password =
smtp-timeout = 60
sender = notify@aur.archlinux.org
reply-to = noreply@aur.archlinux.org

View file

@ -547,18 +547,18 @@ def test_smtp(user: User):
with db.begin():
user.ResetKey = "12345678901234567890123456789012"
SMTP = FakeSMTP()
smtp = FakeSMTP()
get = "aurweb.config.get"
getboolean = "aurweb.config.getboolean"
with mock.patch(get, side_effect=mock_smtp_config(str)):
with mock.patch(getboolean, side_effect=mock_smtp_config(bool)):
with mock.patch("smtplib.SMTP", side_effect=lambda a, b: SMTP):
with mock.patch("smtplib.SMTP", side_effect=smtp):
config.rehash()
notif = notify.WelcomeNotification(user.ID)
notif.send()
config.rehash()
assert len(SMTP.emails) == 1
assert len(smtp.emails) == 1
def mock_smtp_starttls_config(cls):
@ -586,25 +586,25 @@ def test_smtp_starttls(user: User):
user.ResetKey = "12345678901234567890123456789012"
user.BackupEmail = "backup@example.org"
SMTP = FakeSMTP()
smtp = FakeSMTP()
get = "aurweb.config.get"
getboolean = "aurweb.config.getboolean"
with mock.patch(get, side_effect=mock_smtp_starttls_config(str)):
with mock.patch(
getboolean, side_effect=mock_smtp_starttls_config(bool)):
with mock.patch("smtplib.SMTP", side_effect=lambda a, b: SMTP):
with mock.patch("smtplib.SMTP", side_effect=smtp):
notif = notify.WelcomeNotification(user.ID)
notif.send()
assert SMTP.starttls_enabled
assert SMTP.user
assert SMTP.passwd
assert smtp.starttls_enabled
assert smtp.user
assert smtp.passwd
assert len(SMTP.emails) == 2
to = SMTP.emails[0][1]
assert len(smtp.emails) == 2
to = smtp.emails[0][1]
assert to == [user.Email]
to = SMTP.emails[1][1]
to = smtp.emails[1][1]
assert to == [user.BackupEmail]
@ -629,19 +629,19 @@ def test_smtp_ssl(user: User):
with db.begin():
user.ResetKey = "12345678901234567890123456789012"
SMTP = FakeSMTP_SSL()
smtp = FakeSMTP_SSL()
get = "aurweb.config.get"
getboolean = "aurweb.config.getboolean"
with mock.patch(get, side_effect=mock_smtp_ssl_config(str)):
with mock.patch(getboolean, side_effect=mock_smtp_ssl_config(bool)):
with mock.patch("smtplib.SMTP_SSL", side_effect=lambda a, b: SMTP):
with mock.patch("smtplib.SMTP_SSL", side_effect=smtp):
notif = notify.WelcomeNotification(user.ID)
notif.send()
assert len(SMTP.emails) == 1
assert SMTP.use_ssl
assert SMTP.user
assert SMTP.passwd
assert len(smtp.emails) == 1
assert smtp.use_ssl
assert smtp.user
assert smtp.passwd
def test_notification_defaults():
@ -655,6 +655,7 @@ def test_notification_oserror(user: User, caplog: pytest.LogCaptureFixture):
""" Try sending a notification with a bad SMTP configuration. """
caplog.set_level(ERROR)
config_get = config.get
config_getint = config.getint
mocked_options = {
"sendmail": str(),
@ -662,8 +663,9 @@ def test_notification_oserror(user: User, caplog: pytest.LogCaptureFixture):
"smtp-port": "587",
"smtp-user": "notify@server.xyz",
"smtp-password": "notify_server_xyz",
"smtp-timeout": 1,
"sender": "notify@server.xyz",
"reply-to": "no-reply@server.xyz"
"reply-to": "no-reply@server.xyz",
}
def mock_config_get(section: str, key: str) -> str:
@ -672,9 +674,16 @@ def test_notification_oserror(user: User, caplog: pytest.LogCaptureFixture):
return mocked_options.get(key)
return config_get(section, key)
def mock_config_getint(section: str, key: str) -> str:
if section == "notifications":
if key in mocked_options:
return mocked_options.get(key)
return config_getint(section, key)
notif = notify.WelcomeNotification(user.ID)
with mock.patch("aurweb.config.get", side_effect=mock_config_get):
notif.send()
with mock.patch("aurweb.config.getint", side_effect=mock_config_getint):
with mock.patch("aurweb.config.get", side_effect=mock_config_get):
notif.send()
expected = "Unable to emit notification due to an OSError"
assert expected in caplog.text