From 06ac408dbd7629d387dd7b311a26c144ee56631e Mon Sep 17 00:00:00 2001 From: mnandri Date: Thu, 17 Dec 2015 18:41:58 +0100 Subject: extracted a leap attachment store, handling all attachment responsibilities, including saving attachments. Issue #548 --- .../mailstore/test_leap_attachment_store.py | 119 +++++++++++++++++++++ .../unit/adapter/mailstore/test_leap_mailstore.py | 39 ------- service/test/unit/adapter/test_mail_service.py | 5 +- 3 files changed, 122 insertions(+), 41 deletions(-) create mode 100644 service/test/unit/adapter/mailstore/test_leap_attachment_store.py (limited to 'service/test/unit/adapter') diff --git a/service/test/unit/adapter/mailstore/test_leap_attachment_store.py b/service/test/unit/adapter/mailstore/test_leap_attachment_store.py new file mode 100644 index 00000000..172cceb6 --- /dev/null +++ b/service/test/unit/adapter/mailstore/test_leap_attachment_store.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2015 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . +import json +from uuid import uuid4 + +from leap.mail.adaptors.soledad_indexes import MAIL_INDEXES +from leap.soledad.common.document import SoledadDocument +from mockito import mock, when, verify +import test.support.mockito +from twisted.internet import defer +from twisted.trial.unittest import TestCase +from leap.mail.adaptors.soledad import SoledadMailAdaptor, MailboxWrapper, ContentDocWrapper + +from pixelated.adapter.mailstore.leap_attachment_store import LeapAttachmentStore + + +class TestLeapAttachmentStore(TestCase): + def setUp(self): + self.soledad = mock() + self.mbox_uuid = str(uuid4()) + self.doc_by_id = {} + self.mbox_uuid_by_name = {} + self.mbox_soledad_docs = [] + + when(self.soledad).get_from_index('by-type', 'mbox').thenAnswer(lambda: defer.succeed(self.mbox_soledad_docs)) + self._mock_get_mailbox('INBOX') + + @defer.inlineCallbacks + def test_get_mail_attachment(self): + attachment_id = 'AAAA9AAD9E153D24265395203C53884506ABA276394B9FEC02B214BF9E77E48E' + doc = SoledadDocument(json=json.dumps({'content_type': 'foo/bar', 'raw': 'asdf'})) + when(self.soledad).get_from_index('by-type-and-payloadhash', 'cnt', attachment_id).thenReturn(defer.succeed([doc])) + store = LeapAttachmentStore(self.soledad) + + attachment = yield store.get_mail_attachment(attachment_id) + + self.assertEqual({'content-type': 'foo/bar', 'content': bytearray('asdf')}, attachment) + + @defer.inlineCallbacks + def test_store_attachment(self): + content = 'this is some attachment content' + content_type = 'text/plain' + cdoc_serialized = {'content_transfer_encoding': 'base64', 'lkf': [], 'content_disposition': 'attachment', + 'ctype': '', 'raw': 'dGhpcyBpcyBzb21lIGF0dGFjaG1lbnQgY29udGVudA==', + 'phash': '9863729729D2E2EE8E52F0A7115CE33AD18DDA4B58E49AE08DD092D1C8E699B0', + 'content_type': 'text/plain', 'type': 'cnt'} + + store = LeapAttachmentStore(self.soledad) + + attachment_id = yield store.add_attachment(content, content_type) + + self.assertEqual('9863729729D2E2EE8E52F0A7115CE33AD18DDA4B58E49AE08DD092D1C8E699B0', attachment_id) + + verify(self.soledad).create_doc(cdoc_serialized, doc_id=attachment_id) + + @defer.inlineCallbacks + def test_get_mail_attachment_different_content_encodings(self): + attachment_id = '1B0A9AAD9E153D24265395203C53884506ABA276394B9FEC02B214BF9E77E48E' + encoding_examples = [('', 'asdf', 'asdf'), + ('base64', 'asdf', 'YXNkZg=='), + ('quoted-printable', 'äsdf', '=C3=A4sdf')] + + for transfer_encoding, data, encoded_data in encoding_examples: + doc = SoledadDocument(json=json.dumps({'content_type': 'foo/bar', 'raw': encoded_data, + 'content_transfer_encoding': transfer_encoding})) + when(self.soledad).get_from_index('by-type-and-payloadhash', 'cnt', attachment_id).thenReturn(defer.succeed([doc])) + store = LeapAttachmentStore(self.soledad) + + attachment = yield store.get_mail_attachment(attachment_id) + + self.assertEqual(bytearray(data), attachment['content']) + + @defer.inlineCallbacks + def test_get_mail_attachment_throws_exception_if_attachment_does_not_exist(self): + attachment_id = '1B0A9AAD9E153D24265395203C53884506ABA276394B9FEC02B214BF9E77E48E' + when(self.soledad).get_from_index('by-type-and-payloadhash', 'cnt', attachment_id).thenReturn(defer.succeed([])) + store = LeapAttachmentStore(self.soledad) + try: + yield store.get_mail_attachment(attachment_id) + self.fail('ValueError exception expected') + except ValueError: + pass + + def _mock_get_mailbox(self, mailbox_name, create_new_uuid=False): + mbox_uuid = self.mbox_uuid if not create_new_uuid else str(uuid4()) + when(self.soledad).list_indexes().thenReturn(defer.succeed(MAIL_INDEXES)).thenReturn( + defer.succeed(MAIL_INDEXES)) + doc_id = str(uuid4()) + mbox = MailboxWrapper(doc_id=doc_id, mbox=mailbox_name, uuid=mbox_uuid) + soledad_doc = SoledadDocument(doc_id, json=json.dumps(mbox.serialize())) + when(self.soledad).get_from_index('by-type-and-mbox', 'mbox', mailbox_name).thenReturn(defer.succeed([soledad_doc])) + self._mock_get_soledad_doc(doc_id, mbox) + + self.mbox_uuid_by_name[mailbox_name] = mbox_uuid + self.mbox_soledad_docs.append(soledad_doc) + + return mbox, soledad_doc + + def _mock_get_soledad_doc(self, doc_id, doc): + soledad_doc = SoledadDocument(doc_id, json=json.dumps(doc.serialize())) + + # when(self.soledad).get_doc(doc_id).thenReturn(defer.succeed(soledad_doc)) + when(self.soledad).get_doc(doc_id).thenAnswer(lambda: defer.succeed(soledad_doc)) + + self.doc_by_id[doc_id] = soledad_doc diff --git a/service/test/unit/adapter/mailstore/test_leap_mailstore.py b/service/test/unit/adapter/mailstore/test_leap_mailstore.py index 4eabc144..b5b6a742 100644 --- a/service/test/unit/adapter/mailstore/test_leap_mailstore.py +++ b/service/test/unit/adapter/mailstore/test_leap_mailstore.py @@ -134,45 +134,6 @@ class TestLeapMailStore(TestCase): self.assertEqual(expeted_body, mail.body) - @defer.inlineCallbacks - def test_get_mail_attachment(self): - attachment_id = 'AAAA9AAD9E153D24265395203C53884506ABA276394B9FEC02B214BF9E77E48E' - doc = SoledadDocument(json=json.dumps({'content_type': 'foo/bar', 'raw': 'asdf'})) - when(self.soledad).get_from_index('by-type-and-payloadhash', 'cnt', attachment_id).thenReturn(defer.succeed([doc])) - store = LeapMailStore(self.soledad) - - attachment = yield store.get_mail_attachment(attachment_id) - - self.assertEqual({'content-type': 'foo/bar', 'content': bytearray('asdf')}, attachment) - - @defer.inlineCallbacks - def test_get_mail_attachment_different_content_encodings(self): - attachment_id = '1B0A9AAD9E153D24265395203C53884506ABA276394B9FEC02B214BF9E77E48E' - encoding_examples = [('', 'asdf', 'asdf'), - ('base64', 'asdf', 'YXNkZg=='), - ('quoted-printable', 'äsdf', '=C3=A4sdf')] - - for transfer_encoding, data, encoded_data in encoding_examples: - doc = SoledadDocument(json=json.dumps({'content_type': 'foo/bar', 'raw': encoded_data, - 'content_transfer_encoding': transfer_encoding})) - when(self.soledad).get_from_index('by-type-and-payloadhash', 'cnt', attachment_id).thenReturn(defer.succeed([doc])) - store = LeapMailStore(self.soledad) - - attachment = yield store.get_mail_attachment(attachment_id) - - self.assertEqual(bytearray(data), attachment['content']) - - @defer.inlineCallbacks - def test_get_mail_attachment_throws_exception_if_attachment_does_not_exist(self): - attachment_id = '1B0A9AAD9E153D24265395203C53884506ABA276394B9FEC02B214BF9E77E48E' - when(self.soledad).get_from_index('by-type-and-payloadhash', 'cnt', attachment_id).thenReturn(defer.succeed([])) - store = LeapMailStore(self.soledad) - try: - yield store.get_mail_attachment(attachment_id) - self.fail('ValueError exception expected') - except ValueError: - pass - @defer.inlineCallbacks def test_update_mail(self): mdoc_id, fdoc_id = self._add_mail_fixture_to_soledad_from_file('mbox00000000') diff --git a/service/test/unit/adapter/test_mail_service.py b/service/test/unit/adapter/test_mail_service.py index d14a0eb0..27c80fde 100644 --- a/service/test/unit/adapter/test_mail_service.py +++ b/service/test/unit/adapter/test_mail_service.py @@ -28,6 +28,7 @@ class TestMailService(unittest.TestCase): def setUp(self): self.drafts = mock() self.mail_store = mock() + self.attachment_store = mock() self.mailboxes = mock() self.mailboxes.drafts = defer.succeed(self.drafts) @@ -37,7 +38,7 @@ class TestMailService(unittest.TestCase): self.mail_sender = mock() self.search_engine = mock() - self.mail_service = MailService(self.mail_sender, self.mail_store, self.search_engine, 'acount@email') + self.mail_service = MailService(self.mail_sender, self.mail_store, self.search_engine, 'acount@email', self.attachment_store) def tearDown(self): unstub() @@ -158,7 +159,7 @@ class TestMailService(unittest.TestCase): @defer.inlineCallbacks def test_get_attachment(self): attachment_dict = {'content': bytearray('data'), 'content-type': 'text/plain'} - when(self.mail_store).get_mail_attachment('some attachment id').thenReturn(defer.succeed(attachment_dict)) + when(self.attachment_store).get_mail_attachment('some attachment id').thenReturn(defer.succeed(attachment_dict)) attachment = yield self.mail_service.attachment('some attachment id') -- cgit v1.2.3