ProviderTests.java revision 9627d014e16235eadf981b9165807dc72a14a383
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.provider; 18 19import com.android.email.provider.EmailContent.Account; 20import com.android.email.provider.EmailContent.AccountColumns; 21import com.android.email.provider.EmailContent.Attachment; 22import com.android.email.provider.EmailContent.Body; 23import com.android.email.provider.EmailContent.BodyColumns; 24import com.android.email.provider.EmailContent.Mailbox; 25import com.android.email.provider.EmailContent.MailboxColumns; 26import com.android.email.provider.EmailContent.Message; 27import com.android.email.provider.EmailContent.MessageColumns; 28 29import android.content.ContentResolver; 30import android.content.ContentUris; 31import android.content.ContentValues; 32import android.content.Context; 33import android.database.Cursor; 34import android.net.Uri; 35import android.os.Environment; 36import android.test.ProviderTestCase2; 37 38import java.io.File; 39import java.io.IOException; 40import java.util.ArrayList; 41 42/** 43 * Tests of the Email provider. 44 * 45 * You can run this entire test case with: 46 * runtest -c com.android.email.provider.ProviderTests email 47 */ 48public class ProviderTests extends ProviderTestCase2<EmailProvider> { 49 50 EmailProvider mProvider; 51 Context mMockContext; 52 53 public ProviderTests() { 54 super(EmailProvider.class, EmailProvider.EMAIL_AUTHORITY); 55 } 56 57 @Override 58 public void setUp() throws Exception { 59 super.setUp(); 60 mMockContext = getMockContext(); 61 } 62 63 @Override 64 public void tearDown() throws Exception { 65 super.tearDown(); 66 } 67 68 /** 69 * Test simple account save/retrieve 70 */ 71 public void testAccountSave() { 72 Account account1 = ProviderTestUtils.setupAccount("account-save", true, mMockContext); 73 long account1Id = account1.mId; 74 75 Account account2 = EmailContent.Account.restoreAccountWithId(mMockContext, account1Id); 76 77 ProviderTestUtils.assertAccountEqual("testAccountSave", account1, account2); 78 } 79 80 private final static String[] MAILBOX_UNREAD_COUNT_PROJECTION = new String [] { 81 MailboxColumns.UNREAD_COUNT 82 }; 83 private final static int MAILBOX_UNREAD_COUNT_COLMUN = 0; 84 85 /** 86 * Get the value of the unread count in the mailbox of the account. 87 * This can be different from the actual number of unread messages in that mailbox. 88 * @param accountId 89 * @param mailboxId 90 * @return 91 */ 92 private int getUnreadCount(long mailboxId) { 93 String text = null; 94 Cursor c = null; 95 try { 96 c = mMockContext.getContentResolver().query( 97 Mailbox.CONTENT_URI, 98 MAILBOX_UNREAD_COUNT_PROJECTION, 99 EmailContent.RECORD_ID + "=?", 100 new String[] { String.valueOf(mailboxId) }, 101 null); 102 c.moveToFirst(); 103 text = c.getString(MAILBOX_UNREAD_COUNT_COLMUN); 104 } finally { 105 c.close(); 106 } 107 return Integer.valueOf(text); 108 } 109 110 /** 111 * TODO: HostAuth tests 112 */ 113 114 /** 115 * Test simple mailbox save/retrieve 116 */ 117 public void testMailboxSave() { 118 Account account1 = ProviderTestUtils.setupAccount("mailbox-save", true, mMockContext); 119 long account1Id = account1.mId; 120 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, 121 mMockContext); 122 long box1Id = box1.mId; 123 124 Mailbox box2 = EmailContent.Mailbox.restoreMailboxWithId(mMockContext, box1Id); 125 126 ProviderTestUtils.assertMailboxEqual("testMailboxSave", box1, box2); 127 } 128 129 private static String[] expectedAttachmentNames = 130 new String[] {"attachment1.doc", "attachment2.xls", "attachment3"}; 131 // The lengths need to be kept in ascending order 132 private static long[] expectedAttachmentSizes = new long[] {31415L, 97701L, 151213L}; 133 134 /* 135 * Returns null if the message has no body. 136 */ 137 private Body loadBodyForMessageId(long messageId) { 138 Cursor c = null; 139 try { 140 c = mMockContext.getContentResolver().query( 141 EmailContent.Body.CONTENT_URI, 142 EmailContent.Body.CONTENT_PROJECTION, 143 EmailContent.Body.MESSAGE_KEY + "=?", 144 new String[] {String.valueOf(messageId)}, 145 null); 146 int numBodies = c.getCount(); 147 assertTrue("at most one body", numBodies < 2); 148 return c.moveToFirst() ? EmailContent.getContent(c, Body.class) : null; 149 } finally { 150 c.close(); 151 } 152 } 153 154 /** 155 * Test simple message save/retrieve 156 * 157 * TODO: serverId vs. serverIntId 158 */ 159 public void testMessageSave() { 160 Account account1 = ProviderTestUtils.setupAccount("message-save", true, mMockContext); 161 long account1Id = account1.mId; 162 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 163 long box1Id = box1.mId; 164 165 // Test a simple message (saved with no body) 166 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 167 true, mMockContext); 168 long message1Id = message1.mId; 169 Message message1get = EmailContent.Message.restoreMessageWithId(mMockContext, message1Id); 170 ProviderTestUtils.assertMessageEqual("testMessageSave", message1, message1get); 171 172 // Test a message saved with a body 173 // Note that it will read back w/o the text & html so we must extract those 174 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 175 true, mMockContext); 176 long message2Id = message2.mId; 177 String text2 = message2.mText; 178 String html2 = message2.mHtml; 179 message2.mText = null; 180 message2.mHtml = null; 181 Message message2get = EmailContent.Message.restoreMessageWithId(mMockContext, message2Id); 182 ProviderTestUtils.assertMessageEqual("testMessageSave", message2, message2get); 183 184 // Now see if there's a body saved with the right stuff 185 Body body2 = loadBodyForMessageId(message2Id); 186 assertEquals("body text", text2, body2.mTextContent); 187 assertEquals("body html", html2, body2.mHtmlContent); 188 189 // Message with attachments and body 190 Message message3 = ProviderTestUtils.setupMessage("message3", account1Id, box1Id, true, 191 false, mMockContext); 192 ArrayList<Attachment> atts = new ArrayList<Attachment>(); 193 for (int i = 0; i < 3; i++) { 194 atts.add(ProviderTestUtils.setupAttachment( 195 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 196 false, mMockContext)); 197 } 198 message3.mAttachments = atts; 199 message3.save(mMockContext); 200 long message3Id = message3.mId; 201 202 // Now check the attachments; there should be three and they should match name and size 203 Cursor c = null; 204 try { 205 // Note that there is NO guarantee of the order of returned records in the general case, 206 // so we specifically ask for ordering by size. The expectedAttachmentSizes array must 207 // be kept sorted by size (ascending) for this test to work properly 208 c = mMockContext.getContentResolver().query( 209 Attachment.CONTENT_URI, 210 Attachment.CONTENT_PROJECTION, 211 Attachment.MESSAGE_KEY + "=?", 212 new String[] { 213 String.valueOf(message3Id) 214 }, 215 Attachment.SIZE); 216 int numAtts = c.getCount(); 217 assertEquals(3, numAtts); 218 int i = 0; 219 while (c.moveToNext()) { 220 Attachment actual = EmailContent.getContent(c, Attachment.class); 221 ProviderTestUtils.assertAttachmentEqual("save-message3", atts.get(i), actual); 222 i++; 223 } 224 } finally { 225 c.close(); 226 } 227 228 // Message with attachments but no body 229 Message message4 = ProviderTestUtils.setupMessage("message4", account1Id, box1Id, false, 230 false, mMockContext); 231 atts = new ArrayList<Attachment>(); 232 for (int i = 0; i < 3; i++) { 233 atts.add(ProviderTestUtils.setupAttachment( 234 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 235 false, mMockContext)); 236 } 237 message4.mAttachments = atts; 238 message4.save(mMockContext); 239 long message4Id = message4.mId; 240 241 // Now check the attachments; there should be three and they should match name and size 242 c = null; 243 244 try { 245 // Note that there is NO guarantee of the order of returned records in the general case, 246 // so we specifically ask for ordering by size. The expectedAttachmentSizes array must 247 // be kept sorted by size (ascending) for this test to work properly 248 c = mMockContext.getContentResolver().query( 249 Attachment.CONTENT_URI, 250 Attachment.CONTENT_PROJECTION, 251 Attachment.MESSAGE_KEY + "=?", 252 new String[] { 253 String.valueOf(message4Id) 254 }, 255 Attachment.SIZE); 256 int numAtts = c.getCount(); 257 assertEquals(3, numAtts); 258 int i = 0; 259 while (c.moveToNext()) { 260 Attachment actual = EmailContent.getContent(c, Attachment.class); 261 ProviderTestUtils.assertAttachmentEqual("save-message4", atts.get(i), actual); 262 i++; 263 } 264 } finally { 265 c.close(); 266 } 267 } 268 269 /** 270 * TODO: update account 271 */ 272 273 /** 274 * TODO: update mailbox 275 */ 276 277 /** 278 * TODO: update message 279 */ 280 281 /** 282 * Test delete account 283 * TODO: hostauth 284 */ 285 public void testAccountDelete() { 286 Account account1 = ProviderTestUtils.setupAccount("account-delete-1", true, mMockContext); 287 long account1Id = account1.mId; 288 Account account2 = ProviderTestUtils.setupAccount("account-delete-2", true, mMockContext); 289 long account2Id = account2.mId; 290 291 // make sure there are two accounts 292 int numBoxes = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 293 assertEquals(2, numBoxes); 294 295 // now delete one of them 296 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, account1Id); 297 mMockContext.getContentResolver().delete(uri, null, null); 298 299 // make sure there's only one account now 300 numBoxes = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 301 assertEquals(1, numBoxes); 302 303 // now delete the other one 304 uri = ContentUris.withAppendedId(Account.CONTENT_URI, account2Id); 305 mMockContext.getContentResolver().delete(uri, null, null); 306 307 // make sure there are no accounts now 308 numBoxes = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 309 assertEquals(0, numBoxes); 310 } 311 312 /** 313 * Test for Body.lookupBodyIdWithMessageId() 314 * Verifies that: 315 * - for a message without body, -1 is returned. 316 * - for a mesage with body, the id matches the one from loadBodyForMessageId. 317 */ 318 public void testLookupBodyIdWithMessageId() { 319 final ContentResolver resolver = mMockContext.getContentResolver(); 320 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 321 long account1Id = account1.mId; 322 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 323 long box1Id = box1.mId; 324 325 // 1. create message with no body, check that returned bodyId is -1 326 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 327 true, mMockContext); 328 long message1Id = message1.mId; 329 long bodyId1 = Body.lookupBodyIdWithMessageId(resolver, message1Id); 330 assertEquals(bodyId1, -1); 331 332 // 2. create message with body, check that returned bodyId is correct 333 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 334 true, mMockContext); 335 long message2Id = message2.mId; 336 long bodyId2 = Body.lookupBodyIdWithMessageId(resolver, message2Id); 337 Body body = loadBodyForMessageId(message2Id); 338 assertNotNull(body); 339 assertEquals(body.mId, bodyId2); 340 } 341 342 /** 343 * Test for Body.updateBodyWithMessageId(). 344 * 1. - create message without body, 345 * - update its body (set TEXT_CONTENT) 346 * - check correct updated body is read back 347 * 348 * 2. - create message with body, 349 * - update body (set TEXT_CONTENT) 350 * - check correct updated body is read back 351 */ 352 public void testUpdateBodyWithMessageId() { 353 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 354 long account1Id = account1.mId; 355 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 356 long box1Id = box1.mId; 357 358 final String textContent = "foobar some odd text"; 359 360 ContentValues values = new ContentValues(); 361 values.put(BodyColumns.TEXT_CONTENT, textContent); 362 363 // 1 364 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 365 true, mMockContext); 366 long message1Id = message1.mId; 367 Body body1 = loadBodyForMessageId(message1Id); 368 assertNull(body1); 369 Body.updateBodyWithMessageId(mMockContext, message1Id, values); 370 body1 = loadBodyForMessageId(message1Id); 371 assertNotNull(body1); 372 assertEquals(body1.mTextContent, textContent); 373 374 // 2 375 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 376 true, mMockContext); 377 long message2Id = message2.mId; 378 Body body2 = loadBodyForMessageId(message2Id); 379 assertNotNull(body2); 380 assertTrue(!body2.mTextContent.equals(textContent)); 381 Body.updateBodyWithMessageId(mMockContext, message2Id, values); 382 body2 = loadBodyForMessageId(message1Id); 383 assertNotNull(body2); 384 assertEquals(body2.mTextContent, textContent); 385 } 386 387 /** 388 * Test delete body. 389 * 1. create message without body (message id 1) 390 * 2. create message with body (message id 2. The body has _id 1 and messageKey 2). 391 * 3. delete first message. 392 * 4. verify that body for message 2 has not been deleted. 393 * 5. delete message 2, verify body is deleted. 394 */ 395 public void testDeleteBody() { 396 final ContentResolver resolver = mMockContext.getContentResolver(); 397 398 // Create account and mailboxes 399 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 400 long account1Id = account1.mId; 401 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 402 long box1Id = box1.mId; 403 404 // 1. create message without body 405 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 406 true, mMockContext); 407 long message1Id = message1.mId; 408 409 // 2. create message with body 410 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 411 true, mMockContext); 412 long message2Id = message2.mId; 413 // verify body is there 414 assertNotNull(loadBodyForMessageId(message2Id)); 415 416 // 3. delete first message 417 resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message1Id), null, null); 418 419 // 4. verify body for second message wasn't deleted 420 assertNotNull(loadBodyForMessageId(message2Id)); 421 422 // 5. delete second message, check its body is deleted 423 resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message2Id), null, null); 424 assertNull(loadBodyForMessageId(message2Id)); 425 } 426 427 /** 428 * Test delete orphan bodies. 429 * 1. create message without body (message id 1) 430 * 2. create message with body (message id 2. Body has _id 1 and messageKey 2). 431 * 3. delete first message. 432 * 4. delete some other mailbox -- this triggers delete orphan bodies. 433 * 5. verify that body for message 2 has not been deleted. 434 */ 435 public void testDeleteOrphanBodies() { 436 final ContentResolver resolver = mMockContext.getContentResolver(); 437 438 // Create account and twa mailboxes 439 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 440 long account1Id = account1.mId; 441 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 442 long box1Id = box1.mId; 443 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mMockContext); 444 long box2Id = box2.mId; 445 446 // 1. create message without body 447 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 448 true, mMockContext); 449 long message1Id = message1.mId; 450 451 // 2. create message with body 452 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 453 true, mMockContext); 454 long message2Id = message2.mId; 455 //verify body is there 456 Body body = loadBodyForMessageId(message2Id); 457 assertNotNull(loadBodyForMessageId(message2Id)); 458 459 // 3. delete first message 460 resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message1Id), null, null); 461 462 // 4. delete some mailbox (because it triggers "delete orphan bodies") 463 resolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2Id), null, null); 464 465 // 5. verify body for second message wasn't deleted during "delete orphan bodies" 466 assertNotNull(loadBodyForMessageId(message2Id)); 467 } 468 469 /** 470 * Test delete mailbox 471 */ 472 public void testMailboxDelete() { 473 Account account1 = ProviderTestUtils.setupAccount("mailbox-delete", true, mMockContext); 474 long account1Id = account1.mId; 475 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 476 long box1Id = box1.mId; 477 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mMockContext); 478 long box2Id = box2.mId; 479 480 String selection = EmailContent.MailboxColumns.ACCOUNT_KEY + "=?"; 481 String[] selArgs = new String[] { String.valueOf(account1Id) }; 482 483 // make sure there are two mailboxes 484 int numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs); 485 assertEquals(2, numBoxes); 486 487 // now delete one of them 488 Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box1Id); 489 mMockContext.getContentResolver().delete(uri, null, null); 490 491 // make sure there's only one mailbox now 492 numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs); 493 assertEquals(1, numBoxes); 494 495 // now delete the other one 496 uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2Id); 497 mMockContext.getContentResolver().delete(uri, null, null); 498 499 // make sure there are no mailboxes now 500 numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs); 501 assertEquals(0, numBoxes); 502 } 503 504 /** 505 * Test delete message 506 * TODO: body 507 * TODO: attachments 508 */ 509 public void testMessageDelete() { 510 Account account1 = ProviderTestUtils.setupAccount("message-delete", true, mMockContext); 511 long account1Id = account1.mId; 512 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 513 long box1Id = box1.mId; 514 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 515 true, mMockContext); 516 long message1Id = message1.mId; 517 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, 518 true, mMockContext); 519 long message2Id = message2.mId; 520 521 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " + 522 EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 523 String[] selArgs = new String[] { String.valueOf(account1Id), String.valueOf(box1Id) }; 524 525 // make sure there are two messages 526 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 527 assertEquals(2, numMessages); 528 529 // now delete one of them 530 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1Id); 531 mMockContext.getContentResolver().delete(uri, null, null); 532 533 // make sure there's only one message now 534 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 535 assertEquals(1, numMessages); 536 537 // now delete the other one 538 uri = ContentUris.withAppendedId(Message.CONTENT_URI, message2Id); 539 mMockContext.getContentResolver().delete(uri, null, null); 540 541 // make sure there are no messages now 542 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 543 assertEquals(0, numMessages); 544 } 545 546 /** 547 * Test delete synced message 548 * TODO: body 549 * TODO: attachments 550 */ 551 public void testSyncedMessageDelete() { 552 Account account1 = ProviderTestUtils.setupAccount("synced-message-delete", true, 553 mMockContext); 554 long account1Id = account1.mId; 555 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 556 long box1Id = box1.mId; 557 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 558 true, mMockContext); 559 long message1Id = message1.mId; 560 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, 561 true, mMockContext); 562 long message2Id = message2.mId; 563 564 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " 565 + EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 566 String[] selArgs = new String[] { 567 String.valueOf(account1Id), String.valueOf(box1Id) 568 }; 569 570 // make sure there are two messages 571 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 572 assertEquals(2, numMessages); 573 574 // make sure we start with no synced deletions 575 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 576 selArgs); 577 assertEquals(0, numMessages); 578 579 // now delete one of them SYNCED 580 Uri uri = ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message1Id); 581 mMockContext.getContentResolver().delete(uri, null, null); 582 583 // make sure there's only one message now 584 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 585 assertEquals(1, numMessages); 586 587 // make sure there's one synced deletion now 588 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 589 selArgs); 590 assertEquals(1, numMessages); 591 592 // now delete the other one NOT SYNCED 593 uri = ContentUris.withAppendedId(Message.CONTENT_URI, message2Id); 594 mMockContext.getContentResolver().delete(uri, null, null); 595 596 // make sure there are no messages now 597 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 598 assertEquals(0, numMessages); 599 600 // make sure there's still one deletion now 601 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 602 selArgs); 603 assertEquals(1, numMessages); 604 } 605 606 /** 607 * Test message update 608 * TODO: body 609 * TODO: attachments 610 */ 611 public void testMessageUpdate() { 612 Account account1 = ProviderTestUtils.setupAccount("message-update", true, mMockContext); 613 long account1Id = account1.mId; 614 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 615 long box1Id = box1.mId; 616 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 617 true, mMockContext); 618 long message1Id = message1.mId; 619 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, 620 true, mMockContext); 621 long message2Id = message2.mId; 622 ContentResolver cr = mMockContext.getContentResolver(); 623 624 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " 625 + EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 626 String[] selArgs = new String[] { 627 String.valueOf(account1Id), String.valueOf(box1Id) 628 }; 629 630 // make sure there are two messages 631 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 632 assertEquals(2, numMessages); 633 634 // change the first one 635 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1Id); 636 ContentValues cv = new ContentValues(); 637 cv.put(MessageColumns.FROM_LIST, "from-list"); 638 cr.update(uri, cv, null, null); 639 640 // make sure there's no updated message 641 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 642 selArgs); 643 assertEquals(0, numMessages); 644 645 // get the message back from the provider, make sure the change "stuck" 646 Message restoredMessage = Message.restoreMessageWithId(mMockContext, message1Id); 647 assertEquals("from-list", restoredMessage.mFrom); 648 649 // change the second one 650 uri = ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message2Id); 651 cv = new ContentValues(); 652 cv.put(MessageColumns.FROM_LIST, "from-list"); 653 cr.update(uri, cv, null, null); 654 655 // make sure there's one updated message 656 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 657 selArgs); 658 assertEquals(1, numMessages); 659 660 // get the message back from the provider, make sure the change "stuck", 661 // as before 662 restoredMessage = Message.restoreMessageWithId(mMockContext, message2Id); 663 assertEquals("from-list", restoredMessage.mFrom); 664 665 // get the original message back from the provider 666 Cursor c = cr.query(Message.UPDATED_CONTENT_URI, Message.CONTENT_PROJECTION, null, null, 667 null); 668 try { 669 assertTrue(c.moveToFirst()); 670 Message originalMessage = EmailContent.getContent(c, Message.class); 671 // make sure this has the original value 672 assertEquals("from message2", originalMessage.mFrom); 673 // Should only be one 674 assertFalse(c.moveToNext()); 675 } finally { 676 c.close(); 677 } 678 679 // delete the second message 680 cr.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message2Id), null, null); 681 682 // hey, presto! the change should be gone 683 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 684 selArgs); 685 assertEquals(0, numMessages); 686 687 // and there should now be a deleted record 688 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 689 selArgs); 690 assertEquals(1, numMessages); 691 } 692 693 /** 694 * TODO: cascaded delete account 695 * TODO: hostauth 696 * TODO: body 697 * TODO: attachments 698 * TODO: create other account, mailbox & messages and confirm the right objects were deleted 699 */ 700 public void testCascadeDeleteAccount() { 701 Account account1 = ProviderTestUtils.setupAccount("account-delete-cascade", true, 702 mMockContext); 703 long account1Id = account1.mId; 704 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 705 long box1Id = box1.mId; 706 /* Message message1 = */ ProviderTestUtils.setupMessage("message1", account1Id, box1Id, 707 false, true, mMockContext); 708 /* Message message2 = */ ProviderTestUtils.setupMessage("message2", account1Id, box1Id, 709 false, true, mMockContext); 710 711 // make sure there is one account, one mailbox, and two messages 712 int numAccounts = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 713 assertEquals(1, numAccounts); 714 int numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, null, null); 715 assertEquals(1, numBoxes); 716 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 717 assertEquals(2, numMessages); 718 719 // delete the account 720 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, account1Id); 721 mMockContext.getContentResolver().delete(uri, null, null); 722 723 // make sure there are no accounts, mailboxes, or messages 724 numAccounts = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 725 assertEquals(0, numAccounts); 726 numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, null, null); 727 assertEquals(0, numBoxes); 728 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 729 assertEquals(0, numMessages); 730 } 731 732 /** 733 * Test cascaded delete mailbox 734 * TODO: body 735 * TODO: attachments 736 * TODO: create other mailbox & messages and confirm the right objects were deleted 737 */ 738 public void testCascadeDeleteMailbox() { 739 Account account1 = ProviderTestUtils.setupAccount("mailbox-delete-cascade", true, 740 mMockContext); 741 long account1Id = account1.mId; 742 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 743 long box1Id = box1.mId; 744 /* Message message1 = */ ProviderTestUtils.setupMessage("message1", account1Id, box1Id, 745 false, true, mMockContext); 746 /* Message message2 = */ ProviderTestUtils.setupMessage("message2", account1Id, box1Id, 747 false, true, mMockContext); 748 749 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " + 750 EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 751 String[] selArgs = new String[] { String.valueOf(account1Id), String.valueOf(box1Id) }; 752 753 // make sure there are two messages 754 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 755 assertEquals(2, numMessages); 756 757 // now delete the mailbox 758 Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box1Id); 759 mMockContext.getContentResolver().delete(uri, null, null); 760 761 // there should now be zero messages 762 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 763 assertEquals(0, numMessages); 764 } 765 766 /** 767 * TODO: Test cascaded delete message 768 * TODO: body 769 * TODO: attachments 770 */ 771 772 /** 773 * Test that our unique file name algorithm works as expected. Since this test requires an 774 * SD card, we check the environment first, and return immediately if none is mounted. 775 * @throws IOException 776 */ 777 public void testCreateUniqueFile() throws IOException { 778 // Delete existing files, if they exist 779 if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 780 return; 781 } 782 try { 783 String fileName = "A11achm3n1.doc"; 784 File uniqueFile = Attachment.createUniqueFile(fileName); 785 assertEquals(fileName, uniqueFile.getName()); 786 if (uniqueFile.createNewFile()) { 787 uniqueFile = Attachment.createUniqueFile(fileName); 788 assertEquals("A11achm3n1-2.doc", uniqueFile.getName()); 789 if (uniqueFile.createNewFile()) { 790 uniqueFile = Attachment.createUniqueFile(fileName); 791 assertEquals("A11achm3n1-3.doc", uniqueFile.getName()); 792 } 793 } 794 fileName = "A11achm3n1"; 795 uniqueFile = Attachment.createUniqueFile(fileName); 796 assertEquals(fileName, uniqueFile.getName()); 797 if (uniqueFile.createNewFile()) { 798 uniqueFile = Attachment.createUniqueFile(fileName); 799 assertEquals("A11achm3n1-2", uniqueFile.getName()); 800 } 801 } finally { 802 File directory = Environment.getExternalStorageDirectory(); 803 // These are the files that should be created earlier in the test. Make sure 804 // they are deleted for the next go-around 805 String[] fileNames = new String[] {"A11achm3n1.doc", "A11achm3n1-2.doc", "A11achm3n1"}; 806 int length = fileNames.length; 807 for (int i = 0; i < length; i++) { 808 File file = new File(directory, fileNames[i]); 809 if (file.exists()) { 810 file.delete(); 811 } 812 } 813 } 814 } 815 816 /** 817 * Test retrieving attachments by message ID (using EmailContent.Attachment.MESSAGE_ID_URI) 818 */ 819 public void testGetAttachmentByMessageIdUri() { 820 821 // Note, we don't strictly need accounts, mailboxes or messages to run this test. 822 Attachment a1 = ProviderTestUtils.setupAttachment(1, "a1", 100, true, mMockContext); 823 Attachment a2 = ProviderTestUtils.setupAttachment(1, "a2", 200, true, mMockContext); 824 ProviderTestUtils.setupAttachment(2, "a3", 300, true, mMockContext); 825 ProviderTestUtils.setupAttachment(2, "a4", 400, true, mMockContext); 826 827 // Now ask for the attachments of message id=1 828 // Note: Using the "sort by size" trick to bring them back in expected order 829 Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, 1); 830 Cursor c = mMockContext.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION, 831 null, null, Attachment.SIZE); 832 assertEquals(2, c.getCount()); 833 834 try { 835 c.moveToFirst(); 836 Attachment a1Get = EmailContent.getContent(c, Attachment.class); 837 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-1", a1, a1Get); 838 c.moveToNext(); 839 Attachment a2Get = EmailContent.getContent(c, Attachment.class); 840 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-2", a2, a2Get); 841 } finally { 842 c.close(); 843 } 844 } 845 846 /** 847 * Tests of default account behavior 848 * 849 * 1. Simple set/get 850 * 2. Moving default between 3 accounts 851 * 3. Delete default, make sure another becomes default 852 */ 853 public void testSetGetDefaultAccount() { 854 // There should be no default account if there are no accounts 855 long defaultAccountId = Account.getDefaultAccountId(mMockContext); 856 assertEquals(-1, defaultAccountId); 857 858 Account account1 = ProviderTestUtils.setupAccount("account-default-1", true, mMockContext); 859 long account1Id = account1.mId; 860 Account account2 = ProviderTestUtils.setupAccount("account-default-2", true, mMockContext); 861 long account2Id = account2.mId; 862 Account account3 = ProviderTestUtils.setupAccount("account-default-3", true, mMockContext); 863 long account3Id = account3.mId; 864 865 // With three accounts, but none marked default, confirm that some default account 866 // is returned. Which one is undefined here. 867 defaultAccountId = Account.getDefaultAccountId(mMockContext); 868 assertTrue(defaultAccountId == account1Id 869 || defaultAccountId == account2Id 870 || defaultAccountId == account3Id); 871 872 updateIsDefault(account1, true); 873 defaultAccountId = Account.getDefaultAccountId(mMockContext); 874 assertEquals(account1Id, defaultAccountId); 875 876 updateIsDefault(account2, true); 877 defaultAccountId = Account.getDefaultAccountId(mMockContext); 878 assertEquals(account2Id, defaultAccountId); 879 880 updateIsDefault(account3, true); 881 defaultAccountId = Account.getDefaultAccountId(mMockContext); 882 assertEquals(account3Id, defaultAccountId); 883 884 // Now delete a non-default account and confirm no change 885 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, account1Id); 886 mMockContext.getContentResolver().delete(uri, null, null); 887 888 defaultAccountId = Account.getDefaultAccountId(mMockContext); 889 assertEquals(account3Id, defaultAccountId); 890 891 // Now confirm deleting the default account and it switches to another one 892 uri = ContentUris.withAppendedId(Account.CONTENT_URI, account3Id); 893 mMockContext.getContentResolver().delete(uri, null, null); 894 895 defaultAccountId = Account.getDefaultAccountId(mMockContext); 896 assertEquals(account2Id, defaultAccountId); 897 898 // Now delete the final account and confirm there are no default accounts again 899 uri = ContentUris.withAppendedId(Account.CONTENT_URI, account2Id); 900 mMockContext.getContentResolver().delete(uri, null, null); 901 902 defaultAccountId = Account.getDefaultAccountId(mMockContext); 903 assertEquals(-1, defaultAccountId); 904 } 905 906 private void updateIsDefault(Account account, boolean newState) { 907 account.setDefaultAccount(newState); 908 ContentValues cv = new ContentValues(); 909 cv.put(AccountColumns.IS_DEFAULT, account.mIsDefault); 910 account.update(mMockContext, cv); 911 } 912 913 public static Message setupUnreadMessage(String name, long accountId, long mailboxId, 914 boolean addBody, boolean saveIt, Context context) { 915 Message msg = 916 ProviderTestUtils.setupMessage(name, accountId, mailboxId, addBody, false, context); 917 msg.mFlagRead = false; 918 if (saveIt) { 919 msg.save(context); 920 } 921 return msg; 922 } 923 924 public void testUnreadCountTriggers() { 925 // Start with one account and three mailboxes 926 Account account = ProviderTestUtils.setupAccount("triggers", true, mMockContext); 927 Mailbox boxA = ProviderTestUtils.setupMailbox("boxA", account.mId, true, mMockContext); 928 Mailbox boxB = ProviderTestUtils.setupMailbox("boxB", account.mId, true, mMockContext); 929 Mailbox boxC = ProviderTestUtils.setupMailbox("boxC", account.mId, true, mMockContext); 930 931 // Make sure there are no unreads 932 assertEquals(0, getUnreadCount(boxA.mId)); 933 assertEquals(0, getUnreadCount(boxB.mId)); 934 assertEquals(0, getUnreadCount(boxC.mId)); 935 936 // Create 4 unread messages (only 3 named) in boxA 937 Message message1 = setupUnreadMessage("message1", account.mId, boxA.mId, 938 false, true, mMockContext); 939 Message message2= setupUnreadMessage("message2", account.mId, boxA.mId, 940 false, true, mMockContext); 941 Message message3 = setupUnreadMessage("message3", account.mId, boxA.mId, 942 false, true, mMockContext); 943 setupUnreadMessage("message4", account.mId, boxC.mId, false, true, mMockContext); 944 945 // Make sure the unreads are where we expect them 946 assertEquals(3, getUnreadCount(boxA.mId)); 947 assertEquals(0, getUnreadCount(boxB.mId)); 948 assertEquals(1, getUnreadCount(boxC.mId)); 949 950 // After deleting message 1, the count in box A should be decremented (to 2) 951 ContentResolver cr = mMockContext.getContentResolver(); 952 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1.mId); 953 cr.delete(uri, null, null); 954 assertEquals(2, getUnreadCount(boxA.mId)); 955 assertEquals(0, getUnreadCount(boxB.mId)); 956 assertEquals(1, getUnreadCount(boxC.mId)); 957 958 // Move message 2 to box B, leaving 1 in box A and 1 in box B 959 message2.mMailboxKey = boxB.mId; 960 ContentValues cv = new ContentValues(); 961 cv.put(MessageColumns.MAILBOX_KEY, boxB.mId); 962 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message2.mId), cv, null, null); 963 assertEquals(1, getUnreadCount(boxA.mId)); 964 assertEquals(1, getUnreadCount(boxB.mId)); 965 assertEquals(1, getUnreadCount(boxC.mId)); 966 967 // Mark message 3 (from box A) read, leaving 0 in box A 968 cv.clear(); 969 cv.put(MessageColumns.FLAG_READ, 1); 970 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message3.mId), cv, null, null); 971 assertEquals(0, getUnreadCount(boxA.mId)); 972 assertEquals(1, getUnreadCount(boxB.mId)); 973 assertEquals(1, getUnreadCount(boxC.mId)); 974 975 // Move message 3 to box C; should be no change (it's read) 976 message3.mMailboxKey = boxC.mId; 977 cv.clear(); 978 cv.put(MessageColumns.MAILBOX_KEY, boxC.mId); 979 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message3.mId), cv, null, null); 980 assertEquals(0, getUnreadCount(boxA.mId)); 981 assertEquals(1, getUnreadCount(boxB.mId)); 982 assertEquals(1, getUnreadCount(boxC.mId)); 983 984 // Mark message 3 unread; it's now in box C, so that box's count should go up to 3 985 cv.clear(); 986 cv.put(MessageColumns.FLAG_READ, 0); 987 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message3.mId), cv, null, null); 988 assertEquals(0, getUnreadCount(boxA.mId)); 989 assertEquals(1, getUnreadCount(boxB.mId)); 990 assertEquals(2, getUnreadCount(boxC.mId)); 991 } 992 993 /** 994 * Test for EmailProvider.createIndex(). 995 * Check that it returns exacly the same string as the one used previously for index creation. 996 */ 997 public void testCreateIndex() { 998 String oldStr = "create index message_" + MessageColumns.TIMESTAMP 999 + " on " + Message.TABLE_NAME + " (" + MessageColumns.TIMESTAMP + ");"; 1000 String newStr = EmailProvider.createIndex(Message.TABLE_NAME, MessageColumns.TIMESTAMP); 1001 assertEquals(newStr, oldStr); 1002 } 1003} 1004