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.provider; 18 19 import com.android.email.provider.EmailContent.Account; 20 import com.android.email.provider.EmailContent.AccountColumns; 21 import com.android.email.provider.EmailContent.Attachment; 22 import com.android.email.provider.EmailContent.AttachmentColumns; 23 import com.android.email.provider.EmailContent.Body; 24 import com.android.email.provider.EmailContent.BodyColumns; 25 import com.android.email.provider.EmailContent.HostAuth; 26 import com.android.email.provider.EmailContent.Mailbox; 27 import com.android.email.provider.EmailContent.MailboxColumns; 28 import com.android.email.provider.EmailContent.Message; 29 import com.android.email.provider.EmailContent.MessageColumns; 30 31 import android.content.ContentResolver; 32 import android.content.ContentUris; 33 import android.content.ContentValues; 34 import android.content.Context; 35 import android.database.Cursor; 36 import android.net.Uri; 37 import android.os.Bundle; 38 import android.os.Environment; 39 import android.os.Parcel; 40 import android.test.MoreAsserts; 41 import android.test.ProviderTestCase2; 42 43 import java.io.File; 44 import java.io.IOException; 45 import java.util.ArrayList; 46 47 /** 48 * Tests of the Email provider. 49 * 50 * You can run this entire test case with: 51 * runtest -c com.android.email.provider.ProviderTests email 52 */ 53 public class ProviderTests extends ProviderTestCase2<EmailProvider> { 54 55 EmailProvider mProvider; 56 Context mMockContext; 57 58 public ProviderTests() { 59 super(EmailProvider.class, EmailProvider.EMAIL_AUTHORITY); 60 } 61 62 @Override 63 public void setUp() throws Exception { 64 super.setUp(); 65 mMockContext = getMockContext(); 66 } 67 68 @Override 69 public void tearDown() throws Exception { 70 super.tearDown(); 71 } 72 73 /** 74 * TODO: Database upgrade tests 75 */ 76 77 /** 78 * Test simple account save/retrieve 79 */ 80 public void testAccountSave() { 81 Account account1 = ProviderTestUtils.setupAccount("account-save", true, mMockContext); 82 long account1Id = account1.mId; 83 84 Account account2 = EmailContent.Account.restoreAccountWithId(mMockContext, account1Id); 85 86 ProviderTestUtils.assertAccountEqual("testAccountSave", account1, account2); 87 } 88 89 /** 90 * Test simple account save/retrieve with predefined hostauth records 91 */ 92 public void testAccountSaveHostAuth() { 93 Account account1 = ProviderTestUtils.setupAccount("account-hostauth", false, mMockContext); 94 // add hostauth data, which should be saved the first time 95 account1.mHostAuthRecv = ProviderTestUtils.setupHostAuth("account-hostauth-recv", -1, false, 96 mMockContext); 97 account1.mHostAuthSend = ProviderTestUtils.setupHostAuth("account-hostauth-send", -1, false, 98 mMockContext); 99 account1.save(mMockContext); 100 long account1Id = account1.mId; 101 102 // Confirm account reads back correctly 103 Account account1get = EmailContent.Account.restoreAccountWithId(mMockContext, account1Id); 104 ProviderTestUtils.assertAccountEqual("testAccountSave", account1, account1get); 105 106 // Confirm hostauth fields can be accessed & read back correctly 107 HostAuth hostAuth1get = EmailContent.HostAuth.restoreHostAuthWithId(mMockContext, 108 account1get.mHostAuthKeyRecv); 109 ProviderTestUtils.assertHostAuthEqual("testAccountSaveHostAuth-recv", 110 account1.mHostAuthRecv, hostAuth1get); 111 HostAuth hostAuth2get = EmailContent.HostAuth.restoreHostAuthWithId(mMockContext, 112 account1get.mHostAuthKeySend); 113 ProviderTestUtils.assertHostAuthEqual("testAccountSaveHostAuth-send", 114 account1.mHostAuthSend, hostAuth2get); 115 } 116 117 /** 118 * Simple test of account parceling. The rather tortuous path is to ensure that the 119 * account is really flattened all the way down to a parcel and back. 120 */ 121 public void testAccountParcel() { 122 Account account1 = ProviderTestUtils.setupAccount("parcel", false, mMockContext); 123 Bundle b = new Bundle(); 124 b.putParcelable("account", account1); 125 Parcel p = Parcel.obtain(); 126 b.writeToParcel(p, 0); 127 p.setDataPosition(0); // rewind it for reading 128 Bundle b2 = new Bundle(Account.class.getClassLoader()); 129 b2.readFromParcel(p); 130 Account account2 = (Account) b2.getParcelable("account"); 131 p.recycle(); 132 133 ProviderTestUtils.assertAccountEqual("testAccountParcel", account1, account2); 134 } 135 136 /** 137 * Test for {@link Account#getShortcutSafeUri()} and 138 * {@link Account#getAccountIdForShortcutSafeUri}. 139 */ 140 public void testAccountShortcutSafeUri() { 141 final Account account1 = ProviderTestUtils.setupAccount("account-1", true, mMockContext); 142 final Account account2 = ProviderTestUtils.setupAccount("account-2", true, mMockContext); 143 final long account1Id = account1.mId; 144 final long account2Id = account2.mId; 145 146 final Uri uri1 = account1.getShortcutSafeUri(); 147 final Uri uri2 = account2.getShortcutSafeUri(); 148 149 // Check the path part of the URIs. 150 MoreAsserts.assertEquals(new String[] {"account", account1.mCompatibilityUuid}, 151 uri1.getPathSegments().toArray()); 152 MoreAsserts.assertEquals(new String[] {"account", account2.mCompatibilityUuid}, 153 uri2.getPathSegments().toArray()); 154 155 assertEquals(account1Id, Account.getAccountIdFromShortcutSafeUri(mMockContext, uri1)); 156 assertEquals(account2Id, Account.getAccountIdFromShortcutSafeUri(mMockContext, uri2)); 157 158 // Test for the Eclair(2.0-2.1) style URI. 159 assertEquals(account1Id, Account.getAccountIdFromShortcutSafeUri(mMockContext, 160 getEclairStyleShortcutUri(account1))); 161 assertEquals(account2Id, Account.getAccountIdFromShortcutSafeUri(mMockContext, 162 getEclairStyleShortcutUri(account2))); 163 } 164 165 private static Uri getEclairStyleShortcutUri(Account account) { 166 // We used _id instead of UUID only on Eclair(2.0-2.1). 167 return Account.CONTENT_URI.buildUpon().appendEncodedPath("" + account.mId).build(); 168 } 169 170 public void testAccountIsValidId() { 171 final Account account1 = ProviderTestUtils.setupAccount("account-1", true, mMockContext); 172 final Account account2 = ProviderTestUtils.setupAccount("account-2", true, mMockContext); 173 174 assertTrue(Account.isValidId(mMockContext, account1.mId)); 175 assertTrue(Account.isValidId(mMockContext, account2.mId)); 176 177 assertFalse(Account.isValidId(mMockContext, 1234567)); // Some random ID 178 assertFalse(Account.isValidId(mMockContext, -1)); 179 assertFalse(Account.isValidId(mMockContext, -500)); 180 } 181 182 private final static String[] MAILBOX_UNREAD_COUNT_PROJECTION = new String [] { 183 MailboxColumns.UNREAD_COUNT 184 }; 185 private final static int MAILBOX_UNREAD_COUNT_COLMUN = 0; 186 187 /** 188 * Get the value of the unread count in the mailbox of the account. 189 * This can be different from the actual number of unread messages in that mailbox. 190 * @param accountId 191 * @param mailboxId 192 * @return 193 */ 194 private int getUnreadCount(long mailboxId) { 195 String text = null; 196 Cursor c = null; 197 try { 198 c = mMockContext.getContentResolver().query( 199 Mailbox.CONTENT_URI, 200 MAILBOX_UNREAD_COUNT_PROJECTION, 201 EmailContent.RECORD_ID + "=?", 202 new String[] { String.valueOf(mailboxId) }, 203 null); 204 c.moveToFirst(); 205 text = c.getString(MAILBOX_UNREAD_COUNT_COLMUN); 206 } finally { 207 c.close(); 208 } 209 return Integer.valueOf(text); 210 } 211 212 /** 213 * TODO: HostAuth tests 214 */ 215 216 /** 217 * Test the various combinations of SSL, TLS, and trust-certificates encoded as Uris 218 */ 219 @SuppressWarnings("deprecation") 220 public void testHostAuthSecurityUri() { 221 HostAuth ha = ProviderTestUtils.setupHostAuth("uri-security", 1, false, mMockContext); 222 223 final int MASK = 224 HostAuth.FLAG_SSL | HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL_CERTIFICATES; 225 226 // Set various URIs and check the resulting flags 227 ha.setStoreUri("protocol://user:password@server:123"); 228 assertEquals(0, ha.mFlags & MASK); 229 ha.setStoreUri("protocol+ssl+://user:password@server:123"); 230 assertEquals(HostAuth.FLAG_SSL, ha.mFlags & MASK); 231 ha.setStoreUri("protocol+ssl+trustallcerts://user:password@server:123"); 232 assertEquals(HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL_CERTIFICATES, ha.mFlags & MASK); 233 ha.setStoreUri("protocol+tls+://user:password@server:123"); 234 assertEquals(HostAuth.FLAG_TLS, ha.mFlags & MASK); 235 ha.setStoreUri("protocol+tls+trustallcerts://user:password@server:123"); 236 assertEquals(HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL_CERTIFICATES, ha.mFlags & MASK); 237 238 // Now check the retrival method (building URI from flags) 239 ha.mFlags &= ~MASK; 240 String uriString = ha.getStoreUri(); 241 assertTrue(uriString.startsWith("protocol://")); 242 ha.mFlags |= HostAuth.FLAG_SSL; 243 uriString = ha.getStoreUri(); 244 assertTrue(uriString.startsWith("protocol+ssl+://")); 245 ha.mFlags |= HostAuth.FLAG_TRUST_ALL_CERTIFICATES; 246 uriString = ha.getStoreUri(); 247 assertTrue(uriString.startsWith("protocol+ssl+trustallcerts://")); 248 ha.mFlags &= ~MASK; 249 ha.mFlags |= HostAuth.FLAG_TLS; 250 uriString = ha.getStoreUri(); 251 assertTrue(uriString.startsWith("protocol+tls+://")); 252 ha.mFlags |= HostAuth.FLAG_TRUST_ALL_CERTIFICATES; 253 uriString = ha.getStoreUri(); 254 assertTrue(uriString.startsWith("protocol+tls+trustallcerts://")); 255 } 256 257 /** 258 * Test port assignments made from Uris 259 */ 260 @SuppressWarnings("deprecation") 261 public void testHostAuthPortAssignments() { 262 HostAuth ha = ProviderTestUtils.setupHostAuth("uri-port", 1, false, mMockContext); 263 264 // Set various URIs and check the resulting flags 265 // Hardwired port 266 ha.setStoreUri("imap://user:password@server:123"); 267 assertEquals(123, ha.mPort); 268 // Auto-assigned ports 269 ha.setStoreUri("imap://user:password@server"); 270 assertEquals(143, ha.mPort); 271 ha.setStoreUri("imap+ssl://user:password@server"); 272 assertEquals(993, ha.mPort); 273 ha.setStoreUri("imap+ssl+trustallcerts://user:password@server"); 274 assertEquals(993, ha.mPort); 275 ha.setStoreUri("imap+tls://user:password@server"); 276 assertEquals(143, ha.mPort); 277 ha.setStoreUri("imap+tls+trustallcerts://user:password@server"); 278 assertEquals(143, ha.mPort); 279 280 // Hardwired port 281 ha.setStoreUri("pop3://user:password@server:123"); 282 assertEquals(123, ha.mPort); 283 // Auto-assigned ports 284 ha.setStoreUri("pop3://user:password@server"); 285 assertEquals(110, ha.mPort); 286 ha.setStoreUri("pop3+ssl://user:password@server"); 287 assertEquals(995, ha.mPort); 288 ha.setStoreUri("pop3+ssl+trustallcerts://user:password@server"); 289 assertEquals(995, ha.mPort); 290 ha.setStoreUri("pop3+tls://user:password@server"); 291 assertEquals(110, ha.mPort); 292 ha.setStoreUri("pop3+tls+trustallcerts://user:password@server"); 293 assertEquals(110, ha.mPort); 294 295 // Hardwired port 296 ha.setStoreUri("eas://user:password@server:123"); 297 assertEquals(123, ha.mPort); 298 // Auto-assigned ports 299 ha.setStoreUri("eas://user:password@server"); 300 assertEquals(80, ha.mPort); 301 ha.setStoreUri("eas+ssl://user:password@server"); 302 assertEquals(443, ha.mPort); 303 ha.setStoreUri("eas+ssl+trustallcerts://user:password@server"); 304 assertEquals(443, ha.mPort); 305 306 // Hardwired port 307 ha.setStoreUri("smtp://user:password@server:123"); 308 assertEquals(123, ha.mPort); 309 // Auto-assigned ports 310 ha.setStoreUri("smtp://user:password@server"); 311 assertEquals(587, ha.mPort); 312 ha.setStoreUri("smtp+ssl://user:password@server"); 313 assertEquals(465, ha.mPort); 314 ha.setStoreUri("smtp+ssl+trustallcerts://user:password@server"); 315 assertEquals(465, ha.mPort); 316 ha.setStoreUri("smtp+tls://user:password@server"); 317 assertEquals(587, ha.mPort); 318 ha.setStoreUri("smtp+tls+trustallcerts://user:password@server"); 319 assertEquals(587, ha.mPort); 320 } 321 322 /** 323 * Test simple mailbox save/retrieve 324 */ 325 public void testMailboxSave() { 326 Account account1 = ProviderTestUtils.setupAccount("mailbox-save", true, mMockContext); 327 long account1Id = account1.mId; 328 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, 329 mMockContext); 330 long box1Id = box1.mId; 331 332 Mailbox box2 = EmailContent.Mailbox.restoreMailboxWithId(mMockContext, box1Id); 333 334 ProviderTestUtils.assertMailboxEqual("testMailboxSave", box1, box2); 335 } 336 337 private static String[] expectedAttachmentNames = 338 new String[] {"attachment1.doc", "attachment2.xls", "attachment3"}; 339 // The lengths need to be kept in ascending order 340 private static long[] expectedAttachmentSizes = new long[] {31415L, 97701L, 151213L}; 341 342 /* 343 * Returns null if the message has no body. 344 */ 345 private Body loadBodyForMessageId(long messageId) { 346 Cursor c = null; 347 try { 348 c = mMockContext.getContentResolver().query( 349 EmailContent.Body.CONTENT_URI, 350 EmailContent.Body.CONTENT_PROJECTION, 351 EmailContent.Body.MESSAGE_KEY + "=?", 352 new String[] {String.valueOf(messageId)}, 353 null); 354 int numBodies = c.getCount(); 355 assertTrue("at most one body", numBodies < 2); 356 return c.moveToFirst() ? EmailContent.getContent(c, Body.class) : null; 357 } finally { 358 c.close(); 359 } 360 } 361 362 /** 363 * Test simple message save/retrieve 364 * 365 * TODO: serverId vs. serverIntId 366 */ 367 public void testMessageSave() { 368 Account account1 = ProviderTestUtils.setupAccount("message-save", true, mMockContext); 369 long account1Id = account1.mId; 370 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 371 long box1Id = box1.mId; 372 373 // Test a simple message (saved with no body) 374 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 375 true, mMockContext); 376 long message1Id = message1.mId; 377 Message message1get = EmailContent.Message.restoreMessageWithId(mMockContext, message1Id); 378 ProviderTestUtils.assertMessageEqual("testMessageSave", message1, message1get); 379 380 // Test a message saved with a body 381 // Note that it will read back w/o the text & html so we must extract those 382 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 383 true, mMockContext); 384 long message2Id = message2.mId; 385 String text2 = message2.mText; 386 String html2 = message2.mHtml; 387 String textReply2 = message2.mTextReply; 388 String htmlReply2 = message2.mHtmlReply; 389 long sourceKey2 = message2.mSourceKey; 390 String introText2 = message2.mIntroText; 391 message2.mText = null; 392 message2.mHtml = null; 393 message2.mTextReply = null; 394 message2.mHtmlReply = null; 395 message2.mSourceKey = 0; 396 message2.mIntroText = null; 397 Message message2get = EmailContent.Message.restoreMessageWithId(mMockContext, message2Id); 398 ProviderTestUtils.assertMessageEqual("testMessageSave", message2, message2get); 399 400 // Now see if there's a body saved with the right stuff 401 Body body2 = loadBodyForMessageId(message2Id); 402 assertEquals("body text", text2, body2.mTextContent); 403 assertEquals("body html", html2, body2.mHtmlContent); 404 assertEquals("reply text", textReply2, body2.mTextReply); 405 assertEquals("reply html", htmlReply2, body2.mHtmlReply); 406 assertEquals("source key", sourceKey2, body2.mSourceKey); 407 assertEquals("intro text", introText2, body2.mIntroText); 408 409 // Message with attachments and body 410 Message message3 = ProviderTestUtils.setupMessage("message3", account1Id, box1Id, true, 411 false, mMockContext); 412 ArrayList<Attachment> atts = new ArrayList<Attachment>(); 413 for (int i = 0; i < 3; i++) { 414 atts.add(ProviderTestUtils.setupAttachment( 415 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 416 false, mMockContext)); 417 } 418 message3.mAttachments = atts; 419 message3.save(mMockContext); 420 long message3Id = message3.mId; 421 422 // Now check the attachments; there should be three and they should match name and size 423 Cursor c = null; 424 try { 425 // Note that there is NO guarantee of the order of returned records in the general case, 426 // so we specifically ask for ordering by size. The expectedAttachmentSizes array must 427 // be kept sorted by size (ascending) for this test to work properly 428 c = mMockContext.getContentResolver().query( 429 Attachment.CONTENT_URI, 430 Attachment.CONTENT_PROJECTION, 431 Attachment.MESSAGE_KEY + "=?", 432 new String[] { 433 String.valueOf(message3Id) 434 }, 435 Attachment.SIZE); 436 int numAtts = c.getCount(); 437 assertEquals(3, numAtts); 438 int i = 0; 439 while (c.moveToNext()) { 440 Attachment actual = EmailContent.getContent(c, Attachment.class); 441 ProviderTestUtils.assertAttachmentEqual("save-message3", atts.get(i), actual); 442 i++; 443 } 444 } finally { 445 c.close(); 446 } 447 448 // Message with attachments but no body 449 Message message4 = ProviderTestUtils.setupMessage("message4", account1Id, box1Id, false, 450 false, mMockContext); 451 atts = new ArrayList<Attachment>(); 452 for (int i = 0; i < 3; i++) { 453 atts.add(ProviderTestUtils.setupAttachment( 454 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 455 false, mMockContext)); 456 } 457 message4.mAttachments = atts; 458 message4.save(mMockContext); 459 long message4Id = message4.mId; 460 461 // Now check the attachments; there should be three and they should match name and size 462 c = null; 463 464 try { 465 // Note that there is NO guarantee of the order of returned records in the general case, 466 // so we specifically ask for ordering by size. The expectedAttachmentSizes array must 467 // be kept sorted by size (ascending) for this test to work properly 468 c = mMockContext.getContentResolver().query( 469 Attachment.CONTENT_URI, 470 Attachment.CONTENT_PROJECTION, 471 Attachment.MESSAGE_KEY + "=?", 472 new String[] { 473 String.valueOf(message4Id) 474 }, 475 Attachment.SIZE); 476 int numAtts = c.getCount(); 477 assertEquals(3, numAtts); 478 int i = 0; 479 while (c.moveToNext()) { 480 Attachment actual = EmailContent.getContent(c, Attachment.class); 481 ProviderTestUtils.assertAttachmentEqual("save-message4", atts.get(i), actual); 482 i++; 483 } 484 } finally { 485 c.close(); 486 } 487 488 // test EmailContent.restoreAttachmentsWitdMessageId() 489 Attachment[] attachments = 490 Attachment.restoreAttachmentsWithMessageId(mMockContext, message4Id); 491 int size = attachments.length; 492 assertEquals(3, size); 493 for (int i = 0; i < size; ++i) { 494 ProviderTestUtils.assertAttachmentEqual("save-message4", atts.get(i), attachments[i]); 495 } 496 } 497 498 /** 499 * TODO: update account 500 */ 501 502 /** 503 * TODO: update mailbox 504 */ 505 506 /** 507 * TODO: update message 508 */ 509 510 /** 511 * Test delete account 512 * TODO: hostauth 513 */ 514 public void testAccountDelete() { 515 Account account1 = ProviderTestUtils.setupAccount("account-delete-1", true, mMockContext); 516 long account1Id = account1.mId; 517 Account account2 = ProviderTestUtils.setupAccount("account-delete-2", true, mMockContext); 518 long account2Id = account2.mId; 519 520 // make sure there are two accounts 521 int numBoxes = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 522 assertEquals(2, numBoxes); 523 524 // now delete one of them 525 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, account1Id); 526 mMockContext.getContentResolver().delete(uri, null, null); 527 528 // make sure there's only one account now 529 numBoxes = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 530 assertEquals(1, numBoxes); 531 532 // now delete the other one 533 uri = ContentUris.withAppendedId(Account.CONTENT_URI, account2Id); 534 mMockContext.getContentResolver().delete(uri, null, null); 535 536 // make sure there are no accounts now 537 numBoxes = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 538 assertEquals(0, numBoxes); 539 } 540 541 /** 542 * Test for Body.lookupBodyIdWithMessageId() 543 * Verifies that: 544 * - for a message without body, -1 is returned. 545 * - for a mesage with body, the id matches the one from loadBodyForMessageId. 546 */ 547 public void testLookupBodyIdWithMessageId() { 548 final ContentResolver resolver = mMockContext.getContentResolver(); 549 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 550 long account1Id = account1.mId; 551 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 552 long box1Id = box1.mId; 553 554 // 1. create message with no body, check that returned bodyId is -1 555 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 556 true, mMockContext); 557 long message1Id = message1.mId; 558 long bodyId1 = Body.lookupBodyIdWithMessageId(resolver, message1Id); 559 assertEquals(bodyId1, -1); 560 561 // 2. create message with body, check that returned bodyId is correct 562 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 563 true, mMockContext); 564 long message2Id = message2.mId; 565 long bodyId2 = Body.lookupBodyIdWithMessageId(resolver, message2Id); 566 Body body = loadBodyForMessageId(message2Id); 567 assertNotNull(body); 568 assertEquals(body.mId, bodyId2); 569 } 570 571 /** 572 * Test for Body.updateBodyWithMessageId(). 573 * 1. - create message without body, 574 * - update its body (set TEXT_CONTENT) 575 * - check correct updated body is read back 576 * 577 * 2. - create message with body, 578 * - update body (set TEXT_CONTENT) 579 * - check correct updated body is read back 580 */ 581 public void testUpdateBodyWithMessageId() { 582 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 583 long account1Id = account1.mId; 584 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 585 long box1Id = box1.mId; 586 587 final String textContent = "foobar some odd text"; 588 final String htmlContent = "and some html"; 589 final String textReply = "plain text reply"; 590 final String htmlReply = "or the html reply"; 591 final String introText = "fred wrote:"; 592 593 ContentValues values = new ContentValues(); 594 values.put(BodyColumns.TEXT_CONTENT, textContent); 595 values.put(BodyColumns.HTML_CONTENT, htmlContent); 596 values.put(BodyColumns.TEXT_REPLY, textReply); 597 values.put(BodyColumns.HTML_REPLY, htmlReply); 598 values.put(BodyColumns.SOURCE_MESSAGE_KEY, 17); 599 values.put(BodyColumns.INTRO_TEXT, introText); 600 601 // 1 602 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 603 true, mMockContext); 604 long message1Id = message1.mId; 605 Body body1 = loadBodyForMessageId(message1Id); 606 assertNull(body1); 607 Body.updateBodyWithMessageId(mMockContext, message1Id, values); 608 body1 = loadBodyForMessageId(message1Id); 609 assertNotNull(body1); 610 assertEquals(body1.mTextContent, textContent); 611 assertEquals(body1.mHtmlContent, htmlContent); 612 assertEquals(body1.mTextReply, textReply); 613 assertEquals(body1.mHtmlReply, htmlReply); 614 assertEquals(body1.mSourceKey, 17); 615 assertEquals(body1.mIntroText, introText); 616 617 // 2 618 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 619 true, mMockContext); 620 long message2Id = message2.mId; 621 Body body2 = loadBodyForMessageId(message2Id); 622 assertNotNull(body2); 623 assertTrue(!body2.mTextContent.equals(textContent)); 624 Body.updateBodyWithMessageId(mMockContext, message2Id, values); 625 body2 = loadBodyForMessageId(message1Id); 626 assertNotNull(body2); 627 assertEquals(body2.mTextContent, textContent); 628 assertEquals(body2.mHtmlContent, htmlContent); 629 assertEquals(body2.mTextReply, textReply); 630 assertEquals(body2.mHtmlReply, htmlReply); 631 assertEquals(body2.mSourceKey, 17); 632 assertEquals(body2.mIntroText, introText); 633 } 634 635 /** 636 * Test body retrieve methods 637 */ 638 public void testBodyRetrieve() { 639 // No account needed 640 // No mailbox needed 641 Message message1 = ProviderTestUtils.setupMessage("bodyretrieve", 1, 1, true, 642 true, mMockContext); 643 long messageId = message1.mId; 644 645 assertEquals(message1.mText, 646 Body.restoreBodyTextWithMessageId(mMockContext, messageId)); 647 assertEquals(message1.mHtml, 648 Body.restoreBodyHtmlWithMessageId(mMockContext, messageId)); 649 assertEquals(message1.mTextReply, 650 Body.restoreReplyTextWithMessageId(mMockContext, messageId)); 651 assertEquals(message1.mHtmlReply, 652 Body.restoreReplyHtmlWithMessageId(mMockContext, messageId)); 653 assertEquals(message1.mIntroText, 654 Body.restoreIntroTextWithMessageId(mMockContext, messageId)); 655 assertEquals(message1.mSourceKey, 656 Body.restoreBodySourceKey(mMockContext, messageId)); 657 } 658 659 /** 660 * Test delete body. 661 * 1. create message without body (message id 1) 662 * 2. create message with body (message id 2. The body has _id 1 and messageKey 2). 663 * 3. delete first message. 664 * 4. verify that body for message 2 has not been deleted. 665 * 5. delete message 2, verify body is deleted. 666 */ 667 public void testDeleteBody() { 668 final ContentResolver resolver = mMockContext.getContentResolver(); 669 670 // Create account and mailboxes 671 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 672 long account1Id = account1.mId; 673 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 674 long box1Id = box1.mId; 675 676 // 1. create message without body 677 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 678 true, mMockContext); 679 long message1Id = message1.mId; 680 681 // 2. create message with body 682 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 683 true, mMockContext); 684 long message2Id = message2.mId; 685 // verify body is there 686 assertNotNull(loadBodyForMessageId(message2Id)); 687 688 // 3. delete first message 689 resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message1Id), null, null); 690 691 // 4. verify body for second message wasn't deleted 692 assertNotNull(loadBodyForMessageId(message2Id)); 693 694 // 5. delete second message, check its body is deleted 695 resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message2Id), null, null); 696 assertNull(loadBodyForMessageId(message2Id)); 697 } 698 699 /** 700 * Test delete orphan bodies. 701 * 1. create message without body (message id 1) 702 * 2. create message with body (message id 2. Body has _id 1 and messageKey 2). 703 * 3. delete first message. 704 * 4. delete some other mailbox -- this triggers delete orphan bodies. 705 * 5. verify that body for message 2 has not been deleted. 706 */ 707 public void testDeleteOrphanBodies() { 708 final ContentResolver resolver = mMockContext.getContentResolver(); 709 710 // Create account and two mailboxes 711 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 712 long account1Id = account1.mId; 713 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 714 long box1Id = box1.mId; 715 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mMockContext); 716 long box2Id = box2.mId; 717 718 // 1. create message without body 719 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 720 true, mMockContext); 721 long message1Id = message1.mId; 722 723 // 2. create message with body 724 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 725 true, mMockContext); 726 long message2Id = message2.mId; 727 //verify body is there 728 assertNotNull(loadBodyForMessageId(message2Id)); 729 730 // 3. delete first message 731 resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message1Id), null, null); 732 733 // 4. delete some mailbox (because it triggers "delete orphan bodies") 734 resolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2Id), null, null); 735 736 // 5. verify body for second message wasn't deleted during "delete orphan bodies" 737 assertNotNull(loadBodyForMessageId(message2Id)); 738 } 739 740 /** 741 * Test delete orphan messages 742 * 1. create message without body (message id 1) 743 * 2. create message with body (message id 2. Body has _id 1 and messageKey 2). 744 * 3. delete first message. 745 * 4. delete some other mailbox -- this triggers delete orphan bodies. 746 * 5. verify that body for message 2 has not been deleted. 747 */ 748 public void testDeleteOrphanMessages() { 749 final ContentResolver resolver = mMockContext.getContentResolver(); 750 final Context context = mMockContext; 751 752 // Create account and two mailboxes 753 Account acct = ProviderTestUtils.setupAccount("orphaned body", true, context); 754 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", acct.mId, true, context); 755 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", acct.mId, true, context); 756 757 // Create 4 messages in box1 758 Message msg1_1 = 759 ProviderTestUtils.setupMessage("message1", acct.mId, box1.mId, false, true, context); 760 Message msg1_2 = 761 ProviderTestUtils.setupMessage("message2", acct.mId, box1.mId, false, true, context); 762 Message msg1_3 = 763 ProviderTestUtils.setupMessage("message3", acct.mId, box1.mId, false, true, context); 764 Message msg1_4 = 765 ProviderTestUtils.setupMessage("message4", acct.mId, box1.mId, false, true, context); 766 767 // Create 4 messages in box2 768 Message msg2_1 = 769 ProviderTestUtils.setupMessage("message1", acct.mId, box2.mId, false, true, context); 770 Message msg2_2 = 771 ProviderTestUtils.setupMessage("message2", acct.mId, box2.mId, false, true, context); 772 Message msg2_3 = 773 ProviderTestUtils.setupMessage("message3", acct.mId, box2.mId, false, true, context); 774 Message msg2_4 = 775 ProviderTestUtils.setupMessage("message4", acct.mId, box2.mId, false, true, context); 776 777 // Delete 2 from each mailbox 778 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg1_1.mId), 779 null, null); 780 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg1_2.mId), 781 null, null); 782 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg2_1.mId), 783 null, null); 784 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg2_2.mId), 785 null, null); 786 787 // There should be 4 items in the deleted item table 788 assertEquals(4, EmailContent.count(context, Message.DELETED_CONTENT_URI, null, null)); 789 790 // Update 2 from each mailbox 791 ContentValues v = new ContentValues(); 792 v.put(MessageColumns.DISPLAY_NAME, "--updated--"); 793 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg1_3.mId), 794 v, null, null); 795 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg1_4.mId), 796 v, null, null); 797 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg2_3.mId), 798 v, null, null); 799 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg2_4.mId), 800 v, null, null); 801 802 // There should be 4 items in the updated item table 803 assertEquals(4, EmailContent.count(context, Message.UPDATED_CONTENT_URI, null, null)); 804 805 // Manually add 2 messages from a "deleted" mailbox to deleted and updated tables 806 // Use a value > 2 for the deleted box id 807 long delBoxId = 10; 808 // Create 4 messages in the "deleted" mailbox 809 Message msgX_A = 810 ProviderTestUtils.setupMessage("messageA", acct.mId, delBoxId, false, false, context); 811 Message msgX_B = 812 ProviderTestUtils.setupMessage("messageB", acct.mId, delBoxId, false, false, context); 813 Message msgX_C = 814 ProviderTestUtils.setupMessage("messageC", acct.mId, delBoxId, false, false, context); 815 Message msgX_D = 816 ProviderTestUtils.setupMessage("messageD", acct.mId, delBoxId, false, false, context); 817 818 ContentValues cv; 819 // We have to assign id's manually because there are no autoincrement id's for these tables 820 // Start with an id that won't exist, since id's in these tables must be unique 821 long msgId = 10; 822 // It's illegal to manually insert these, so we need to catch the exception 823 // NOTE: The insert succeeds, and then throws the exception 824 try { 825 cv = msgX_A.toContentValues(); 826 cv.put(EmailContent.RECORD_ID, msgId++); 827 resolver.insert(Message.DELETED_CONTENT_URI, cv); 828 } catch (IllegalArgumentException e) { 829 } 830 try { 831 cv = msgX_B.toContentValues(); 832 cv.put(EmailContent.RECORD_ID, msgId++); 833 resolver.insert(Message.DELETED_CONTENT_URI, cv); 834 } catch (IllegalArgumentException e) { 835 } 836 try { 837 cv = msgX_C.toContentValues(); 838 cv.put(EmailContent.RECORD_ID, msgId++); 839 resolver.insert(Message.UPDATED_CONTENT_URI, cv); 840 } catch (IllegalArgumentException e) { 841 } 842 try { 843 cv = msgX_D.toContentValues(); 844 cv.put(EmailContent.RECORD_ID, msgId++); 845 resolver.insert(Message.UPDATED_CONTENT_URI, cv); 846 } catch (IllegalArgumentException e) { 847 } 848 849 // There should be 6 items in the deleted and updated tables 850 assertEquals(6, EmailContent.count(context, Message.UPDATED_CONTENT_URI, null, null)); 851 assertEquals(6, EmailContent.count(context, Message.DELETED_CONTENT_URI, null, null)); 852 853 // Delete the orphans 854 EmailProvider.deleteOrphans(EmailProvider.getReadableDatabase(context), 855 Message.DELETED_TABLE_NAME); 856 EmailProvider.deleteOrphans(EmailProvider.getReadableDatabase(context), 857 Message.UPDATED_TABLE_NAME); 858 859 // There should now be 4 messages in each of the deleted and updated tables again 860 assertEquals(4, EmailContent.count(context, Message.UPDATED_CONTENT_URI, null, null)); 861 assertEquals(4, EmailContent.count(context, Message.DELETED_CONTENT_URI, null, null)); 862 } 863 864 /** 865 * Test delete mailbox 866 */ 867 public void testMailboxDelete() { 868 Account account1 = ProviderTestUtils.setupAccount("mailbox-delete", true, mMockContext); 869 long account1Id = account1.mId; 870 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 871 long box1Id = box1.mId; 872 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mMockContext); 873 long box2Id = box2.mId; 874 875 String selection = EmailContent.MailboxColumns.ACCOUNT_KEY + "=?"; 876 String[] selArgs = new String[] { String.valueOf(account1Id) }; 877 878 // make sure there are two mailboxes 879 int numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs); 880 assertEquals(2, numBoxes); 881 882 // now delete one of them 883 Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box1Id); 884 mMockContext.getContentResolver().delete(uri, null, null); 885 886 // make sure there's only one mailbox now 887 numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs); 888 assertEquals(1, numBoxes); 889 890 // now delete the other one 891 uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2Id); 892 mMockContext.getContentResolver().delete(uri, null, null); 893 894 // make sure there are no mailboxes now 895 numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs); 896 assertEquals(0, numBoxes); 897 } 898 899 /** 900 * Test delete message 901 * TODO: body 902 * TODO: attachments 903 */ 904 public void testMessageDelete() { 905 Account account1 = ProviderTestUtils.setupAccount("message-delete", true, mMockContext); 906 long account1Id = account1.mId; 907 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 908 long box1Id = box1.mId; 909 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 910 true, mMockContext); 911 long message1Id = message1.mId; 912 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, 913 true, mMockContext); 914 long message2Id = message2.mId; 915 916 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " + 917 EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 918 String[] selArgs = new String[] { String.valueOf(account1Id), String.valueOf(box1Id) }; 919 920 // make sure there are two messages 921 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 922 assertEquals(2, numMessages); 923 924 // now delete one of them 925 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1Id); 926 mMockContext.getContentResolver().delete(uri, null, null); 927 928 // make sure there's only one message now 929 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 930 assertEquals(1, numMessages); 931 932 // now delete the other one 933 uri = ContentUris.withAppendedId(Message.CONTENT_URI, message2Id); 934 mMockContext.getContentResolver().delete(uri, null, null); 935 936 // make sure there are no messages now 937 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 938 assertEquals(0, numMessages); 939 } 940 941 /** 942 * Test delete synced message 943 * TODO: body 944 * TODO: attachments 945 */ 946 public void testSyncedMessageDelete() { 947 Account account1 = ProviderTestUtils.setupAccount("synced-message-delete", true, 948 mMockContext); 949 long account1Id = account1.mId; 950 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 951 long box1Id = box1.mId; 952 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 953 true, mMockContext); 954 long message1Id = message1.mId; 955 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, 956 true, mMockContext); 957 long message2Id = message2.mId; 958 959 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " 960 + EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 961 String[] selArgs = new String[] { 962 String.valueOf(account1Id), String.valueOf(box1Id) 963 }; 964 965 // make sure there are two messages 966 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 967 assertEquals(2, numMessages); 968 969 // make sure we start with no synced deletions 970 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 971 selArgs); 972 assertEquals(0, numMessages); 973 974 // now delete one of them SYNCED 975 Uri uri = ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message1Id); 976 mMockContext.getContentResolver().delete(uri, null, null); 977 978 // make sure there's only one message now 979 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 980 assertEquals(1, numMessages); 981 982 // make sure there's one synced deletion now 983 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 984 selArgs); 985 assertEquals(1, numMessages); 986 987 // now delete the other one NOT SYNCED 988 uri = ContentUris.withAppendedId(Message.CONTENT_URI, message2Id); 989 mMockContext.getContentResolver().delete(uri, null, null); 990 991 // make sure there are no messages now 992 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 993 assertEquals(0, numMessages); 994 995 // make sure there's still one deletion now 996 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 997 selArgs); 998 assertEquals(1, numMessages); 999 } 1000 1001 /** 1002 * Test message update 1003 * TODO: body 1004 * TODO: attachments 1005 */ 1006 public void testMessageUpdate() { 1007 Account account1 = ProviderTestUtils.setupAccount("message-update", true, mMockContext); 1008 long account1Id = account1.mId; 1009 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1010 long box1Id = box1.mId; 1011 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 1012 true, mMockContext); 1013 long message1Id = message1.mId; 1014 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, 1015 true, mMockContext); 1016 long message2Id = message2.mId; 1017 ContentResolver cr = mMockContext.getContentResolver(); 1018 1019 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " 1020 + EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 1021 String[] selArgs = new String[] { 1022 String.valueOf(account1Id), String.valueOf(box1Id) 1023 }; 1024 1025 // make sure there are two messages 1026 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1027 assertEquals(2, numMessages); 1028 1029 // change the first one 1030 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1Id); 1031 ContentValues cv = new ContentValues(); 1032 cv.put(MessageColumns.FROM_LIST, "from-list"); 1033 cr.update(uri, cv, null, null); 1034 1035 // make sure there's no updated message 1036 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1037 selArgs); 1038 assertEquals(0, numMessages); 1039 1040 // get the message back from the provider, make sure the change "stuck" 1041 Message restoredMessage = Message.restoreMessageWithId(mMockContext, message1Id); 1042 assertEquals("from-list", restoredMessage.mFrom); 1043 1044 // change the second one 1045 uri = ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message2Id); 1046 cv = new ContentValues(); 1047 cv.put(MessageColumns.FROM_LIST, "from-list"); 1048 cr.update(uri, cv, null, null); 1049 1050 // make sure there's one updated message 1051 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1052 selArgs); 1053 assertEquals(1, numMessages); 1054 1055 // get the message back from the provider, make sure the change "stuck", 1056 // as before 1057 restoredMessage = Message.restoreMessageWithId(mMockContext, message2Id); 1058 assertEquals("from-list", restoredMessage.mFrom); 1059 1060 // get the original message back from the provider 1061 Cursor c = cr.query(Message.UPDATED_CONTENT_URI, Message.CONTENT_PROJECTION, null, null, 1062 null); 1063 try { 1064 assertTrue(c.moveToFirst()); 1065 Message originalMessage = EmailContent.getContent(c, Message.class); 1066 // make sure this has the original value 1067 assertEquals("from message2", originalMessage.mFrom); 1068 // Should only be one 1069 assertFalse(c.moveToNext()); 1070 } finally { 1071 c.close(); 1072 } 1073 1074 // delete the second message 1075 cr.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message2Id), null, null); 1076 1077 // hey, presto! the change should be gone 1078 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1079 selArgs); 1080 assertEquals(0, numMessages); 1081 1082 // and there should now be a deleted record 1083 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 1084 selArgs); 1085 assertEquals(1, numMessages); 1086 } 1087 1088 /** 1089 * TODO: cascaded delete account 1090 * TODO: hostauth 1091 * TODO: body 1092 * TODO: attachments 1093 * TODO: create other account, mailbox & messages and confirm the right objects were deleted 1094 */ 1095 public void testCascadeDeleteAccount() { 1096 Account account1 = ProviderTestUtils.setupAccount("account-delete-cascade", true, 1097 mMockContext); 1098 long account1Id = account1.mId; 1099 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1100 long box1Id = box1.mId; 1101 /* Message message1 = */ ProviderTestUtils.setupMessage("message1", account1Id, box1Id, 1102 false, true, mMockContext); 1103 /* Message message2 = */ ProviderTestUtils.setupMessage("message2", account1Id, box1Id, 1104 false, true, mMockContext); 1105 1106 // make sure there is one account, one mailbox, and two messages 1107 int numAccounts = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 1108 assertEquals(1, numAccounts); 1109 int numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, null, null); 1110 assertEquals(1, numBoxes); 1111 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 1112 assertEquals(2, numMessages); 1113 1114 // delete the account 1115 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, account1Id); 1116 mMockContext.getContentResolver().delete(uri, null, null); 1117 1118 // make sure there are no accounts, mailboxes, or messages 1119 numAccounts = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 1120 assertEquals(0, numAccounts); 1121 numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, null, null); 1122 assertEquals(0, numBoxes); 1123 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 1124 assertEquals(0, numMessages); 1125 } 1126 1127 /** 1128 * Test cascaded delete mailbox 1129 * TODO: body 1130 * TODO: attachments 1131 * TODO: create other mailbox & messages and confirm the right objects were deleted 1132 */ 1133 public void testCascadeDeleteMailbox() { 1134 Account account1 = ProviderTestUtils.setupAccount("mailbox-delete-cascade", true, 1135 mMockContext); 1136 long account1Id = account1.mId; 1137 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1138 long box1Id = box1.mId; 1139 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, 1140 false, true, mMockContext); 1141 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, 1142 false, true, mMockContext); 1143 Message message3 = ProviderTestUtils.setupMessage("message3", account1Id, box1Id, 1144 false, true, mMockContext); 1145 Message message4 = ProviderTestUtils.setupMessage("message4", account1Id, box1Id, 1146 false, true, mMockContext); 1147 ProviderTestUtils.setupMessage("message5", account1Id, box1Id, false, true, mMockContext); 1148 ProviderTestUtils.setupMessage("message6", account1Id, box1Id, false, true, mMockContext); 1149 1150 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " + 1151 EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 1152 String[] selArgs = new String[] { String.valueOf(account1Id), String.valueOf(box1Id) }; 1153 1154 // make sure there are six messages 1155 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1156 assertEquals(6, numMessages); 1157 1158 ContentValues cv = new ContentValues(); 1159 cv.put(Message.SERVER_ID, "SERVER_ID"); 1160 ContentResolver resolver = mMockContext.getContentResolver(); 1161 1162 // Update two messages 1163 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message1.mId), 1164 cv, null, null); 1165 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message2.mId), 1166 cv, null, null); 1167 // Delete two messages 1168 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message3.mId), 1169 null, null); 1170 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message4.mId), 1171 null, null); 1172 1173 // There should now be two messages in updated/deleted, and 4 in messages 1174 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1175 assertEquals(4, numMessages); 1176 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 1177 selArgs); 1178 assertEquals(2, numMessages); 1179 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1180 selArgs); 1181 assertEquals(2, numMessages); 1182 1183 // now delete the mailbox 1184 Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box1Id); 1185 resolver.delete(uri, null, null); 1186 1187 // there should now be zero messages in all three tables 1188 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1189 assertEquals(0, numMessages); 1190 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 1191 selArgs); 1192 assertEquals(0, numMessages); 1193 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1194 selArgs); 1195 assertEquals(0, numMessages); 1196 } 1197 1198 /** 1199 * Test cascaded delete message 1200 * Confirms that deleting a message will also delete its body & attachments 1201 */ 1202 public void testCascadeMessageDelete() { 1203 Account account1 = ProviderTestUtils.setupAccount("message-cascade", true, mMockContext); 1204 long account1Id = account1.mId; 1205 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1206 long box1Id = box1.mId; 1207 1208 // Each message has a body, and also give each 2 attachments 1209 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 1210 false, mMockContext); 1211 ArrayList<Attachment> atts = new ArrayList<Attachment>(); 1212 for (int i = 0; i < 2; i++) { 1213 atts.add(ProviderTestUtils.setupAttachment( 1214 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 1215 false, mMockContext)); 1216 } 1217 message1.mAttachments = atts; 1218 message1.save(mMockContext); 1219 long message1Id = message1.mId; 1220 1221 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, true, 1222 false, mMockContext); 1223 atts = new ArrayList<Attachment>(); 1224 for (int i = 0; i < 2; i++) { 1225 atts.add(ProviderTestUtils.setupAttachment( 1226 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 1227 false, mMockContext)); 1228 } 1229 message2.mAttachments = atts; 1230 message2.save(mMockContext); 1231 long message2Id = message2.mId; 1232 1233 // Set up to test total counts of bodies & attachments for our test messages 1234 String bodySelection = BodyColumns.MESSAGE_KEY + " IN (?,?)"; 1235 String attachmentSelection = AttachmentColumns.MESSAGE_KEY + " IN (?,?)"; 1236 String[] selArgs = new String[] { String.valueOf(message1Id), String.valueOf(message2Id) }; 1237 1238 // make sure there are two bodies 1239 int numBodies = EmailContent.count(mMockContext, Body.CONTENT_URI, bodySelection, selArgs); 1240 assertEquals(2, numBodies); 1241 1242 // make sure there are four attachments 1243 int numAttachments = EmailContent.count(mMockContext, Attachment.CONTENT_URI, 1244 attachmentSelection, selArgs); 1245 assertEquals(4, numAttachments); 1246 1247 // now delete one of the messages 1248 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1Id); 1249 mMockContext.getContentResolver().delete(uri, null, null); 1250 1251 // there should be one body and two attachments 1252 numBodies = EmailContent.count(mMockContext, Body.CONTENT_URI, bodySelection, selArgs); 1253 assertEquals(1, numBodies); 1254 1255 numAttachments = EmailContent.count(mMockContext, Attachment.CONTENT_URI, 1256 attachmentSelection, selArgs); 1257 assertEquals(2, numAttachments); 1258 1259 // now delete the other message 1260 uri = ContentUris.withAppendedId(Message.CONTENT_URI, message2Id); 1261 mMockContext.getContentResolver().delete(uri, null, null); 1262 1263 // make sure there are no bodies or attachments 1264 numBodies = EmailContent.count(mMockContext, Body.CONTENT_URI, bodySelection, selArgs); 1265 assertEquals(0, numBodies); 1266 1267 numAttachments = EmailContent.count(mMockContext, Attachment.CONTENT_URI, 1268 attachmentSelection, selArgs); 1269 assertEquals(0, numAttachments); 1270 } 1271 1272 /** 1273 * Test that our unique file name algorithm works as expected. Since this test requires an 1274 * SD card, we check the environment first, and return immediately if none is mounted. 1275 * @throws IOException 1276 */ 1277 public void testCreateUniqueFile() throws IOException { 1278 // Delete existing files, if they exist 1279 if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 1280 return; 1281 } 1282 try { 1283 String fileName = "A11achm3n1.doc"; 1284 File uniqueFile = Attachment.createUniqueFile(fileName); 1285 assertEquals(fileName, uniqueFile.getName()); 1286 if (uniqueFile.createNewFile()) { 1287 uniqueFile = Attachment.createUniqueFile(fileName); 1288 assertEquals("A11achm3n1-2.doc", uniqueFile.getName()); 1289 if (uniqueFile.createNewFile()) { 1290 uniqueFile = Attachment.createUniqueFile(fileName); 1291 assertEquals("A11achm3n1-3.doc", uniqueFile.getName()); 1292 } 1293 } 1294 fileName = "A11achm3n1"; 1295 uniqueFile = Attachment.createUniqueFile(fileName); 1296 assertEquals(fileName, uniqueFile.getName()); 1297 if (uniqueFile.createNewFile()) { 1298 uniqueFile = Attachment.createUniqueFile(fileName); 1299 assertEquals("A11achm3n1-2", uniqueFile.getName()); 1300 } 1301 } finally { 1302 File directory = Environment.getExternalStorageDirectory(); 1303 // These are the files that should be created earlier in the test. Make sure 1304 // they are deleted for the next go-around 1305 String[] fileNames = new String[] {"A11achm3n1.doc", "A11achm3n1-2.doc", "A11achm3n1"}; 1306 int length = fileNames.length; 1307 for (int i = 0; i < length; i++) { 1308 File file = new File(directory, fileNames[i]); 1309 if (file.exists()) { 1310 file.delete(); 1311 } 1312 } 1313 } 1314 } 1315 1316 /** 1317 * Test retrieving attachments by message ID (using EmailContent.Attachment.MESSAGE_ID_URI) 1318 */ 1319 public void testGetAttachmentByMessageIdUri() { 1320 1321 // Note, we don't strictly need accounts, mailboxes or messages to run this test. 1322 Attachment a1 = ProviderTestUtils.setupAttachment(1, "a1", 100, true, mMockContext); 1323 Attachment a2 = ProviderTestUtils.setupAttachment(1, "a2", 200, true, mMockContext); 1324 ProviderTestUtils.setupAttachment(2, "a3", 300, true, mMockContext); 1325 ProviderTestUtils.setupAttachment(2, "a4", 400, true, mMockContext); 1326 1327 // Now ask for the attachments of message id=1 1328 // Note: Using the "sort by size" trick to bring them back in expected order 1329 Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, 1); 1330 Cursor c = mMockContext.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION, 1331 null, null, Attachment.SIZE); 1332 assertEquals(2, c.getCount()); 1333 1334 try { 1335 c.moveToFirst(); 1336 Attachment a1Get = EmailContent.getContent(c, Attachment.class); 1337 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-1", a1, a1Get); 1338 c.moveToNext(); 1339 Attachment a2Get = EmailContent.getContent(c, Attachment.class); 1340 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-2", a2, a2Get); 1341 } finally { 1342 c.close(); 1343 } 1344 } 1345 1346 /** 1347 * Test deleting attachments by message ID (using EmailContent.Attachment.MESSAGE_ID_URI) 1348 */ 1349 public void testDeleteAttachmentByMessageIdUri() { 1350 ContentResolver mockResolver = mMockContext.getContentResolver(); 1351 1352 // Note, we don't strictly need accounts, mailboxes or messages to run this test. 1353 ProviderTestUtils.setupAttachment(1, "a1", 100, true, mMockContext); 1354 ProviderTestUtils.setupAttachment(1, "a2", 200, true, mMockContext); 1355 Attachment a3 = ProviderTestUtils.setupAttachment(2, "a3", 300, true, mMockContext); 1356 Attachment a4 = ProviderTestUtils.setupAttachment(2, "a4", 400, true, mMockContext); 1357 1358 // Delete all attachments for message id=1 1359 Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, 1); 1360 mockResolver.delete(uri, null, null); 1361 1362 // Read back all attachments and confirm that we have the expected remaining attachments 1363 // (the attachments that are set for message id=2). Note order-by size to simplify test. 1364 Cursor c = mockResolver.query(Attachment.CONTENT_URI, Attachment.CONTENT_PROJECTION, 1365 null, null, Attachment.SIZE); 1366 assertEquals(2, c.getCount()); 1367 1368 try { 1369 c.moveToFirst(); 1370 Attachment a3Get = EmailContent.getContent(c, Attachment.class); 1371 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-3", a3, a3Get); 1372 c.moveToNext(); 1373 Attachment a4Get = EmailContent.getContent(c, Attachment.class); 1374 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-4", a4, a4Get); 1375 } finally { 1376 c.close(); 1377 } 1378 } 1379 1380 /** 1381 * Tests of default account behavior 1382 * 1383 * 1. Simple set/get 1384 * 2. Moving default between 3 accounts 1385 * 3. Delete default, make sure another becomes default 1386 */ 1387 public void testSetGetDefaultAccount() { 1388 // There should be no default account if there are no accounts 1389 long defaultAccountId = Account.getDefaultAccountId(mMockContext); 1390 assertEquals(-1, defaultAccountId); 1391 1392 Account account1 = ProviderTestUtils.setupAccount("account-default-1", true, mMockContext); 1393 long account1Id = account1.mId; 1394 Account account2 = ProviderTestUtils.setupAccount("account-default-2", true, mMockContext); 1395 long account2Id = account2.mId; 1396 Account account3 = ProviderTestUtils.setupAccount("account-default-3", true, mMockContext); 1397 long account3Id = account3.mId; 1398 1399 // With three accounts, but none marked default, confirm that some default account 1400 // is returned. Which one is undefined here. 1401 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1402 assertTrue(defaultAccountId == account1Id 1403 || defaultAccountId == account2Id 1404 || defaultAccountId == account3Id); 1405 1406 updateIsDefault(account1, true); 1407 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1408 assertEquals(account1Id, defaultAccountId); 1409 1410 updateIsDefault(account2, true); 1411 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1412 assertEquals(account2Id, defaultAccountId); 1413 1414 updateIsDefault(account3, true); 1415 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1416 assertEquals(account3Id, defaultAccountId); 1417 1418 // Now delete a non-default account and confirm no change 1419 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, account1Id); 1420 mMockContext.getContentResolver().delete(uri, null, null); 1421 1422 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1423 assertEquals(account3Id, defaultAccountId); 1424 1425 // Now confirm deleting the default account and it switches to another one 1426 uri = ContentUris.withAppendedId(Account.CONTENT_URI, account3Id); 1427 mMockContext.getContentResolver().delete(uri, null, null); 1428 1429 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1430 assertEquals(account2Id, defaultAccountId); 1431 1432 // Now delete the final account and confirm there are no default accounts again 1433 uri = ContentUris.withAppendedId(Account.CONTENT_URI, account2Id); 1434 mMockContext.getContentResolver().delete(uri, null, null); 1435 1436 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1437 assertEquals(-1, defaultAccountId); 1438 } 1439 1440 private void updateIsDefault(Account account, boolean newState) { 1441 account.setDefaultAccount(newState); 1442 ContentValues cv = new ContentValues(); 1443 cv.put(AccountColumns.IS_DEFAULT, account.mIsDefault); 1444 account.update(mMockContext, cv); 1445 } 1446 1447 public static Message setupUnreadMessage(String name, long accountId, long mailboxId, 1448 boolean addBody, boolean saveIt, Context context) { 1449 Message msg = 1450 ProviderTestUtils.setupMessage(name, accountId, mailboxId, addBody, false, context); 1451 msg.mFlagRead = false; 1452 if (saveIt) { 1453 msg.save(context); 1454 } 1455 return msg; 1456 } 1457 1458 public void testUnreadCountTriggers() { 1459 // Start with one account and three mailboxes 1460 Account account = ProviderTestUtils.setupAccount("triggers", true, mMockContext); 1461 Mailbox boxA = ProviderTestUtils.setupMailbox("boxA", account.mId, true, mMockContext); 1462 Mailbox boxB = ProviderTestUtils.setupMailbox("boxB", account.mId, true, mMockContext); 1463 Mailbox boxC = ProviderTestUtils.setupMailbox("boxC", account.mId, true, mMockContext); 1464 1465 // Make sure there are no unreads 1466 assertEquals(0, getUnreadCount(boxA.mId)); 1467 assertEquals(0, getUnreadCount(boxB.mId)); 1468 assertEquals(0, getUnreadCount(boxC.mId)); 1469 1470 // Create 4 unread messages (only 3 named) in boxA 1471 Message message1 = setupUnreadMessage("message1", account.mId, boxA.mId, 1472 false, true, mMockContext); 1473 Message message2= setupUnreadMessage("message2", account.mId, boxA.mId, 1474 false, true, mMockContext); 1475 Message message3 = setupUnreadMessage("message3", account.mId, boxA.mId, 1476 false, true, mMockContext); 1477 setupUnreadMessage("message4", account.mId, boxC.mId, false, true, mMockContext); 1478 1479 // Make sure the unreads are where we expect them 1480 assertEquals(3, getUnreadCount(boxA.mId)); 1481 assertEquals(0, getUnreadCount(boxB.mId)); 1482 assertEquals(1, getUnreadCount(boxC.mId)); 1483 1484 // After deleting message 1, the count in box A should be decremented (to 2) 1485 ContentResolver cr = mMockContext.getContentResolver(); 1486 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1.mId); 1487 cr.delete(uri, null, null); 1488 assertEquals(2, getUnreadCount(boxA.mId)); 1489 assertEquals(0, getUnreadCount(boxB.mId)); 1490 assertEquals(1, getUnreadCount(boxC.mId)); 1491 1492 // Move message 2 to box B, leaving 1 in box A and 1 in box B 1493 message2.mMailboxKey = boxB.mId; 1494 ContentValues cv = new ContentValues(); 1495 cv.put(MessageColumns.MAILBOX_KEY, boxB.mId); 1496 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message2.mId), cv, null, null); 1497 assertEquals(1, getUnreadCount(boxA.mId)); 1498 assertEquals(1, getUnreadCount(boxB.mId)); 1499 assertEquals(1, getUnreadCount(boxC.mId)); 1500 1501 // Mark message 3 (from box A) read, leaving 0 in box A 1502 cv.clear(); 1503 cv.put(MessageColumns.FLAG_READ, 1); 1504 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message3.mId), cv, null, null); 1505 assertEquals(0, getUnreadCount(boxA.mId)); 1506 assertEquals(1, getUnreadCount(boxB.mId)); 1507 assertEquals(1, getUnreadCount(boxC.mId)); 1508 1509 // Move message 3 to box C; should be no change (it's read) 1510 message3.mMailboxKey = boxC.mId; 1511 cv.clear(); 1512 cv.put(MessageColumns.MAILBOX_KEY, boxC.mId); 1513 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message3.mId), cv, null, null); 1514 assertEquals(0, getUnreadCount(boxA.mId)); 1515 assertEquals(1, getUnreadCount(boxB.mId)); 1516 assertEquals(1, getUnreadCount(boxC.mId)); 1517 1518 // Mark message 3 unread; it's now in box C, so that box's count should go up to 3 1519 cv.clear(); 1520 cv.put(MessageColumns.FLAG_READ, 0); 1521 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message3.mId), cv, null, null); 1522 assertEquals(0, getUnreadCount(boxA.mId)); 1523 assertEquals(1, getUnreadCount(boxB.mId)); 1524 assertEquals(2, getUnreadCount(boxC.mId)); 1525 } 1526 1527 /** 1528 * Test for EmailProvider.createIndex(). 1529 * Check that it returns exacly the same string as the one used previously for index creation. 1530 */ 1531 public void testCreateIndex() { 1532 String oldStr = "create index message_" + MessageColumns.TIMESTAMP 1533 + " on " + Message.TABLE_NAME + " (" + MessageColumns.TIMESTAMP + ");"; 1534 String newStr = EmailProvider.createIndex(Message.TABLE_NAME, MessageColumns.TIMESTAMP); 1535 assertEquals(newStr, oldStr); 1536 } 1537 1538 public void testIdAddToField() { 1539 ContentResolver cr = mMockContext.getContentResolver(); 1540 ContentValues cv = new ContentValues(); 1541 1542 // Try changing the newMessageCount of an account 1543 Account account = ProviderTestUtils.setupAccount("field-add", true, mMockContext); 1544 int startCount = account.mNewMessageCount; 1545 // "field" and "add" are the two required elements 1546 cv.put(EmailContent.FIELD_COLUMN_NAME, AccountColumns.NEW_MESSAGE_COUNT); 1547 cv.put(EmailContent.ADD_COLUMN_NAME, 17); 1548 cr.update(ContentUris.withAppendedId(Account.ADD_TO_FIELD_URI, account.mId), 1549 cv, null, null); 1550 Account restoredAccount = Account.restoreAccountWithId(mMockContext, account.mId); 1551 assertEquals(17 + startCount, restoredAccount.mNewMessageCount); 1552 cv.put(EmailContent.ADD_COLUMN_NAME, -11); 1553 cr.update(ContentUris.withAppendedId(Account.ADD_TO_FIELD_URI, account.mId), 1554 cv, null, null); 1555 restoredAccount = Account.restoreAccountWithId(mMockContext, account.mId); 1556 assertEquals(17 - 11 + startCount, restoredAccount.mNewMessageCount); 1557 1558 // Now try with a mailbox 1559 Mailbox boxA = ProviderTestUtils.setupMailbox("boxA", account.mId, true, mMockContext); 1560 assertEquals(0, boxA.mUnreadCount); 1561 cv.put(EmailContent.FIELD_COLUMN_NAME, MailboxColumns.UNREAD_COUNT); 1562 cv.put(EmailContent.ADD_COLUMN_NAME, 11); 1563 cr.update(ContentUris.withAppendedId(Mailbox.ADD_TO_FIELD_URI, boxA.mId), cv, null, null); 1564 Mailbox restoredBoxA = Mailbox.restoreMailboxWithId(mMockContext, boxA.mId); 1565 assertEquals(11, restoredBoxA.mUnreadCount); 1566 } 1567 1568 public void testDatabaseCorruptionRecovery() { 1569 final ContentResolver resolver = mMockContext.getContentResolver(); 1570 final Context context = mMockContext; 1571 1572 // Create account and two mailboxes 1573 Account acct = ProviderTestUtils.setupAccount("acct1", true, context); 1574 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", acct.mId, true, context); 1575 1576 // Create 4 messages in box1 with bodies 1577 ProviderTestUtils.setupMessage("message1", acct.mId, box1.mId, true, true, context); 1578 ProviderTestUtils.setupMessage("message2", acct.mId, box1.mId, true, true, context); 1579 ProviderTestUtils.setupMessage("message3", acct.mId, box1.mId, true, true, context); 1580 ProviderTestUtils.setupMessage("message4", acct.mId, box1.mId, true, true, context); 1581 1582 // Confirm there are four messages 1583 int count = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 1584 assertEquals(4, count); 1585 // Confirm there are four bodies 1586 count = EmailContent.count(mMockContext, Body.CONTENT_URI, null, null); 1587 assertEquals(4, count); 1588 1589 // Find the EmailProvider.db file 1590 File dbFile = mMockContext.getDatabasePath(EmailProvider.DATABASE_NAME); 1591 // The EmailProvider.db database should exist (the provider creates it automatically) 1592 assertTrue(dbFile != null); 1593 assertTrue(dbFile.exists()); 1594 // Delete it, and confirm it is gone 1595 assertTrue(dbFile.delete()); 1596 assertFalse(dbFile.exists()); 1597 1598 // Find the EmailProviderBody.db file 1599 dbFile = mMockContext.getDatabasePath(EmailProvider.BODY_DATABASE_NAME); 1600 // The EmailProviderBody.db database should still exist 1601 assertTrue(dbFile != null); 1602 assertTrue(dbFile.exists()); 1603 1604 // URI to uncache the databases 1605 // This simulates the Provider starting up again (otherwise, it will still be pointing to 1606 // the already opened files) 1607 // Note that we only have access to the EmailProvider via the ContentResolver; therefore, 1608 // we cannot directly call into the provider and use a URI for this 1609 resolver.update(EmailProvider.INTEGRITY_CHECK_URI, null, null, null); 1610 1611 // TODO We should check for the deletion of attachment files once this is implemented in 1612 // the provider 1613 1614 // Explanation for what happens below... 1615 // The next time the database is created by the provider, it will notice that there's 1616 // already a EmailProviderBody.db file. In this case, it will delete that database to 1617 // ensure that both are in sync (and empty) 1618 1619 // Confirm there are no bodies 1620 count = EmailContent.count(mMockContext, Body.CONTENT_URI, null, null); 1621 assertEquals(0, count); 1622 1623 // Confirm there are no messages 1624 count = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 1625 assertEquals(0, count); 1626 } 1627 1628 public void testBodyDatabaseCorruptionRecovery() { 1629 final ContentResolver resolver = mMockContext.getContentResolver(); 1630 final Context context = mMockContext; 1631 1632 // Create account and two mailboxes 1633 Account acct = ProviderTestUtils.setupAccount("acct1", true, context); 1634 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", acct.mId, true, context); 1635 1636 // Create 4 messages in box1 with bodies 1637 ProviderTestUtils.setupMessage("message1", acct.mId, box1.mId, true, true, context); 1638 ProviderTestUtils.setupMessage("message2", acct.mId, box1.mId, true, true, context); 1639 ProviderTestUtils.setupMessage("message3", acct.mId, box1.mId, true, true, context); 1640 ProviderTestUtils.setupMessage("message4", acct.mId, box1.mId, true, true, context); 1641 1642 // Confirm there are four messages 1643 int count = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 1644 assertEquals(4, count); 1645 // Confirm there are four bodies 1646 count = EmailContent.count(mMockContext, Body.CONTENT_URI, null, null); 1647 assertEquals(4, count); 1648 1649 // Find the EmailProviderBody.db file 1650 File dbFile = mMockContext.getDatabasePath(EmailProvider.BODY_DATABASE_NAME); 1651 // The EmailProviderBody.db database should exist (the provider creates it automatically) 1652 assertTrue(dbFile != null); 1653 assertTrue(dbFile.exists()); 1654 // Delete it, and confirm it is gone 1655 assertTrue(dbFile.delete()); 1656 assertFalse(dbFile.exists()); 1657 1658 // Find the EmailProvider.db file 1659 dbFile = mMockContext.getDatabasePath(EmailProvider.DATABASE_NAME); 1660 // The EmailProviderBody.db database should still exist 1661 assertTrue(dbFile != null); 1662 assertTrue(dbFile.exists()); 1663 1664 // URI to uncache the databases 1665 // This simulates the Provider starting up again (otherwise, it will still be pointing to 1666 // the already opened files) 1667 // Note that we only have access to the EmailProvider via the ContentResolver; therefore, 1668 // we cannot directly call into the provider and use a URI for this 1669 resolver.update(EmailProvider.INTEGRITY_CHECK_URI, null, null, null); 1670 1671 // TODO We should check for the deletion of attachment files once this is implemented in 1672 // the provider 1673 1674 // Explanation for what happens below... 1675 // The next time the body database is created by the provider, it will notice that there's 1676 // already a populated EmailProvider.db file. In this case, it will delete that database to 1677 // ensure that both are in sync (and empty) 1678 1679 // Confirm there are no messages 1680 count = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 1681 assertEquals(0, count); 1682 1683 // Confirm there are no bodies 1684 count = EmailContent.count(mMockContext, Body.CONTENT_URI, null, null); 1685 assertEquals(0, count); 1686 } 1687 1688 public void testFindMailboxOfType() { 1689 final Context context = mMockContext; 1690 1691 // Create two accounts and a variety of mailbox types 1692 Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context); 1693 Mailbox acct1Inbox = 1694 ProviderTestUtils.setupMailbox("Inbox1", acct1.mId, true, context, Mailbox.TYPE_INBOX); 1695 Mailbox acct1Calendar 1696 = ProviderTestUtils.setupMailbox("Cal1", acct1.mId, true, context, Mailbox.TYPE_CALENDAR); 1697 Mailbox acct1Contacts = 1698 ProviderTestUtils.setupMailbox("Con1", acct1.mId, true, context, Mailbox.TYPE_CONTACTS); 1699 Account acct2 = ProviderTestUtils.setupAccount("acct1", true, context); 1700 Mailbox acct2Inbox = 1701 ProviderTestUtils.setupMailbox("Inbox2", acct2.mId, true, context, Mailbox.TYPE_INBOX); 1702 Mailbox acct2Calendar = 1703 ProviderTestUtils.setupMailbox("Cal2", acct2.mId, true, context, Mailbox.TYPE_CALENDAR); 1704 Mailbox acct2Contacts = 1705 ProviderTestUtils.setupMailbox("Con2", acct2.mId, true, context, Mailbox.TYPE_CONTACTS); 1706 1707 // Check that we can find them by type 1708 assertEquals(acct1Inbox.mId, 1709 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX)); 1710 assertEquals(acct2Inbox.mId, 1711 Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_INBOX)); 1712 assertEquals(acct1Calendar.mId, 1713 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR)); 1714 assertEquals(acct2Calendar.mId, 1715 Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_CALENDAR)); 1716 assertEquals(acct1Contacts.mId, 1717 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS)); 1718 assertEquals(acct2Contacts.mId, 1719 Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_CONTACTS)); 1720 } 1721 1722 public void testRestoreMailboxOfType() { 1723 final Context context = mMockContext; 1724 1725 // Create two accounts and a variety of mailbox types 1726 Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context); 1727 Mailbox acct1Inbox = 1728 ProviderTestUtils.setupMailbox("Inbox1", acct1.mId, true, context, Mailbox.TYPE_INBOX); 1729 Mailbox acct1Calendar 1730 = ProviderTestUtils.setupMailbox("Cal1", acct1.mId, true, context, Mailbox.TYPE_CALENDAR); 1731 Mailbox acct1Contacts = 1732 ProviderTestUtils.setupMailbox("Con1", acct1.mId, true, context, Mailbox.TYPE_CONTACTS); 1733 Account acct2 = ProviderTestUtils.setupAccount("acct1", true, context); 1734 Mailbox acct2Inbox = 1735 ProviderTestUtils.setupMailbox("Inbox2", acct2.mId, true, context, Mailbox.TYPE_INBOX); 1736 Mailbox acct2Calendar = 1737 ProviderTestUtils.setupMailbox("Cal2", acct2.mId, true, context, Mailbox.TYPE_CALENDAR); 1738 Mailbox acct2Contacts = 1739 ProviderTestUtils.setupMailbox("Con2", acct2.mId, true, context, Mailbox.TYPE_CONTACTS); 1740 1741 // Check that we can find them by type 1742 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Inbox, 1743 Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX)); 1744 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Inbox, 1745 Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_INBOX)); 1746 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Calendar, 1747 Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR)); 1748 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Calendar, 1749 Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_CALENDAR)); 1750 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Contacts, 1751 Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS)); 1752 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Contacts, 1753 Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_CONTACTS)); 1754 } 1755 } 1756