Skip to content

Commit

Permalink
imap4.IMAP4Server: test missing portal and use base class' auth.
Browse files Browse the repository at this point in the history
twisted.mail.test.test_imap.SimpleServer's theAccount is now always a
class variable, and TestRealm can now retrieve it from SimpleServer on
each requestAvatar invocation.  This allows the removal of
SimpleServer.authenticateLogin, so that tests can exercise
IMAP4Server.authenticateLogin directly.

This also tests what happens upon receipt of LOGIN without a portal.
  • Loading branch information
markrwilliams committed Aug 19, 2017
1 parent efebb61 commit ab94a2a
Showing 1 changed file with 46 additions and 17 deletions.
63 changes: 46 additions & 17 deletions src/twisted/mail/test/test_imap.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
networkString, iterbytes, _PY3)
from twisted.trial import unittest

from twisted.cred.portal import Portal
from twisted.cred.portal import Portal, IRealm
from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse
from twisted.cred.error import UnauthorizedLogin
from twisted.cred.credentials import (
Expand Down Expand Up @@ -1867,13 +1867,14 @@ def select(self, name, rw=1):



class SimpleServer(imap4.IMAP4Server):
class SimpleServer(imap4.IMAP4Server, object):
theAccount = Account(b'testuser')
def __init__(self, *args, **kw):
imap4.IMAP4Server.__init__(self, *args, **kw)
realm = TestRealm()
realm.theAccount = Account(b'testuser')
realm = TestRealm(accountHolder=self)
portal = Portal(realm)
c = InMemoryUsernamePasswordDatabaseDontUse()
c.addUser(b'testuser', b'password-test')
self.checker = c
self.portal = portal
portal.registerChecker(c)
Expand All @@ -1887,13 +1888,6 @@ def lineReceived(self, line):

imap4.IMAP4Server.lineReceived(self, line)

_username = b'testuser'
_password = b'password-test'
def authenticateLogin(self, username, password):
if username == self._username and password == self._password:
return imap4.IAccount, self.theAccount, lambda: None
raise UnauthorizedLogin()



class SimpleClient(imap4.IMAP4Client):
Expand Down Expand Up @@ -2064,9 +2058,24 @@ def _cbTestFailedLogin(self, ignored):
self.assertEqual(self.server.state, 'unauth')


def test_loginWithoutPortal(self):
"""
Attempting to log into a server that has no L{Portal} results
in a failed login.
"""
self.server.portal = None
def login():
d = self.client.login(b'testuser', b'wrong-password')
d.addBoth(self._cbStopClient)

d1 = self.connected.addCallback(strip(login)).addErrback(self._ebGeneral)
d2 = self.loopback()
d = defer.gatherResults([d1, d2])
return d.addCallback(self._cbTestFailedLogin)


def testLoginRequiringQuoting(self):
self.server._username = b'{test}user'
self.server._password = b'{test}password'
self.server.checker.users = {b'{test}user': b'{test}password'}

def login():
d = self.client.login(b'{test}user', b'{test}password')
Expand Down Expand Up @@ -3348,12 +3357,33 @@ def test_searchSince(self):
self.server.search_SINCE(self.laterQuery, self.seq, self.msg))



@implementer(IRealm)
class TestRealm:
"""
A L{IRealm} for tests.
@cvar theAccount: An C{Account} instance. Tests can set this to
ensure predictable account retrieval.
"""
theAccount = None

def __init__(self, accountHolder=None):
"""
Create a realm for testing.
@param accountHolder: (optional) An object whose C{theAccount}
attribute will be returned instead of
L{TestRealm.theAccount}. Attribute access occurs on every
avatar request, so any modifications to
C{accountHolder.theAccount} will be reflected here.
"""
if accountHolder:
self._getAccount = lambda: accountHolder.theAccount
else:
self._getAccount = lambda: self.theAccount

def requestAvatar(self, avatarId, mind, *interfaces):
return imap4.IAccount, self.theAccount, lambda: None
return imap4.IAccount, self._getAccount(), lambda: None



Expand Down Expand Up @@ -4147,8 +4177,7 @@ def test_emptyStringLiteral(self):
"""
Empty string literals are parsed.
"""
self.server._username = b''
self.server._password = b''
self.server.checker.users = {b"": b""}
transport = StringTransport()
self.server.makeConnection(transport)

Expand Down

0 comments on commit ab94a2a

Please sign in to comment.