LegacyConversionsTests.java revision 2193962ca2b3157e79f731736afa2a0c972e778a
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 17package com.android.email; 18 19import com.android.email.provider.EmailContent; 20import com.android.email.provider.EmailProvider; 21import com.android.email.provider.ProviderTestUtils; 22import com.android.email.provider.EmailContent.Attachment; 23import com.android.emailcommon.internet.MimeBodyPart; 24import com.android.emailcommon.internet.MimeHeader; 25import com.android.emailcommon.internet.MimeMessage; 26import com.android.emailcommon.internet.MimeUtility; 27import com.android.emailcommon.internet.TextBody; 28import com.android.emailcommon.mail.Address; 29import com.android.emailcommon.mail.BodyPart; 30import com.android.emailcommon.mail.Flag; 31import com.android.emailcommon.mail.Message; 32import com.android.emailcommon.mail.MessageTestUtils; 33import com.android.emailcommon.mail.MessagingException; 34import com.android.emailcommon.mail.Part; 35import com.android.emailcommon.mail.Message.RecipientType; 36import com.android.emailcommon.mail.MessageTestUtils.MessageBuilder; 37import com.android.emailcommon.mail.MessageTestUtils.MultipartBuilder; 38import com.android.emailcommon.utility.ConversionUtilities; 39 40import android.content.ContentUris; 41import android.content.Context; 42import android.database.Cursor; 43import android.net.Uri; 44import android.test.ProviderTestCase2; 45 46import java.io.IOException; 47import java.util.ArrayList; 48import java.util.Date; 49 50/** 51 * Tests of the Legacy Conversions code (used by MessagingController). 52 * 53 * NOTE: It would probably make sense to rewrite this using a MockProvider, instead of the 54 * ProviderTestCase (which is a real provider running on a temp database). This would be more of 55 * a true "unit test". 56 * 57 * You can run this entire test case with: 58 * runtest -c com.android.email.LegacyConversionsTests email 59 */ 60public class LegacyConversionsTests extends ProviderTestCase2<EmailProvider> { 61 62 private static final String UID = "UID.12345678"; 63 private static final String SENDER = "sender@android.com"; 64 private static final String RECIPIENT_TO = "recipient-to@android.com"; 65 private static final String RECIPIENT_CC = "recipient-cc@android.com"; 66 private static final String RECIPIENT_BCC = "recipient-bcc@android.com"; 67 private static final String REPLY_TO = "reply-to@android.com"; 68 private static final String SUBJECT = "This is the subject"; 69 private static final String MESSAGE_ID = "Test-Message-ID"; 70 private static final String MESSAGE_ID_2 = "Test-Message-ID-Second"; 71 72 EmailProvider mProvider; 73 Context mProviderContext; 74 Context mContext; 75 Account mLegacyAccount = null; 76 Preferences mPreferences = null; 77 78 public LegacyConversionsTests() { 79 super(EmailProvider.class, EmailProvider.EMAIL_AUTHORITY); 80 } 81 82 @Override 83 public void setUp() throws Exception { 84 super.setUp(); 85 mProviderContext = getMockContext(); 86 mContext = getContext(); 87 } 88 89 @Override 90 public void tearDown() throws Exception { 91 super.tearDown(); 92 if (mLegacyAccount != null) { 93 mLegacyAccount.delete(mPreferences); 94 } 95 } 96 97 /** 98 * TODO: basic Legacy -> Provider Message conversions 99 * TODO: basic Legacy -> Provider Body conversions 100 * TODO: rainy day tests of all kinds 101 */ 102 103 /** 104 * Test basic conversion from Store message to Provider message 105 * 106 * TODO: Not a complete test of all fields, and some fields need special tests (e.g. flags) 107 * TODO: There are many special cases in the tested function, that need to be 108 * tested here as well. 109 */ 110 public void testUpdateMessageFields() throws MessagingException { 111 MimeMessage message = buildTestMessage(RECIPIENT_TO, RECIPIENT_CC, RECIPIENT_BCC, 112 REPLY_TO, SENDER, SUBJECT, null); 113 EmailContent.Message localMessage = new EmailContent.Message(); 114 115 boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1); 116 assertTrue(result); 117 checkProviderMessage("testUpdateMessageFields", message, localMessage); 118 } 119 120 /** 121 * Test basic conversion from Store message to Provider message, when the provider message 122 * does not have a proper message-id. 123 */ 124 public void testUpdateMessageFieldsNoMessageId() throws MessagingException { 125 MimeMessage message = buildTestMessage(RECIPIENT_TO, RECIPIENT_CC, RECIPIENT_BCC, 126 REPLY_TO, SENDER, SUBJECT, null); 127 EmailContent.Message localMessage = new EmailContent.Message(); 128 129 // If the source message-id is null, the target should be left as-is 130 localMessage.mMessageId = MESSAGE_ID_2; 131 message.removeHeader("Message-ID"); 132 133 boolean result = LegacyConversions.updateMessageFields(localMessage, message, 1, 1); 134 assertTrue(result); 135 assertEquals(MESSAGE_ID_2, localMessage.mMessageId); 136 } 137 138 /** 139 * Build a lightweight Store message with simple field population 140 */ 141 private MimeMessage buildTestMessage(String to, String cc, String bcc, String replyTo, 142 String sender, String subject, String content) throws MessagingException { 143 MimeMessage message = new MimeMessage(); 144 145 if (to != null) { 146 Address[] addresses = Address.parse(to); 147 message.setRecipients(RecipientType.TO, addresses); 148 } 149 if (cc != null) { 150 Address[] addresses = Address.parse(cc); 151 message.setRecipients(RecipientType.CC, addresses); 152 } 153 if (bcc != null) { 154 Address[] addresses = Address.parse(bcc); 155 message.setRecipients(RecipientType.BCC, addresses); 156 } 157 if (replyTo != null) { 158 Address[] addresses = Address.parse(replyTo); 159 message.setReplyTo(addresses); 160 } 161 if (sender != null) { 162 Address[] addresses = Address.parse(sender); 163 message.setFrom(addresses[0]); 164 } 165 if (subject != null) { 166 message.setSubject(subject); 167 } 168 if (content != null) { 169 TextBody body = new TextBody(content); 170 message.setBody(body); 171 } 172 173 message.setUid(UID); 174 message.setSentDate(new Date()); 175 message.setInternalDate(new Date()); 176 message.setMessageId(MESSAGE_ID); 177 return message; 178 } 179 180 /** 181 * Basic test of body parts conversion from Store message to Provider message. 182 * This tests that a null body part simply results in null text, and does not crash 183 * or return "null". 184 * 185 * TODO very incomplete, there are many permutations to be explored 186 */ 187 public void testUpdateBodyFieldsNullText() throws MessagingException { 188 EmailContent.Body localBody = new EmailContent.Body(); 189 EmailContent.Message localMessage = new EmailContent.Message(); 190 ArrayList<Part> viewables = new ArrayList<Part>(); 191 Part emptyTextPart = new MimeBodyPart(null, "text/plain"); 192 viewables.add(emptyTextPart); 193 194 // a "null" body part of type text/plain should result in a null mTextContent 195 boolean result = ConversionUtilities.updateBodyFields(localBody, localMessage, viewables); 196 assertTrue(result); 197 assertNull(localBody.mTextContent); 198 } 199 200 /** 201 * Sunny day test of adding attachments from an IMAP/POP message. 202 */ 203 public void testAddAttachments() throws MessagingException, IOException { 204 // Prepare a local message to add the attachments to 205 final long accountId = 1; 206 final long mailboxId = 1; 207 208 // test 1: legacy message using content-type:name style for name 209 final EmailContent.Message localMessage = ProviderTestUtils.setupMessage( 210 "local-message", accountId, mailboxId, false, true, mProviderContext); 211 final Message legacyMessage = prepareLegacyMessageWithAttachments(2, false); 212 convertAndCheckcheckAddedAttachments(localMessage, legacyMessage); 213 214 // test 2: legacy message using content-disposition:filename style for name 215 final EmailContent.Message localMessage2 = ProviderTestUtils.setupMessage( 216 "local-message", accountId, mailboxId, false, true, mProviderContext); 217 final Message legacyMessage2 = prepareLegacyMessageWithAttachments(2, true); 218 convertAndCheckcheckAddedAttachments(localMessage2, legacyMessage2); 219 } 220 221 /** 222 * Helper for testAddAttachments 223 */ 224 private void convertAndCheckcheckAddedAttachments(final EmailContent.Message localMessage, 225 final Message legacyMessage) throws MessagingException, IOException { 226 // Now, convert from legacy to provider and see what happens 227 ArrayList<Part> viewables = new ArrayList<Part>(); 228 ArrayList<Part> attachments = new ArrayList<Part>(); 229 MimeUtility.collectParts(legacyMessage, viewables, attachments); 230 LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments); 231 232 // Read back all attachments for message and check field values 233 Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId); 234 Cursor c = mProviderContext.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION, 235 null, null, null); 236 try { 237 assertEquals(2, c.getCount()); 238 while (c.moveToNext()) { 239 Attachment attachment = Attachment.getContent(c, Attachment.class); 240 if ("100".equals(attachment.mLocation)) { 241 checkAttachment("attachment1Part", attachments.get(0), attachment, 242 localMessage.mAccountKey); 243 } else if ("101".equals(attachment.mLocation)) { 244 checkAttachment("attachment2Part", attachments.get(1), attachment, 245 localMessage.mAccountKey); 246 } else { 247 fail("Unexpected attachment with location " + attachment.mLocation); 248 } 249 } 250 } finally { 251 c.close(); 252 } 253 } 254 255 /** 256 * Test that only "attachment" or "inline" attachments are captured and added. 257 * @throws MessagingException 258 * @throws IOException 259 */ 260 public void testAttachmentDispositions() throws MessagingException, IOException { 261 // Prepare a local message to add the attachments to 262 final long accountId = 1; 263 final long mailboxId = 1; 264 265 // Prepare the three attachments we want to test 266 BodyPart[] sourceAttachments = new BodyPart[3]; 267 BodyPart attachmentPart; 268 269 // 1. Standard attachment 270 attachmentPart = MessageTestUtils.bodyPart("image/jpg", null); 271 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "image/jpg"); 272 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); 273 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, 274 "attachment;\n filename=\"file-1\";\n size=100"); 275 attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "100"); 276 sourceAttachments[0] = attachmentPart; 277 278 // 2. Inline attachment 279 attachmentPart = MessageTestUtils.bodyPart("image/gif", null); 280 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "image/gif"); 281 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); 282 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, 283 "inline;\n filename=\"file-2\";\n size=200"); 284 attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "101"); 285 sourceAttachments[1] = attachmentPart; 286 287 // 3. Neither (use VCALENDAR) 288 attachmentPart = MessageTestUtils.bodyPart("text/calendar", null); 289 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, 290 "text/calendar; charset=UTF-8; method=REQUEST"); 291 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "7bit"); 292 attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "102"); 293 sourceAttachments[2] = attachmentPart; 294 295 // Prepare local message (destination) and legacy message w/attachments (source) 296 final EmailContent.Message localMessage = ProviderTestUtils.setupMessage( 297 "local-message", accountId, mailboxId, false, true, mProviderContext); 298 final Message legacyMessage = prepareLegacyMessageWithAttachments(sourceAttachments); 299 convertAndCheckcheckAddedAttachments(localMessage, legacyMessage); 300 301 // Run the conversion and check for the converted attachments - this test asserts 302 // that there are two attachments numbered 100 & 101 (so will fail if it finds 102) 303 convertAndCheckcheckAddedAttachments(localMessage, legacyMessage); 304 } 305 306 /** 307 * Test that attachments aren't re-added in the DB. This supports the "partial download" 308 * nature of POP messages. 309 */ 310 public void testAddDuplicateAttachments() throws MessagingException, IOException { 311 // Prepare a local message to add the attachments to 312 final long accountId = 1; 313 final long mailboxId = 1; 314 final EmailContent.Message localMessage = ProviderTestUtils.setupMessage( 315 "local-message", accountId, mailboxId, false, true, mProviderContext); 316 317 // Prepare a legacy message with attachments 318 Message legacyMessage = prepareLegacyMessageWithAttachments(2, false); 319 320 // Now, convert from legacy to provider and see what happens 321 ArrayList<Part> viewables = new ArrayList<Part>(); 322 ArrayList<Part> attachments = new ArrayList<Part>(); 323 MimeUtility.collectParts(legacyMessage, viewables, attachments); 324 LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments); 325 326 // Confirm two attachment objects created 327 Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, localMessage.mId); 328 assertEquals(2, EmailContent.count(mProviderContext, uri, null, null)); 329 330 // Now add the attachments again and confirm there are still only two 331 LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments); 332 assertEquals(2, EmailContent.count(mProviderContext, uri, null, null)); 333 334 // Now add a 3rd & 4th attachment and make sure the total is 4, not 2 or 6 335 legacyMessage = prepareLegacyMessageWithAttachments(4, false); 336 viewables = new ArrayList<Part>(); 337 attachments = new ArrayList<Part>(); 338 MimeUtility.collectParts(legacyMessage, viewables, attachments); 339 LegacyConversions.updateAttachments(mProviderContext, localMessage, attachments); 340 assertEquals(4, EmailContent.count(mProviderContext, uri, null, null)); 341 } 342 343 /** 344 * Prepare a legacy message with 1+ attachments 345 * @param numAttachments how many attachments to add 346 * @param filenameInDisposition False: attachment names are sent as content-type:name. True: 347 * attachment names are sent as content-disposition:filename. 348 */ 349 private Message prepareLegacyMessageWithAttachments(int numAttachments, 350 boolean filenameInDisposition) throws MessagingException { 351 BodyPart[] attachmentParts = new BodyPart[numAttachments]; 352 for (int i = 0; i < numAttachments; ++i) { 353 // construct parameter parts for content-type:name or content-disposition:filename. 354 String name = ""; 355 String filename = ""; 356 String quotedName = "\"test-attachment-" + i + "\""; 357 if (filenameInDisposition) { 358 filename = ";\n filename=" + quotedName; 359 } else { 360 name = ";\n name=" + quotedName; 361 } 362 363 // generate an attachment that came from a server 364 BodyPart attachmentPart = MessageTestUtils.bodyPart("image/jpg", null); 365 366 // name=attachmentN size=N00 location=10N 367 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "image/jpg" + name); 368 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_TRANSFER_ENCODING, "base64"); 369 attachmentPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, 370 "attachment" + filename + ";\n size=" + (i+1) + "00"); 371 attachmentPart.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, "10" + i); 372 373 attachmentParts[i] = attachmentPart; 374 } 375 376 return prepareLegacyMessageWithAttachments(attachmentParts); 377 } 378 379 /** 380 * Prepare a legacy message with 1+ attachments 381 * @param attachments array containing one or more attachments 382 */ 383 private Message prepareLegacyMessageWithAttachments(BodyPart[] attachments) 384 throws MessagingException { 385 // Build the multipart that holds the attachments 386 MultipartBuilder mpBuilder = new MultipartBuilder("multipart/mixed"); 387 for (int i = 0; i < attachments.length; ++i) { 388 mpBuilder.addBodyPart(attachments[i]); 389 } 390 391 // Now build a message with them 392 final Message legacyMessage = new MessageBuilder() 393 .setBody(new MultipartBuilder("multipart/mixed") 394 .addBodyPart(MessageTestUtils.bodyPart("text/html", null)) 395 .addBodyPart(mpBuilder.buildBodyPart()) 396 .build()) 397 .build(); 398 399 return legacyMessage; 400 } 401 402 /** 403 * Test the stringInequal helper 404 */ 405 public void testStringInequal() { 406 // Pairs that are "equal" 407 assertFalse(LegacyConversions.stringNotEqual(null, null)); 408 assertFalse(LegacyConversions.stringNotEqual(null, "")); 409 assertFalse(LegacyConversions.stringNotEqual("", null)); 410 assertFalse(LegacyConversions.stringNotEqual("", "")); 411 assertFalse(LegacyConversions.stringNotEqual("string-equal", "string-equal")); 412 // Pairs that are "inequal" 413 assertTrue(LegacyConversions.stringNotEqual(null, "string-inequal")); 414 assertTrue(LegacyConversions.stringNotEqual("", "string-inequal")); 415 assertTrue(LegacyConversions.stringNotEqual("string-inequal", null)); 416 assertTrue(LegacyConversions.stringNotEqual("string-inequal", "")); 417 assertTrue(LegacyConversions.stringNotEqual("string-inequal-a", "string-inequal-b")); 418 } 419 420 /** 421 * Compare attachment that was converted from Part (expected) to Provider Attachment (actual) 422 * 423 * TODO content URI should only be set if we also saved a file 424 * TODO other data encodings 425 */ 426 private void checkAttachment(String tag, Part expected, EmailContent.Attachment actual, 427 long accountKey) throws MessagingException { 428 String contentType = MimeUtility.unfoldAndDecode(expected.getContentType()); 429 String contentTypeName = MimeUtility.getHeaderParameter(contentType, "name"); 430 assertEquals(tag, expected.getMimeType(), actual.mMimeType); 431 String disposition = expected.getDisposition(); 432 String sizeString = MimeUtility.getHeaderParameter(disposition, "size"); 433 String dispositionFilename = MimeUtility.getHeaderParameter(disposition, "filename"); 434 long expectedSize = (sizeString != null) ? Long.parseLong(sizeString) : 0; 435 assertEquals(tag, expectedSize, actual.mSize); 436 assertEquals(tag, expected.getContentId(), actual.mContentId); 437 438 // filename is either content-type:name or content-disposition:filename 439 String expectedName = (contentTypeName != null) ? contentTypeName : dispositionFilename; 440 assertEquals(tag, expectedName, actual.mFileName); 441 442 // content URI should be null 443 assertNull(tag, actual.mContentUri); 444 445 assertTrue(tag, 0 != actual.mMessageKey); 446 447 // location is either both null or both matching 448 String expectedPartId = null; 449 String[] storeData = expected.getHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA); 450 if (storeData != null && storeData.length > 0) { 451 expectedPartId = storeData[0]; 452 } 453 assertEquals(tag, expectedPartId, actual.mLocation); 454 assertEquals(tag, "B", actual.mEncoding); 455 assertEquals(tag, accountKey, actual.mAccountKey); 456 } 457 458 /** 459 * TODO: Sunny day test of adding attachments from a POP message. 460 */ 461 462 /** 463 * Sunny day tests of converting an original message to a legacy message 464 */ 465 public void testMakeLegacyMessage() throws MessagingException { 466 // Set up and store a message in the provider 467 long account1Id = 1; 468 long mailbox1Id = 1; 469 470 // Test message 1: No body 471 EmailContent.Message localMessage1 = ProviderTestUtils.setupMessage("make-legacy", 472 account1Id, mailbox1Id, false, true, mProviderContext); 473 Message getMessage1 = LegacyConversions.makeMessage(mProviderContext, localMessage1); 474 checkLegacyMessage("no body", localMessage1, getMessage1); 475 476 // Test message 2: Simple body 477 EmailContent.Message localMessage2 = ProviderTestUtils.setupMessage("make-legacy", 478 account1Id, mailbox1Id, true, false, mProviderContext); 479 localMessage2.mTextReply = null; 480 localMessage2.mHtmlReply = null; 481 localMessage2.mIntroText = null; 482 localMessage2.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK; 483 localMessage2.save(mProviderContext); 484 Message getMessage2 = LegacyConversions.makeMessage(mProviderContext, localMessage2); 485 checkLegacyMessage("simple body", localMessage2, getMessage2); 486 487 // Test message 3: Body + replied-to text 488 EmailContent.Message localMessage3 = ProviderTestUtils.setupMessage("make-legacy", 489 account1Id, mailbox1Id, true, false, mProviderContext); 490 localMessage3.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK; 491 localMessage3.mFlags |= EmailContent.Message.FLAG_TYPE_REPLY; 492 localMessage3.save(mProviderContext); 493 Message getMessage3 = LegacyConversions.makeMessage(mProviderContext, localMessage3); 494 checkLegacyMessage("reply-to", localMessage3, getMessage3); 495 496 // Test message 4: Body + forwarded text 497 EmailContent.Message localMessage4 = ProviderTestUtils.setupMessage("make-legacy", 498 account1Id, mailbox1Id, true, false, mProviderContext); 499 localMessage4.mFlags &= ~EmailContent.Message.FLAG_TYPE_MASK; 500 localMessage4.mFlags |= EmailContent.Message.FLAG_TYPE_FORWARD; 501 localMessage4.save(mProviderContext); 502 Message getMessage4 = LegacyConversions.makeMessage(mProviderContext, localMessage4); 503 checkLegacyMessage("forwarding", localMessage4, getMessage4); 504 } 505 506 /** 507 * Check equality of a pair of converted messages 508 */ 509 private void checkProviderMessage(String tag, Message expect, EmailContent.Message actual) 510 throws MessagingException { 511 assertEquals(tag, expect.getUid(), actual.mServerId); 512 assertEquals(tag, expect.getSubject(), actual.mSubject); 513 assertEquals(tag, Address.pack(expect.getFrom()), actual.mFrom); 514 assertEquals(tag, expect.getSentDate().getTime(), actual.mTimeStamp); 515 assertEquals(tag, Address.pack(expect.getRecipients(RecipientType.TO)), actual.mTo); 516 assertEquals(tag, Address.pack(expect.getRecipients(RecipientType.CC)), actual.mCc); 517 assertEquals(tag, ((MimeMessage)expect).getMessageId(), actual.mMessageId); 518 assertEquals(tag, expect.isSet(Flag.SEEN), actual.mFlagRead); 519 assertEquals(tag, expect.isSet(Flag.FLAGGED), actual.mFlagFavorite); 520 } 521 522 /** 523 * Check equality of a pair of converted messages 524 */ 525 private void checkLegacyMessage(String tag, EmailContent.Message expect, Message actual) 526 throws MessagingException { 527 assertEquals(tag, expect.mServerId, actual.getUid()); 528 assertEquals(tag, expect.mServerTimeStamp, actual.getInternalDate().getTime()); 529 assertEquals(tag, expect.mSubject, actual.getSubject()); 530 assertEquals(tag, expect.mFrom, Address.pack(actual.getFrom())); 531 assertEquals(tag, expect.mTimeStamp, actual.getSentDate().getTime()); 532 assertEquals(tag, expect.mTo, Address.pack(actual.getRecipients(RecipientType.TO))); 533 assertEquals(tag, expect.mCc, Address.pack(actual.getRecipients(RecipientType.CC))); 534 assertEquals(tag, expect.mBcc, Address.pack(actual.getRecipients(RecipientType.BCC))); 535 assertEquals(tag, expect.mReplyTo, Address.pack(actual.getReplyTo())); 536 assertEquals(tag, expect.mMessageId, ((MimeMessage)actual).getMessageId()); 537 // check flags 538 assertEquals(tag, expect.mFlagRead, actual.isSet(Flag.SEEN)); 539 assertEquals(tag, expect.mFlagFavorite, actual.isSet(Flag.FLAGGED)); 540 541 // Check the body of the message 542 ArrayList<Part> viewables = new ArrayList<Part>(); 543 ArrayList<Part> attachments = new ArrayList<Part>(); 544 MimeUtility.collectParts(actual, viewables, attachments); 545 String get1Text = null; 546 String get1Html = null; 547 String get1TextReply = null; 548 String get1HtmlReply = null; 549 String get1TextIntro = null; 550 for (Part viewable : viewables) { 551 String text = MimeUtility.getTextFromPart(viewable); 552 boolean isHtml = viewable.getMimeType().equalsIgnoreCase("text/html"); 553 String[] headers = viewable.getHeader(MimeHeader.HEADER_ANDROID_BODY_QUOTED_PART); 554 if (headers != null) { 555 String header = headers[0]; 556 boolean isReply = LegacyConversions.BODY_QUOTED_PART_REPLY.equalsIgnoreCase(header); 557 boolean isFwd = LegacyConversions.BODY_QUOTED_PART_FORWARD.equalsIgnoreCase(header); 558 boolean isIntro = LegacyConversions.BODY_QUOTED_PART_INTRO.equalsIgnoreCase(header); 559 if (isReply || isFwd) { 560 if (isHtml) { 561 get1HtmlReply = text; 562 } else { 563 get1TextReply = text; 564 } 565 } else if (isIntro) { 566 get1TextIntro = text; 567 } 568 // Check flags 569 int replyTypeFlags = expect.mFlags & EmailContent.Message.FLAG_TYPE_MASK; 570 if (isReply) { 571 assertEquals(tag, EmailContent.Message.FLAG_TYPE_REPLY, replyTypeFlags); 572 } 573 if (isFwd) { 574 assertEquals(tag, EmailContent.Message.FLAG_TYPE_FORWARD, replyTypeFlags); 575 } 576 } else { 577 if (isHtml) { 578 get1Html = text; 579 } else { 580 get1Text = text; 581 } 582 } 583 } 584 assertEquals(tag, expect.mText, get1Text); 585 assertEquals(tag, expect.mHtml, get1Html); 586 assertEquals(tag, expect.mTextReply, get1TextReply); 587 assertEquals(tag, expect.mHtmlReply, get1HtmlReply); 588 assertEquals(tag, expect.mIntroText, get1TextIntro); 589 590 // TODO Check the attachments 591 592// cv.put("attachment_count", attachments.size()); 593 } 594 595 /** 596 * Test conversion of a legacy account to a provider account 597 */ 598 public void testMakeProviderAccount() throws MessagingException { 599 600 setupLegacyAccount("testMakeProviderAccount", true); 601 EmailContent.Account toAccount = 602 LegacyConversions.makeAccount(mProviderContext, mLegacyAccount); 603 checkProviderAccount("testMakeProviderAccount", mLegacyAccount, toAccount); 604 } 605 606 /** 607 * Test conversion of a provider account to a legacy account 608 */ 609 public void testMakeLegacyAccount() throws MessagingException { 610 EmailContent.Account fromAccount = ProviderTestUtils.setupAccount("convert-to-legacy", 611 false, mProviderContext); 612 fromAccount.mHostAuthRecv = 613 ProviderTestUtils.setupHostAuth("legacy-recv", 0, false, mProviderContext); 614 fromAccount.mHostAuthSend = 615 ProviderTestUtils.setupHostAuth("legacy-send", 0, false, mProviderContext); 616 fromAccount.save(mProviderContext); 617 618 Account toAccount = LegacyConversions.makeLegacyAccount(mProviderContext, fromAccount); 619 checkLegacyAccount("testMakeLegacyAccount", fromAccount, toAccount); 620 } 621 622 /** 623 * Setup a legacy account in mLegacyAccount with many fields prefilled. 624 */ 625 private void setupLegacyAccount(String name, boolean saveIt) { 626 // prefs & legacy account are saved for cleanup (it's stored in the real prefs file) 627 mPreferences = Preferences.getPreferences(mProviderContext); 628 mLegacyAccount = new Account(mProviderContext); 629 630 // fill in useful fields 631 mLegacyAccount.mUuid = "test-uid-" + name; 632 mLegacyAccount.mStoreUri = "store://test/" + name; 633 mLegacyAccount.mLocalStoreUri = "local://localhost/" + name; 634 mLegacyAccount.mSenderUri = "sender://test/" + name; 635 mLegacyAccount.mDescription = "description " + name; 636 mLegacyAccount.mName = "name " + name; 637 mLegacyAccount.mEmail = "email " + name; 638 mLegacyAccount.mAutomaticCheckIntervalMinutes = 100; 639 mLegacyAccount.mLastAutomaticCheckTime = 200; 640 mLegacyAccount.mNotifyNewMail = true; 641 mLegacyAccount.mDraftsFolderName = "drafts " + name; 642 mLegacyAccount.mSentFolderName = "sent " + name; 643 mLegacyAccount.mTrashFolderName = "trash " + name; 644 mLegacyAccount.mOutboxFolderName = "outbox " + name; 645 mLegacyAccount.mAccountNumber = 300; 646 mLegacyAccount.mVibrate = true; 647 mLegacyAccount.mVibrateWhenSilent = false; 648 mLegacyAccount.mRingtoneUri = "ringtone://test/" + name; 649 mLegacyAccount.mSyncWindow = 400; 650 mLegacyAccount.mBackupFlags = 0; 651 mLegacyAccount.mDeletePolicy = Account.DELETE_POLICY_NEVER; 652 mLegacyAccount.mSecurityFlags = 500; 653 mLegacyAccount.mSignature = "signature " + name; 654 655 if (saveIt) { 656 mLegacyAccount.save(mPreferences); 657 } 658 } 659 660 /** 661 * Compare a provider account to the legacy account it was created from 662 */ 663 private void checkProviderAccount(String tag, Account expect, EmailContent.Account actual) 664 throws MessagingException { 665 assertEquals(tag + " description", expect.getDescription(), actual.mDisplayName); 666 assertEquals(tag + " email", expect.getEmail(), actual.mEmailAddress); 667 assertEquals(tag + " sync key", null, actual.mSyncKey); 668 assertEquals(tag + " lookback", expect.getSyncWindow(), actual.mSyncLookback); 669 assertEquals(tag + " sync intvl", expect.getAutomaticCheckIntervalMinutes(), 670 actual.mSyncInterval); 671 // These asserts are checking mHostAuthKeyRecv & mHostAuthKeySend 672 assertEquals(tag + " store", expect.getStoreUri(), actual.getStoreUri(mProviderContext)); 673 assertEquals(tag + " sender", expect.getSenderUri(), actual.getSenderUri(mProviderContext)); 674 // Synthesize & check flags 675 int expectFlags = 0; 676 if (expect.mNotifyNewMail) expectFlags |= EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL; 677 if (expect.mVibrate) expectFlags |= EmailContent.Account.FLAGS_VIBRATE_ALWAYS; 678 if (expect.mVibrateWhenSilent) 679 expectFlags |= EmailContent.Account.FLAGS_VIBRATE_WHEN_SILENT; 680 expectFlags |= 681 (expect.mDeletePolicy << EmailContent.Account.FLAGS_DELETE_POLICY_SHIFT) 682 & EmailContent.Account.FLAGS_DELETE_POLICY_MASK; 683 assertEquals(tag + " flags", expectFlags, actual.mFlags); 684 assertEquals(tag + " default", false, actual.mIsDefault); 685 assertEquals(tag + " uuid", expect.getUuid(), actual.mCompatibilityUuid); 686 assertEquals(tag + " name", expect.getName(), actual.mSenderName); 687 assertEquals(tag + " ringtone", expect.getRingtone(), actual.mRingtoneUri); 688 assertEquals(tag + " proto vers", expect.mProtocolVersion, actual.mProtocolVersion); 689 assertEquals(tag + " new count", 0, actual.mNewMessageCount); 690 assertEquals(tag + " security", expect.mSecurityFlags, actual.mSecurityFlags); 691 assertEquals(tag + " sec sync key", null, actual.mSecuritySyncKey); 692 assertEquals(tag + " signature", expect.mSignature, actual.mSignature); 693 } 694 695 /** 696 * Compare a legacy account to the provider account it was created from 697 */ 698 private void checkLegacyAccount(String tag, EmailContent.Account expect, Account actual) 699 throws MessagingException { 700 int expectFlags = expect.getFlags(); 701 702 assertEquals(tag + " uuid", expect.mCompatibilityUuid, actual.mUuid); 703 assertEquals(tag + " store", expect.getStoreUri(mProviderContext), actual.mStoreUri); 704 assertTrue(actual.mLocalStoreUri.startsWith("local://localhost")); 705 assertEquals(tag + " sender", expect.getSenderUri(mProviderContext), actual.mSenderUri); 706 assertEquals(tag + " description", expect.getDisplayName(), actual.mDescription); 707 assertEquals(tag + " name", expect.getSenderName(), actual.mName); 708 assertEquals(tag + " email", expect.getEmailAddress(), actual.mEmail); 709 assertEquals(tag + " checkintvl", expect.getSyncInterval(), 710 actual.mAutomaticCheckIntervalMinutes); 711 assertEquals(tag + " checktime", 0, actual.mLastAutomaticCheckTime); 712 assertEquals(tag + " notify", 713 (expectFlags & EmailContent.Account.FLAGS_NOTIFY_NEW_MAIL) != 0, 714 actual.mNotifyNewMail); 715 assertEquals(tag + " drafts", null, actual.mDraftsFolderName); 716 assertEquals(tag + " sent", null, actual.mSentFolderName); 717 assertEquals(tag + " trash", null, actual.mTrashFolderName); 718 assertEquals(tag + " outbox", null, actual.mOutboxFolderName); 719 assertEquals(tag + " acct #", -1, actual.mAccountNumber); 720 assertEquals(tag + " vibrate", 721 (expectFlags & EmailContent.Account.FLAGS_VIBRATE_ALWAYS) != 0, 722 actual.mVibrate); 723 assertEquals(tag + " vibrateSilent", 724 (expectFlags & EmailContent.Account.FLAGS_VIBRATE_WHEN_SILENT) != 0, 725 actual.mVibrateWhenSilent); 726 assertEquals(tag + " ", expect.getRingtone(), actual.mRingtoneUri); 727 assertEquals(tag + " sync window", expect.getSyncLookback(), actual.mSyncWindow); 728 assertEquals(tag + " backup flags", 0, actual.mBackupFlags); 729 assertEquals(tag + " proto vers", expect.mProtocolVersion, actual.mProtocolVersion); 730 assertEquals(tag + " delete policy", expect.getDeletePolicy(), actual.getDeletePolicy()); 731 assertEquals(tag + " security", expect.mSecurityFlags, actual.mSecurityFlags); 732 assertEquals(tag + " signature", expect.mSignature, actual.mSignature); 733 } 734} 735