Home | History | Annotate | Download | only in email
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.email;
     18 
     19 import android.content.ContentUris;
     20 import android.content.Context;
     21 import android.database.Cursor;
     22 import android.net.Uri;
     23 import android.test.ProviderTestCase2;
     24 import android.test.suitebuilder.annotation.Suppress;
     25 
     26 import com.android.email.provider.EmailProvider;
     27 import com.android.email.provider.ProviderTestUtils;
     28 import com.android.emailcommon.internet.MimeBodyPart;
     29 import com.android.emailcommon.internet.MimeHeader;
     30 import com.android.emailcommon.internet.MimeMessage;
     31 import com.android.emailcommon.internet.MimeUtility;
     32 import com.android.emailcommon.internet.TextBody;
     33 import com.android.emailcommon.mail.Address;
     34 import com.android.emailcommon.mail.BodyPart;
     35 import com.android.emailcommon.mail.Flag;
     36 import com.android.emailcommon.mail.Message;
     37 import com.android.emailcommon.mail.Message.RecipientType;
     38 import com.android.emailcommon.mail.MessageTestUtils;
     39 import com.android.emailcommon.mail.MessageTestUtils.MessageBuilder;
     40 import com.android.emailcommon.mail.MessageTestUtils.MultipartBuilder;
     41 import com.android.emailcommon.mail.MessagingException;
     42 import com.android.emailcommon.mail.Part;
     43 import com.android.emailcommon.provider.EmailContent;
     44 import com.android.emailcommon.provider.EmailContent.Attachment;
     45 import com.android.emailcommon.utility.ConversionUtilities;
     46 import com.android.emailcommon.utility.ConversionUtilities.BodyFieldData;
     47 
     48 import java.io.IOException;
     49 import java.util.ArrayList;
     50 import java.util.Date;
     51 
     52 /**
     53  * Tests of the Legacy Conversions code (used by MessagingController).
     54  *
     55  * NOTE:  It would probably make sense to rewrite this using a MockProvider, instead of the
     56  * ProviderTestCase (which is a real provider running on a temp database).  This would be more of
     57  * a true "unit test".
     58  *
     59  * You can run this entire test case with:
     60  *   runtest -c com.android.email.LegacyConversionsTests email
     61  */
     62 @Suppress
     63 public class LegacyConversionsTests extends ProviderTestCase2<EmailProvider> {
     64 
     65     private static final String UID = "UID.12345678";
     66     private static final String SENDER = "sender (at) android.com";
     67     private static final String RECIPIENT_TO = "recipient-to (at) android.com";
     68     private static final String RECIPIENT_CC = "recipient-cc (at) android.com";
     69     private static final String RECIPIENT_BCC = "recipient-bcc (at) android.com";
     70     private static final String REPLY_TO = "reply-to (at) android.com";
     71     private static final String SUBJECT = "This is the subject";
     72     private static final String MESSAGE_ID = "Test-Message-ID";
     73     private static final String MESSAGE_ID_2 = "Test-Message-ID-Second";
     74 
     75     EmailProvider mProvider;
     76     Context mProviderContext;
     77     Context mContext;
     78     Preferences mPreferences = null;
     79 
     80     public LegacyConversionsTests() {
     81         super(EmailProvider.class, EmailContent.AUTHORITY);
     82     }
     83 
     84     @Override
     85     public void setUp() throws Exception {
     86         super.setUp();
     87         mProviderContext = getMockContext();
     88         mContext = getContext();
     89     }
     90 
     91     /**
     92      * TODO: basic Legacy -> Provider Message conversions
     93      * TODO: basic Legacy -> Provider Body conversions
     94      * TODO: rainy day tests of all kinds
     95      */
     96 
     97     /**
     98      * Test basic conversion from Store message to Provider message
     99      *
    100      * TODO: Not a complete test of all fields, and some fields need special tests (e.g. flags)
    101      * TODO: There are many special cases in the tested function, that need to be
    102      * tested here as well.
    103      */
    104     public void testUpdateMessageFields() throws MessagingException {
    105         MimeMessage message = buildTestMessage(RECIPIENT_TO, RECIPIENT_CC, RECIPIENT_BCC,
    106                 REPLY_TO, SENDER, SUBJECT, null);
    107         EmailContent.Message localMessage = new EmailContent.Message();
    108 
    109         boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1);
    110         assertTrue(result);
    111         checkProviderMessage("testUpdateMessageFields", message, localMessage);
    112     }
    113 
    114     /**
    115      * Test basic conversion from Store message to Provider message, when the provider message
    116      * does not have a proper message-id.
    117      */
    118     public void testUpdateMessageFieldsNoMessageId() throws MessagingException {
    119         MimeMessage message = buildTestMessage(RECIPIENT_TO, RECIPIENT_CC, RECIPIENT_BCC,
    120                 REPLY_TO, SENDER, SUBJECT, null);
    121         EmailContent.Message localMessage = new EmailContent.Message();
    122 
    123         // If the source message-id is null, the target should be left as-is
    124         localMessage.mMessageId = MESSAGE_ID_2;
    125         message.removeHeader("Message-ID");
    126 
    127         boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1);
    128         assertTrue(result);
    129         assertEquals(MESSAGE_ID_2, localMessage.mMessageId);
    130     }
    131 
    132     /**
    133      * Build a lightweight Store message with simple field population
    134      */
    135     private MimeMessage buildTestMessage(String to, String cc, String bcc, String replyTo,
    136             String sender, String subject, String content) throws MessagingException {
    137         MimeMessage message = new MimeMessage();
    138 
    139         if (to != null) {
    140             Address[] addresses = Address.parse(to);
    141             message.setRecipients(RecipientType.TO, addresses);
    142         }
    143         if (cc != null) {
    144             Address[] addresses = Address.parse(cc);
    145             message.setRecipients(RecipientType.CC, addresses);
    146         }
    147         if (bcc != null) {
    148             Address[] addresses = Address.parse(bcc);
    149             message.setRecipients(RecipientType.BCC, addresses);
    150         }
    151         if (replyTo != null) {
    152             Address[] addresses = Address.parse(replyTo);
    153             message.setReplyTo(addresses);
    154         }
    155         if (sender != null) {
    156             Address[] addresses = Address.parse(sender);
    157             message.setFrom(addresses[0]);
    158         }
    159         if (subject != null) {
    160             message.setSubject(subject);
    161         }
    162         if (content != null) {
    163             TextBody body = new TextBody(content);
    164             message.setBody(body);
    165         }
    166 
    167         message.setUid(UID);
    168         message.setSentDate(new Date());
    169         message.setInternalDate(new Date());
    170         message.setMessageId(MESSAGE_ID);
    171         return message;
    172     }
    173 
    174     /**
    175      * Basic test of body parts conversion from Store message to Provider message.
    176      * This tests that a null body part simply results in null text, and does not crash
    177      * or return "null".
    178      *
    179      * TODO very incomplete, there are many permutations to be explored
    180      */
    181     public void testUpdateBodyFieldsNullText() throws MessagingException {
    182         EmailContent.Body localBody = new EmailContent.Body();
    183         EmailContent.Message localMessage = new EmailContent.Message();
    184         ArrayList<Part> viewables = new ArrayList<Part>();
    185         Part emptyTextPart = new MimeBodyPart(null, "text/plain");
    186         viewables.add(emptyTextPart);
    187 
    188         // a "null" body part of type text/plain should result in a null mTextContent
    189         final BodyFieldData data =
    190                 ConversionUtilities.parseBodyFields(viewables);
    191         assertNull(data.textContent);
    192     }
    193 
    194     /**
    195      * Sunny day test of adding attachments from an IMAP/POP message.
    196      */
    197     public void testAddAttachments() throws MessagingException, IOException {
    198         // Prepare a local message to add the attachments to
    199         final long accountId = 1;
    200         final long mailboxId = 1;
    201 
    202         // test 1: legacy message using content-type:name style for name
    203         final EmailContent.Message localMessage = ProviderTestUtils.setupMessage(
    204                 "local-message", accountId, mailboxId, false, true, mProviderContext);
    205         final Message legacyMessage = prepareLegacyMessageWithAttachments(2, false);
    206         convertAndCheckcheckAddedAttachments(localMessage, legacyMessage);
    207 
    208         // test 2: legacy message using content-disposition:filename style for name
    209         final EmailContent.Message localMessage2 = ProviderTestUtils.setupMessage(
    210                 "local-message", accountId, mailboxId, false, true, mProviderContext);
    211         final Message legacyMessage2 = prepareLegacyMessageWithAttachments(2, true);
    212         convertAndCheckcheckAddedAttachments(localMessage2, legacyMessage2);
    213     }
    214 
    215     /**
    216      * Helper for testAddAttachments
    217      */
    218     private void convertAndCheckcheckAddedAttachments(final EmailContent.Message localMessage,
    219             final Message legacyMessage) throws MessagingException, IOException {
    220         // Now, convert from legacy to provider and see what happens
    221         ArrayList<Part> viewables = new ArrayList<Part>();
    222         ArrayList<Part> attachments = new ArrayList<Part>();
    223         MimeUtility.collectParts(legacyMessage, viewables, attachments);
    224         LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments);
    225 
    226         // Read back all attachments for message and check field values
    227         Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId);
    228         Cursor c = mProviderContext.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION,
    229                 null, null, null);
    230         try {
    231             assertEquals(2, c.getCount());
    232             while (c.moveToNext()) {
    233                 Attachment attachment = Attachment.getContent(c, Attachment.class);
    234                 if ("100".equals(attachment.mLocation)) {
    235                     checkAttachment("attachment1Part", attachments.get(0), attachment,
    236                             localMessage.mAccountKey);
    237                 } else if ("101".equals(attachment.mLocation)) {
    238                     checkAttachment("attachment2Part", attachments.get(1), attachment,
    239                             localMessage.mAccountKey);
    240                 } else {
    241                     fail("Unexpected attachment with location " + attachment.mLocation);
    242                 }
    243             }
    244         } finally {
    245             c.close();
    246         }
    247     }
    248 
    249     /**
    250      * Test that only "attachment" or "inline" attachments are captured and added.
    251      * @throws MessagingException
    252      * @throws IOException
    253      */
    254     public void testAttachmentDispositions() throws MessagingException, IOException {
    255         // Prepare a local message to add the attachments to
    256         final long accountId = 1;
    257         final long mailboxId = 1;
    258 
    259         // Prepare the three attachments we want to test
    260         BodyPart[] sourceAttachments = new BodyPart[3];
    261         BodyPart attachmentPart;
    262 
    263         // 1. Standard attachment
    264         attachmentPart = MessageTestUtils.bodyPart("image/jpg", null);
    265         attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "image/jpg");
    266         attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
    267         attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION,
    268                 "attachment;\n filename=\"file-1\";\n size=100");
    269         attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "100");
    270         sourceAttachments[0] = attachmentPart;
    271 
    272         // 2. Inline attachment
    273         attachmentPart = MessageTestUtils.bodyPart("image/gif", null);
    274         attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "image/gif");
    275         attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
    276         attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION,
    277                 "inline;\n filename=\"file-2\";\n size=200");
    278         attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "101");
    279         sourceAttachments[1] = attachmentPart;
    280 
    281         // 3. Neither (use VCALENDAR)
    282         attachmentPart = MessageTestUtils.bodyPart("text/calendar", null);
    283         attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE,
    284                 "text/calendar; charset=UTF-8; method=REQUEST");
    285         attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "7bit");
    286         attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "102");
    287         sourceAttachments[2] = attachmentPart;
    288 
    289         // Prepare local message (destination) and legacy message w/attachments (source)
    290         final EmailContent.Message localMessage = ProviderTestUtils.setupMessage(
    291                 "local-message", accountId, mailboxId, false, true, mProviderContext);
    292         final Message legacyMessage = prepareLegacyMessageWithAttachments(sourceAttachments);
    293         convertAndCheckcheckAddedAttachments(localMessage, legacyMessage);
    294 
    295         // Run the conversion and check for the converted attachments - this test asserts
    296         // that there are two attachments numbered 100 & 101 (so will fail if it finds 102)
    297         convertAndCheckcheckAddedAttachments(localMessage, legacyMessage);
    298     }
    299 
    300     /**
    301      * Test that attachments aren't re-added in the DB.  This supports the "partial download"
    302      * nature of POP messages.
    303      */
    304     public void testAddDuplicateAttachments() throws MessagingException, IOException {
    305         // Prepare a local message to add the attachments to
    306         final long accountId = 1;
    307         final long mailboxId = 1;
    308         final EmailContent.Message localMessage = ProviderTestUtils.setupMessage(
    309                 "local-message", accountId, mailboxId, false, true, mProviderContext);
    310 
    311         // Prepare a legacy message with attachments
    312         Message legacyMessage = prepareLegacyMessageWithAttachments(2, false);
    313 
    314         // Now, convert from legacy to provider and see what happens
    315         ArrayList<Part> viewables = new ArrayList<Part>();
    316         ArrayList<Part> attachments = new ArrayList<Part>();
    317         MimeUtility.collectParts(legacyMessage, viewables, attachments);
    318         LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments);
    319 
    320         // Confirm two attachment objects created
    321         Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId);
    322         assertEquals(2, EmailContent.count(mProviderContext, uri, null, null));
    323 
    324         // Now add the attachments again and confirm there are still only two
    325         LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments);
    326         assertEquals(2, EmailContent.count(mProviderContext, uri, null, null));
    327 
    328         // Now add a 3rd & 4th attachment and make sure the total is 4, not 2 or 6
    329         legacyMessage = prepareLegacyMessageWithAttachments(4, false);
    330         viewables = new ArrayList<Part>();
    331         attachments = new ArrayList<Part>();
    332         MimeUtility.collectParts(legacyMessage, viewables, attachments);
    333         LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments);
    334         assertEquals(4, EmailContent.count(mProviderContext, uri, null, null));
    335     }
    336 
    337     /**
    338      * Prepare a legacy message with 1+ attachments
    339      * @param numAttachments how many attachments to add
    340      * @param filenameInDisposition False: attachment names are sent as content-type:name.  True:
    341      *          attachment names are sent as content-disposition:filename.
    342      */
    343     private Message prepareLegacyMessageWithAttachments(int numAttachments,
    344             boolean filenameInDisposition) throws MessagingException {
    345         BodyPart[] attachmentParts = new BodyPart[numAttachments];
    346         for (int i = 0; i < numAttachments; ++i) {
    347             // construct parameter parts for content-type:name or content-disposition:filename.
    348             String name = "";
    349             String filename = "";
    350             String quotedName = "\"test-attachment-" + i + "\"";
    351             if (filenameInDisposition) {
    352                 filename = ";\n filename=" + quotedName;
    353             } else {
    354                 name = ";\n name=" + quotedName;
    355             }
    356 
    357             // generate an attachment that came from a server
    358             BodyPart attachmentPart = MessageTestUtils.bodyPart("image/jpg", null);
    359 
    360             // name=attachmentN size=N00 location=10N
    361             attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "image/jpg" + name);
    362             attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64");
    363             attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION,
    364                     "attachment" + filename +  ";\n size=" + (i+1) + "00");
    365             attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "10" + i);
    366 
    367             attachmentParts[i] = attachmentPart;
    368         }
    369 
    370         return prepareLegacyMessageWithAttachments(attachmentParts);
    371     }
    372 
    373     /**
    374      * Prepare a legacy message with 1+ attachments
    375      * @param attachments array containing one or more attachments
    376      */
    377     private Message prepareLegacyMessageWithAttachments(BodyPart[] attachments)
    378             throws MessagingException {
    379         // Build the multipart that holds the attachments
    380         MultipartBuilder mpBuilder = new MultipartBuilder("multipart/mixed");
    381         for (int i = 0; i < attachments.length; ++i) {
    382             mpBuilder.addBodyPart(attachments[i]);
    383         }
    384 
    385         // Now build a message with them
    386         final Message legacyMessage = new MessageBuilder()
    387             .setBody(new MultipartBuilder("multipart/mixed")
    388                      .addBodyPart(MessageTestUtils.bodyPart("text/html", null))
    389                      .addBodyPart(mpBuilder.buildBodyPart())
    390                      .build())
    391                 .build();
    392 
    393         return legacyMessage;
    394     }
    395 
    396     /**
    397      * Test the stringInequal helper
    398      */
    399     public void testStringInequal() {
    400         // Pairs that are "equal"
    401         assertFalse(LegacyConversions.stringNotEqual(null, null));
    402         assertFalse(LegacyConversions.stringNotEqual(null, ""));
    403         assertFalse(LegacyConversions.stringNotEqual("", null));
    404         assertFalse(LegacyConversions.stringNotEqual("", ""));
    405         assertFalse(LegacyConversions.stringNotEqual("string-equal", "string-equal"));
    406         // Pairs that are "inequal"
    407         assertTrue(LegacyConversions.stringNotEqual(null, "string-inequal"));
    408         assertTrue(LegacyConversions.stringNotEqual("", "string-inequal"));
    409         assertTrue(LegacyConversions.stringNotEqual("string-inequal", null));
    410         assertTrue(LegacyConversions.stringNotEqual("string-inequal", ""));
    411         assertTrue(LegacyConversions.stringNotEqual("string-inequal-a", "string-inequal-b"));
    412     }
    413 
    414     /**
    415      * Compare attachment that was converted from Part (expected) to Provider Attachment (actual)
    416      *
    417      * TODO content URI should only be set if we also saved a file
    418      * TODO other data encodings
    419      */
    420     private void checkAttachment(String tag, Part expected, EmailContent.Attachment actual,
    421             long accountKey) throws MessagingException {
    422         String contentType = MimeUtility.unfoldAndDecode(expected.getContentType());
    423         String contentTypeName = MimeUtility.getHeaderParameter(contentType, "name");
    424         assertEquals(tag, expected.getMimeType(), actual.mMimeType);
    425         String disposition = expected.getDisposition();
    426         String sizeString = MimeUtility.getHeaderParameter(disposition, "size");
    427         String dispositionFilename = MimeUtility.getHeaderParameter(disposition, "filename");
    428         long expectedSize = (sizeString != null) ? Long.parseLong(sizeString) : 0;
    429         assertEquals(tag, expectedSize, actual.mSize);
    430         assertEquals(tag, expected.getContentId(), actual.mContentId);
    431 
    432         // filename is either content-type:name or content-disposition:filename
    433         String expectedName = (contentTypeName != null) ? contentTypeName : dispositionFilename;
    434         assertEquals(tag, expectedName, actual.mFileName);
    435 
    436         // content URI should be null
    437         assertNull(tag, actual.getContentUri());
    438 
    439         assertTrue(tag, 0 != actual.mMessageKey);
    440 
    441         // location is either both null or both matching
    442         String expectedPartId = null;
    443         String[] storeData = expected.getHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA);
    444         if (storeData != null && storeData.length > 0) {
    445             expectedPartId = storeData[0];
    446         }
    447         assertEquals(tag, expectedPartId, actual.mLocation);
    448         assertEquals(tag, "B", actual.mEncoding);
    449         assertEquals(tag, accountKey, actual.mAccountKey);
    450     }
    451 
    452     /**
    453      * TODO: Sunny day test of adding attachments from a POP message.
    454      */
    455 
    456     /**
    457      * Sunny day tests of converting an original message to a legacy message
    458      */
    459     public void testMakeLegacyMessage() throws MessagingException {
    460         // Set up and store a message in the provider
    461         long account1Id = 1;
    462         long mailbox1Id = 1;
    463 
    464         // Test message 1: No body
    465         EmailContent.Message localMessage1 = ProviderTestUtils.setupMessage("make-legacy",
    466                 account1Id, mailbox1Id, false, true, mProviderContext);
    467         Message getMessage1 = LegacyConversions.makeMessage(mProviderContext, localMessage1);
    468         checkLegacyMessage("no body", localMessage1, getMessage1);
    469 
    470         // Test message 2: Simple body
    471         EmailContent.Message localMessage2 = ProviderTestUtils.setupMessage("make-legacy",
    472                 account1Id, mailbox1Id, true, false, mProviderContext);
    473         localMessage2.mTextReply = null;
    474         localMessage2.mHtmlReply = null;
    475         localMessage2.mIntroText = null;
    476         localMessage2.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK;
    477         localMessage2.save(mProviderContext);
    478         Message getMessage2 = LegacyConversions.makeMessage(mProviderContext, localMessage2);
    479         checkLegacyMessage("simple body", localMessage2, getMessage2);
    480 
    481         // Test message 3: Body + replied-to text
    482         EmailContent.Message localMessage3 = ProviderTestUtils.setupMessage("make-legacy",
    483                 account1Id, mailbox1Id, true, false, mProviderContext);
    484         localMessage3.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK;
    485         localMessage3.mFlags |= EmailContent.Message.FLAG_TYPE_REPLY;
    486         localMessage3.save(mProviderContext);
    487         Message getMessage3 = LegacyConversions.makeMessage(mProviderContext, localMessage3);
    488         checkLegacyMessage("reply-to", localMessage3, getMessage3);
    489 
    490         // Test message 4: Body + forwarded text
    491         EmailContent.Message localMessage4 = ProviderTestUtils.setupMessage("make-legacy",
    492                 account1Id, mailbox1Id, true, false, mProviderContext);
    493         localMessage4.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK;
    494         localMessage4.mFlags |= EmailContent.Message.FLAG_TYPE_FORWARD;
    495         localMessage4.save(mProviderContext);
    496         Message getMessage4 = LegacyConversions.makeMessage(mProviderContext, localMessage4);
    497         checkLegacyMessage("forwarding", localMessage4, getMessage4);
    498     }
    499 
    500     /**
    501      * Check equality of a pair of converted messages
    502      */
    503     private void checkProviderMessage(String tag, Message expect, EmailContent.Message actual)
    504             throws MessagingException {
    505         assertEquals(tag, expect.getUid(), actual.mServerId);
    506         assertEquals(tag, expect.getSubject(), actual.mSubject);
    507         assertEquals(tag, Address.pack(expect.getFrom()), actual.mFrom);
    508         assertEquals(tag, expect.getSentDate().getTime(), actual.mTimeStamp);
    509         assertEquals(tag, Address.pack(expect.getRecipients(RecipientType.TO)), actual.mTo);
    510         assertEquals(tag, Address.pack(expect.getRecipients(RecipientType.CC)), actual.mCc);
    511         assertEquals(tag, ((MimeMessage)expect).getMessageId(), actual.mMessageId);
    512         assertEquals(tag, expect.isSet(Flag.SEEN), actual.mFlagRead);
    513         assertEquals(tag, expect.isSet(Flag.FLAGGED), actual.mFlagFavorite);
    514     }
    515 
    516     /**
    517      * Check equality of a pair of converted messages
    518      */
    519     private void checkLegacyMessage(String tag, EmailContent.Message expect, Message actual)
    520             throws MessagingException {
    521         assertEquals(tag, expect.mServerId, actual.getUid());
    522         assertEquals(tag, expect.mServerTimeStamp, actual.getInternalDate().getTime());
    523         assertEquals(tag, expect.mSubject, actual.getSubject());
    524         assertEquals(tag, expect.mFrom, Address.pack(actual.getFrom()));
    525         assertEquals(tag, expect.mTimeStamp, actual.getSentDate().getTime());
    526         assertEquals(tag, expect.mTo, Address.pack(actual.getRecipients(RecipientType.TO)));
    527         assertEquals(tag, expect.mCc, Address.pack(actual.getRecipients(RecipientType.CC)));
    528         assertEquals(tag, expect.mBcc, Address.pack(actual.getRecipients(RecipientType.BCC)));
    529         assertEquals(tag, expect.mReplyTo, Address.pack(actual.getReplyTo()));
    530         assertEquals(tag, expect.mMessageId, ((MimeMessage)actual).getMessageId());
    531         // check flags
    532         assertEquals(tag, expect.mFlagRead, actual.isSet(Flag.SEEN));
    533         assertEquals(tag, expect.mFlagFavorite, actual.isSet(Flag.FLAGGED));
    534 
    535         // Check the body of the message
    536         ArrayList<Part> viewables = new ArrayList<Part>();
    537         ArrayList<Part> attachments = new ArrayList<Part>();
    538         MimeUtility.collectParts(actual, viewables, attachments);
    539         String get1Text = null;
    540         String get1Html = null;
    541         String get1TextReply = null;
    542         String get1HtmlReply = null;
    543         String get1TextIntro = null;
    544         for (Part viewable : viewables) {
    545             String text = MimeUtility.getTextFromPart(viewable);
    546             boolean isHtml = viewable.getMimeType().equalsIgnoreCase("text/html");
    547             String[] headers = viewable.getHeader(MimeHeader.HEADER_ANDROID_BODY_QUOTED_PART);
    548             if (headers != null) {
    549                 String header = headers[0];
    550                 boolean isReply = LegacyConversions.BODY_QUOTED_PART_REPLY.equalsIgnoreCase(header);
    551                 boolean isFwd = LegacyConversions.BODY_QUOTED_PART_FORWARD.equalsIgnoreCase(header);
    552                 boolean isIntro = LegacyConversions.BODY_QUOTED_PART_INTRO.equalsIgnoreCase(header);
    553                 if (isReply || isFwd) {
    554                     if (isHtml) {
    555                         get1HtmlReply = text;
    556                     } else {
    557                         get1TextReply = text;
    558                     }
    559                 } else if (isIntro) {
    560                     get1TextIntro = text;
    561                 }
    562                 // Check flags
    563                 int replyTypeFlags = expect.mFlags & EmailContent.Message.FLAG_TYPE_MASK;
    564                 if (isReply) {
    565                     assertEquals(tag, EmailContent.Message.FLAG_TYPE_REPLY, replyTypeFlags);
    566                 }
    567                 if (isFwd) {
    568                     assertEquals(tag, EmailContent.Message.FLAG_TYPE_FORWARD, replyTypeFlags);
    569                 }
    570             } else {
    571                 if (isHtml) {
    572                     get1Html = text;
    573                 } else {
    574                     get1Text = text;
    575                 }
    576             }
    577         }
    578         assertEquals(tag, expect.mText, get1Text);
    579         assertEquals(tag, expect.mHtml, get1Html);
    580         assertEquals(tag, expect.mTextReply, get1TextReply);
    581         assertEquals(tag, expect.mHtmlReply, get1HtmlReply);
    582         assertEquals(tag, expect.mIntroText, get1TextIntro);
    583 
    584         // TODO Check the attachments
    585 
    586 //      cv.put("attachment_count", attachments.size());
    587     }
    588 }
    589