diff options
| author | Kali Kaneko <kali@leap.se> | 2014-01-02 16:08:09 -0400 | 
|---|---|---|
| committer | Kali Kaneko <kali@leap.se> | 2014-01-08 20:34:41 -0400 | 
| commit | 8a1c59db0c9d444e9fb309b425194c41467ee16b (patch) | |
| tree | 499bde2bfb640ca4a2028ed197c55f30435cd5af /mail/src | |
| parent | 44e8329dc439382b5c2a3e7829e433f894809716 (diff) | |
fix tests after rewrite
Diffstat (limited to 'mail/src')
| -rw-r--r-- | mail/src/leap/mail/imap/fields.py | 3 | ||||
| -rw-r--r-- | mail/src/leap/mail/imap/mailbox.py | 41 | ||||
| -rw-r--r-- | mail/src/leap/mail/imap/messages.py | 94 | ||||
| -rw-r--r-- | mail/src/leap/mail/imap/tests/test_imap.py | 196 | 
4 files changed, 227 insertions, 107 deletions
| diff --git a/mail/src/leap/mail/imap/fields.py b/mail/src/leap/mail/imap/fields.py index 40817cd..bc536fe 100644 --- a/mail/src/leap/mail/imap/fields.py +++ b/mail/src/leap/mail/imap/fields.py @@ -35,6 +35,7 @@ class WithMsgFields(object):      UID_KEY = "uid"      MBOX_KEY = "mbox"      SEEN_KEY = "seen" +    DEL_KEY = "deleted"      RECENT_KEY = "recent"      FLAGS_KEY = "flags"      MULTIPART_KEY = "multi" @@ -95,6 +96,7 @@ class WithMsgFields(object):      TYPE_SUBS_IDX = 'by-type-and-subscribed'      TYPE_MBOX_SEEN_IDX = 'by-type-and-mbox-and-seen'      TYPE_MBOX_RECT_IDX = 'by-type-and-mbox-and-recent' +    TYPE_MBOX_DEL_IDX = 'by-type-and-mbox-and-deleted'      TYPE_C_HASH_IDX = 'by-type-and-contenthash'      TYPE_C_HASH_PART_IDX = 'by-type-and-contenthash-and-partnumber'      TYPE_P_HASH_IDX = 'by-type-and-payloadhash' @@ -128,6 +130,7 @@ class WithMsgFields(object):          # messages          TYPE_MBOX_SEEN_IDX: [KTYPE, MBOX_VAL, 'bool(seen)'],          TYPE_MBOX_RECT_IDX: [KTYPE, MBOX_VAL, 'bool(recent)'], +        TYPE_MBOX_DEL_IDX: [KTYPE, MBOX_VAL, 'bool(deleted)'],          TYPE_MBOX_RECT_SEEN_IDX: [KTYPE, MBOX_VAL,                                    'bool(recent)', 'bool(seen)'],      } diff --git a/mail/src/leap/mail/imap/mailbox.py b/mail/src/leap/mail/imap/mailbox.py index 5ea6f55..10087f6 100644 --- a/mail/src/leap/mail/imap/mailbox.py +++ b/mail/src/leap/mail/imap/mailbox.py @@ -390,18 +390,17 @@ class SoledadMailbox(WithMsgFields, MBoxParser):          else:              flags = tuple(str(flag) for flag in flags) -        d = self._do_add_message(message, flags, date, uid_next) +        d = self._do_add_message(message, flags=flags, date=date, uid=uid_next)          d.addCallback(self._notify_new)          return d      @deferred -    def _do_add_message(self, message, flags, date, uid_next): +    def _do_add_message(self, message, flags, date, uid):          """          Calls to the messageCollection add_msg method (deferred to thread).          Invoked from addMessage.          """ -        self.messages.add_msg(message, flags=flags, date=date, -                              uid=uid_next) +        self.messages.add_msg(message, flags=flags, date=date, uid=uid)      def _notify_new(self, *args):          """ @@ -436,21 +435,29 @@ class SoledadMailbox(WithMsgFields, MBoxParser):          # we should postpone the removal          self._soledad.delete_doc(self._get_mbox()) -    @deferred +    def _close_cb(self, result): +        self.closed = True + +    def close(self): +        """ +        Expunge and mark as closed +        """ +        d = self.expunge() +        d.addCallback(self._close_cb) +        return d + +    def _expunge_cb(self, result): +        return result +      def expunge(self):          """          Remove all messages flagged \\Deleted          """          if not self.isWriteable():              raise imap4.ReadOnlyMailbox -        deleted = [] -        for m in self.messages: -            if self.DELETED_FLAG in m.getFlags(): -                self.messages.remove(m) -                # XXX this would ve more efficient if we can just pass -                # a sequence of uids. -                deleted.append(m.getUID()) -        return deleted +        d = self.messages.remove_all_deleted() +        d.addCallback(self._expunge_cb) +        return d      @deferred      def fetch(self, messages, uid): @@ -603,14 +610,6 @@ class SoledadMailbox(WithMsgFields, MBoxParser):          self._signal_unread_to_ui()          return result -    @deferred -    def close(self): -        """ -        Expunge and mark as closed -        """ -        self.expunge() -        self.closed = True -      # IMessageCopier      @deferred diff --git a/mail/src/leap/mail/imap/messages.py b/mail/src/leap/mail/imap/messages.py index 47c40d5..80411f9 100644 --- a/mail/src/leap/mail/imap/messages.py +++ b/mail/src/leap/mail/imap/messages.py @@ -20,9 +20,11 @@ LeapMessage and MessageCollection.  import copy  import logging  import StringIO -from collections import namedtuple + +from collections import defaultdict, namedtuple  from twisted.mail import imap4 +from twisted.internet import defer  from twisted.python import log  from u1db import errors as u1db_errors  from zope.interface import implements @@ -182,6 +184,7 @@ class MessageAttachment(object):          if not self._msg:              return {}          headers = dict(self._msg.items()) +          names = map(lambda s: s.upper(), names)          if negate:              cond = lambda key: key.upper() not in names @@ -329,6 +332,7 @@ class LeapMessage(fields, MailParser, MBoxParser):          doc.content[self.FLAGS_KEY] = flags          doc.content[self.SEEN_KEY] = self.SEEN_FLAG in flags          doc.content[self.RECENT_KEY] = self.RECENT_FLAG in flags +        doc.content[self.DEL_KEY] = self.DELETED_FLAG in flags          self._soledad.put_doc(doc)      def addFlags(self, flags): @@ -455,6 +459,7 @@ class LeapMessage(fields, MailParser, MBoxParser):          headers = self._get_headers()          if not headers:              return {'content-type': ''} +          names = map(lambda s: s.upper(), names)          if negate:              cond = lambda key: key.upper() not in names @@ -465,8 +470,8 @@ class LeapMessage(fields, MailParser, MBoxParser):              # twisted imap server expects headers to be lowercase          head = dict( -            map(str, (key, value)) if key.lower() != "content-type" -            else map(str, (key.lower(), value)) +            (str(key), map(str, value)) if key.lower() != "content-type" +            else (str(key.lower(), map(str, value)))              for (key, value) in head.items())          # unpack and filter original dict by negate-condition @@ -670,6 +675,9 @@ class LeapMessage(fields, MailParser, MBoxParser):          # until we think about a good way of deorphaning.          # Maybe a crawler of unreferenced docs. +        uid = self._uid +        print "removing...", uid +          fd = self._get_flags_doc()          hd = self._get_headers_doc()          #bd = self._get_body_doc() @@ -682,7 +690,11 @@ class LeapMessage(fields, MailParser, MBoxParser):              #docs.append(ad)          for d in filter(None, docs): -            self._soledad.delete_doc(d) +            try: +                self._soledad.delete_doc(d) +            except Exception as exc: +                logger.error(exc) +        return uid      def does_exist(self):          """ @@ -849,6 +861,7 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser):              fields.SEEN_KEY: False,              fields.RECENT_KEY: True, +            fields.DEL_KEY: False,              fields.FLAGS_KEY: [],              fields.MULTIPART_KEY: False,              fields.SIZE_KEY: 0 @@ -921,7 +934,7 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser):          self.soledad_writer = MessageProducer(              SoledadDocWriter(soledad), -            period=0.05) +            period=0.02)      def _get_empty_doc(self, _type=FLAGS_DOC):          """ @@ -966,7 +979,9 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser):              (self.FLAGS_DOC, self.HEADERS_DOC, self.BODY_DOC))          msg = self._get_parsed_msg(raw) -        headers = dict(msg) +        headers = defaultdict(list) +        for k, v in msg.items(): +            headers[k].append(v)          raw_str = msg.as_string()          chash = self._get_hash(msg)          multi = msg.is_multipart() @@ -987,7 +1002,8 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser):                      inner_parts.append(p)          else:              body = msg.get_payload() -        logger.debug("adding msg (multipart:%s)" % multi) +        logger.debug("adding msg with uid %s (multipart:%s)" % ( +            uid, multi))          # flags doc ---------------------------------------          fd[self.MBOX_KEY] = self.mbox @@ -998,26 +1014,33 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser):          if flags:              fd[self.FLAGS_KEY] = map(self._stringify, flags)              fd[self.SEEN_KEY] = self.SEEN_FLAG in flags -            fd[self.RECENT_KEY] = self.RECENT_FLAG in flags +            fd[self.DEL_KEY] = self.DELETED_FLAG in flags +            fd[self.RECENT_KEY] = True  # set always by default          # headers doc ----------------------------------------          hd[self.CONTENT_HASH_KEY] = chash          hd[self.HEADERS_KEY] = headers + +        print "headers" +        import pprint +        pprint.pprint(headers) +          if not subject and self.SUBJECT_FIELD in headers: -            hd[self.SUBJECT_KEY] = headers[self.SUBJECT_FIELD] +            hd[self.SUBJECT_KEY] = first(headers[self.SUBJECT_FIELD])          else:              hd[self.SUBJECT_KEY] = subject          if not date and self.DATE_FIELD in headers: -            hd[self.DATE_KEY] = headers[self.DATE_FIELD] +            hd[self.DATE_KEY] = first(headers[self.DATE_FIELD])          else:              hd[self.DATE_KEY] = date          if multi: +            # XXX fix for multipart nested case              hd[self.NUM_PARTS_KEY] = len(msg.get_payload())          # body doc          bd[self.CONTENT_HASH_KEY] = chash          bd[self.BODY_KEY] = body -        # in an ideal world, we would not need to save a copy of the +        # XXX in an ideal world, we would not need to save a copy of the          # raw message. But we'll keep it until we can be sure that          # we can rebuild the original message from the parts.          bd[self.RAW_KEY] = raw_str @@ -1062,14 +1085,29 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser):              self.soledad_writer.put(ptuple(                  mode=ptuple.ATTACHMENT_CREATE, payload=at)) -    def remove(self, msg): +    def _remove_cb(self, result): +        return result + +    def remove_all_deleted(self): +        """ +        Removes all messages flagged as deleted.          """ -        Removes a message. +        delete_deferl = [] +        for msg in self.get_deleted(): +            delete_deferl.append(msg.remove()) +        d1 = defer.gatherResults(delete_deferl, consumeErrors=True) +        d1.addCallback(self._remove_cb) +        return d1 -        :param msg: a  Leapmessage instance +    def remove(self, msg): +        """ +        Remove a given msg. +        :param msg: the message to be removed          :type msg: LeapMessage          """ -        msg.remove() +        d = msg.remove() +        d.addCallback(self._remove_cb) +        return d      # getters @@ -1178,7 +1216,7 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser):      def recent_iter(self):          """ -        Get an iterator for the message docs with `recent` flag. +        Get an iterator for the message UIDs with `recent` flag.          :return: iterator through recent message docs          :rtype: iterable @@ -1210,6 +1248,30 @@ class MessageCollection(WithMsgFields, IndexedDB, MailParser, MBoxParser):              fields.TYPE_FLAGS_VAL, self.mbox, '1')          return count +    # deleted messages + +    def deleted_iter(self): +        """ +        Get an iterator for the message UIDs with `deleted` flag. + +        :return: iterator through deleted message docs +        :rtype: iterable +        """ +        return (doc.content[self.UID_KEY] for doc in +                self._soledad.get_from_index( +                    fields.TYPE_MBOX_DEL_IDX, +                    fields.TYPE_FLAGS_VAL, self.mbox, '1')) + +    def get_deleted(self): +        """ +        Get all messages with the `Deleted` flag. + +        :returns: a generator of LeapMessages +        :rtype: generator +        """ +        return (LeapMessage(self._soledad, docid, self.mbox) +                for docid in self.deleted_iter()) +      def __len__(self):          """          Returns the number of messages on this mailbox. diff --git a/mail/src/leap/mail/imap/tests/test_imap.py b/mail/src/leap/mail/imap/tests/test_imap.py index ea75854..e1bed8c 100644 --- a/mail/src/leap/mail/imap/tests/test_imap.py +++ b/mail/src/leap/mail/imap/tests/test_imap.py @@ -25,7 +25,7 @@ XXX add authors from the original twisted tests.  @license: GPLv3, see included LICENSE file  """  # XXX review license of the original tests!!! -from nose.twistedtools import deferred +from email import parser  try:      from cStringIO import StringIO @@ -36,9 +36,13 @@ import os  import types  import tempfile  import shutil +import time + +from itertools import chain  from mock import Mock +from nose.twistedtools import deferred, stop_reactor  from twisted.mail import imap4 @@ -58,9 +62,9 @@ import twisted.cred.portal  # import u1db  from leap.common.testing.basetest import BaseLeapTest -from leap.mail.imap.server import SoledadMailbox -from leap.mail.imap.server import SoledadBackedAccount -from leap.mail.imap.server import MessageCollection +from leap.mail.imap.account import SoledadBackedAccount +from leap.mail.imap.mailbox import SoledadMailbox +from leap.mail.imap.messages import MessageCollection  from leap.soledad.client import Soledad  from leap.soledad.client import SoledadCrypto @@ -321,6 +325,9 @@ class IMAP4HelperMixin(BaseLeapTest):          for mb in self.server.theAccount.mailboxes:              self.server.theAccount.delete(mb) +        # email parser +        self.parser = parser.Parser() +      def tearDown(self):          """          tearDown method called after each test. @@ -389,6 +396,7 @@ class MessageCollectionTestCase(IMAP4HelperMixin, unittest.TestCase):      """      Tests for the MessageCollection class      """ +    count = 0      def setUp(self):          """ @@ -396,34 +404,35 @@ class MessageCollectionTestCase(IMAP4HelperMixin, unittest.TestCase):          We override mixin method since we are only testing          MessageCollection interface in this particular TestCase          """ -        self.messages = MessageCollection("testmbox", self._soledad) -        for m in self.messages.get_all(): -            self.messages.remove(m) +        self.messages = MessageCollection("testmbox%s" % (self.count,), +                                          self._soledad) +        MessageCollectionTestCase.count += 1      def tearDown(self):          """          tearDown method for each test -        Delete the message collection          """          del self.messages +    def wait(self): +        time.sleep(2) +      def testEmptyMessage(self):          """          Test empty message and collection          """ -        em = self.messages._get_empty_msg() +        em = self.messages._get_empty_doc()          self.assertEqual(              em,              { -                "date": '',                  "flags": [], -                "headers": {},                  "mbox": "inbox", -                "raw": "",                  "recent": True,                  "seen": False, -                "subject": "", -                "type": "msg", +                "deleted": False, +                "multi": False, +                "size": 0, +                "type": "flags",                  "uid": 1,              })          self.assertEqual(self.messages.count(), 0) @@ -432,23 +441,22 @@ class MessageCollectionTestCase(IMAP4HelperMixin, unittest.TestCase):          """          Add multiple messages          """ +        # TODO really profile addition          mc = self.messages +        print "messages", self.messages          self.assertEqual(self.messages.count(), 0) -        mc.add_msg('Stuff', subject="test1") -        self.assertEqual(self.messages.count(), 1) -        mc.add_msg('Stuff', subject="test2") -        self.assertEqual(self.messages.count(), 2) -        mc.add_msg('Stuff', subject="test3") -        self.assertEqual(self.messages.count(), 3) -        mc.add_msg('Stuff', subject="test4") +        mc.add_msg('Stuff', uid=1, subject="test1") +        mc.add_msg('Stuff', uid=2, subject="test2") +        mc.add_msg('Stuff', uid=3, subject="test3") +        mc.add_msg('Stuff', uid=4, subject="test4") +        self.wait()          self.assertEqual(self.messages.count(), 4) -        mc.add_msg('Stuff', subject="test5") -        mc.add_msg('Stuff', subject="test6") -        mc.add_msg('Stuff', subject="test7") -        mc.add_msg('Stuff', subject="test8") -        mc.add_msg('Stuff', subject="test9") -        mc.add_msg('Stuff', subject="test10") -        self.assertEqual(self.messages.count(), 10) +        mc.add_msg('Stuff', uid=5, subject="test5") +        mc.add_msg('Stuff', uid=6, subject="test6") +        mc.add_msg('Stuff', uid=7, subject="test7") +        self.wait() +        self.assertEqual(self.messages.count(), 7) +        self.wait()      def testRecentCount(self):          """ @@ -456,45 +464,48 @@ class MessageCollectionTestCase(IMAP4HelperMixin, unittest.TestCase):          """          mc = self.messages          self.assertEqual(self.messages.count_recent(), 0) -        mc.add_msg('Stuff', subject="test1", uid=1) +        mc.add_msg('Stuff', uid=1, subject="test1")          # For the semantics defined in the RFC, we auto-add the          # recent flag by default. +        self.wait()          self.assertEqual(self.messages.count_recent(), 1) -        mc.add_msg('Stuff', subject="test2", uid=2, flags=('\\Deleted',)) +        mc.add_msg('Stuff', subject="test2", uid=2, +                   flags=('\\Deleted',)) +        self.wait()          self.assertEqual(self.messages.count_recent(), 2) -        mc.add_msg('Stuff', subject="test3", uid=3, flags=('\\Recent',)) +        mc.add_msg('Stuff', subject="test3", uid=3, +                   flags=('\\Recent',)) +        self.wait()          self.assertEqual(self.messages.count_recent(), 3)          mc.add_msg('Stuff', subject="test4", uid=4,                     flags=('\\Deleted', '\\Recent')) +        self.wait()          self.assertEqual(self.messages.count_recent(), 4) -        for m in mc: -            msg = self.messages.get_msg_by_uid(m.get('uid')) -            msg_newflags = msg.removeFlags(('\\Recent',)) -            self._soledad.put_doc(msg_newflags) - +        for msg in mc: +            msg.removeFlags(('\\Recent',))          self.assertEqual(mc.count_recent(), 0)      def testFilterByMailbox(self):          """          Test that queries filter by selected mailbox          """ +        def wait(): +            time.sleep(1) +          mc = self.messages          self.assertEqual(self.messages.count(), 0) -        mc.add_msg('', subject="test1") -        self.assertEqual(self.messages.count(), 1) -        mc.add_msg('', subject="test2") -        self.assertEqual(self.messages.count(), 2) -        mc.add_msg('', subject="test3") +        mc.add_msg('', uid=1, subject="test1") +        mc.add_msg('', uid=2, subject="test2") +        mc.add_msg('', uid=3, subject="test3") +        wait()          self.assertEqual(self.messages.count(), 3) - -        newmsg = mc._get_empty_msg() +        newmsg = mc._get_empty_doc()          newmsg['mailbox'] = "mailbox/foo" -        newmsg['subject'] = "test another mailbox"          mc._soledad.create_doc(newmsg)          self.assertEqual(mc.count(), 3)          self.assertEqual( -            len(mc._soledad.get_from_index(mc.TYPE_IDX, "*")), 4) +            len(mc._soledad.get_from_index(mc.TYPE_IDX, "flags")), 4)  class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase): @@ -1174,16 +1185,20 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):          def login():              return self.client.login('testuser', 'password-test') +        def wait(): +            time.sleep(0.5) +          def append():              return self.client.append(                  'root/subthing',                  message, -                ['\\SEEN', '\\DELETED'], +                ('\\SEEN', '\\DELETED'),                  'Tue, 17 Jun 2003 11:22:16 -0600 (MDT)',              )          d1 = self.connected.addCallback(strip(login))          d1.addCallbacks(strip(append), self._ebGeneral) +        d1.addCallbacks(strip(wait), self._ebGeneral)          d1.addCallbacks(self._cbStopClient, self._ebGeneral)          d2 = self.loopback()          d = defer.gatherResults([d1, d2]) @@ -1191,17 +1206,31 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):      def _cbTestFullAppend(self, ignored, infile):          mb = SimpleLEAPServer.theAccount.getMailbox('root/subthing') +        time.sleep(0.5)          self.assertEqual(1, len(mb.messages)) +        msg = mb.messages.get_msg_by_uid(1)          self.assertEqual( -            ['\\SEEN', '\\DELETED'], -            mb.messages[1].content['flags']) +            ('\\SEEN', '\\DELETED'), +            msg.getFlags())          self.assertEqual(              'Tue, 17 Jun 2003 11:22:16 -0600 (MDT)', -            mb.messages[1].content['date']) +            msg.getInternalDate()) + +        parsed = self.parser.parse(open(infile)) +        body = parsed.get_payload() +        headers = parsed.items() +        self.assertEqual( +            body, +            msg.getBodyFile().read()) + +        msg_headers = msg.getHeaders(True, "",) +        gotheaders = list(chain( +            *[[(k, item) for item in v] for (k, v) in msg_headers.items()])) -        self.assertEqual(open(infile).read(), mb.messages[1].content['raw']) +        self.assertItemsEqual( +            headers, gotheaders)      @deferred(timeout=None)      def testPartialAppend(self): @@ -1209,12 +1238,14 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):          Test partially appending a message to the mailbox          """          infile = util.sibpath(__file__, 'rfc822.message') -        message = open(infile)          SimpleLEAPServer.theAccount.addMailbox('PARTIAL/SUBTHING')          def login():              return self.client.login('testuser', 'password-test') +        def wait(): +            time.sleep(1) +          def append():              message = file(infile)              return self.client.sendCommand( @@ -1226,6 +1257,7 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):                  )              )          d1 = self.connected.addCallback(strip(login)) +        d1.addCallbacks(strip(wait), self._ebGeneral)          d1.addCallbacks(strip(append), self._ebGeneral)          d1.addCallbacks(self._cbStopClient, self._ebGeneral)          d2 = self.loopback() @@ -1235,15 +1267,20 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):      def _cbTestPartialAppend(self, ignored, infile):          mb = SimpleLEAPServer.theAccount.getMailbox('PARTIAL/SUBTHING') - +        time.sleep(1)          self.assertEqual(1, len(mb.messages)) +        msg = mb.messages.get_msg_by_uid(1)          self.assertEqual( -            ['\\SEEN', ], -            mb.messages[1].content['flags'] +            ('\\SEEN', ), +            msg.getFlags()          ) +        #self.assertEqual( +            #'Right now', msg.getInternalDate()) +        parsed = self.parser.parse(open(infile)) +        body = parsed.get_payload()          self.assertEqual( -            'Right now', mb.messages[1].content['date']) -        self.assertEqual(open(infile).read(), mb.messages[1].content['raw']) +            body, +            msg.getBodyFile().read())      @deferred(timeout=None)      def testCheck(self): @@ -1279,14 +1316,19 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):          self.server.theAccount.addMailbox(name)          m = SimpleLEAPServer.theAccount.getMailbox(name) -        m.messages.add_msg('', subject="Message 1", +        m.messages.add_msg('test 1', uid=1, subject="Message 1",                             flags=('\\Deleted', 'AnotherFlag')) -        m.messages.add_msg('', subject="Message 2", flags=('AnotherFlag',)) -        m.messages.add_msg('', subject="Message 3", flags=('\\Deleted',)) +        m.messages.add_msg('test 2', uid=2, subject="Message 2", +                           flags=('AnotherFlag',)) +        m.messages.add_msg('test 3', uid=3, subject="Message 3", +                           flags=('\\Deleted',))          def login():              return self.client.login('testuser', 'password-test') +        def wait(): +            time.sleep(1) +          def select():              return self.client.select(name) @@ -1294,6 +1336,7 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):              return self.client.close()          d = self.connected.addCallback(strip(login)) +        d.addCallbacks(strip(wait), self._ebGeneral)          d.addCallbacks(strip(select), self._ebGeneral)          d.addCallbacks(strip(close), self._ebGeneral)          d.addCallbacks(self._cbStopClient, self._ebGeneral) @@ -1302,8 +1345,10 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):      def _cbTestClose(self, ignored, m):          self.assertEqual(len(m.messages), 1) +        messages = [msg for msg in m.messages] +        self.assertFalse(messages[0] is None)          self.assertEqual( -            m.messages[1].content['subject'], +            messages[0]._hdoc.content['subject'],              'Message 2')          self.failUnless(m.closed) @@ -1315,17 +1360,19 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):          name = 'mailbox-expunge'          SimpleLEAPServer.theAccount.addMailbox(name)          m = SimpleLEAPServer.theAccount.getMailbox(name) -        m.messages.add_msg('', subject="Message 1", +        m.messages.add_msg('test 1', uid=1, subject="Message 1",                             flags=('\\Deleted', 'AnotherFlag')) -        self.failUnless(m.messages.count() == 1) -        m.messages.add_msg('', subject="Message 2", flags=('AnotherFlag',)) -        self.failUnless(m.messages.count() == 2) -        m.messages.add_msg('', subject="Message 3", flags=('\\Deleted',)) -        self.failUnless(m.messages.count() == 3) +        m.messages.add_msg('test 2', uid=2, subject="Message 2", +                           flags=('AnotherFlag',)) +        m.messages.add_msg('test 3', uid=3, subject="Message 3", +                           flags=('\\Deleted',))          def login():              return self.client.login('testuser', 'password-test') +        def wait(): +            time.sleep(2) +          def select():              return self.client.select('mailbox-expunge') @@ -1338,6 +1385,7 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):          self.results = None          d1 = self.connected.addCallback(strip(login)) +        d1.addCallbacks(strip(wait), self._ebGeneral)          d1.addCallbacks(strip(select), self._ebGeneral)          d1.addCallbacks(strip(expunge), self._ebGeneral)          d1.addCallbacks(expunged, self._ebGeneral) @@ -1348,12 +1396,13 @@ class LeapIMAP4ServerTestCase(IMAP4HelperMixin, unittest.TestCase):      def _cbTestExpunge(self, ignored, m):          # we only left 1 mssage with no deleted flag -        self.assertEqual(m.messages.count(), 1) +        self.assertEqual(len(m.messages), 1) +        messages = [msg for msg in m.messages]          self.assertEqual( -            m.messages[1].content['subject'], +            messages[0]._hdoc.content['subject'],              'Message 2') -        self.assertEqual(self.results, [0, 1]) -        # XXX fix this thing with the indexes... +        # the uids of the deleted messages +        self.assertItemsEqual(self.results, [1, 3])  class IMAP4ServerSearchTestCase(IMAP4HelperMixin, unittest.TestCase): @@ -1363,3 +1412,10 @@ class IMAP4ServerSearchTestCase(IMAP4HelperMixin, unittest.TestCase):      """      # XXX coming soon to your screens!      pass + + +def tearDownModule(): +    """ +    Tear down functions for module level +    """ +    stop_reactor() | 
