ProviderTests.java revision 040ddf60cfef4aaecf4bfe1f897fce3248d777a4
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.emailcommon.mail.Snippet; 20import com.android.emailcommon.provider.EmailContent; 21import com.android.emailcommon.provider.EmailContent.Account; 22import com.android.emailcommon.provider.EmailContent.AccountColumns; 23import com.android.emailcommon.provider.EmailContent.Attachment; 24import com.android.emailcommon.provider.EmailContent.AttachmentColumns; 25import com.android.emailcommon.provider.EmailContent.Body; 26import com.android.emailcommon.provider.EmailContent.BodyColumns; 27import com.android.emailcommon.provider.EmailContent.HostAuth; 28import com.android.emailcommon.provider.EmailContent.Mailbox; 29import com.android.emailcommon.provider.EmailContent.MailboxColumns; 30import com.android.emailcommon.provider.EmailContent.Message; 31import com.android.emailcommon.provider.EmailContent.MessageColumns; 32import com.android.emailcommon.utility.Utility; 33 34import android.content.ContentResolver; 35import android.content.ContentUris; 36import android.content.ContentValues; 37import android.content.Context; 38import android.database.Cursor; 39import android.database.sqlite.SQLiteDatabase; 40import android.net.Uri; 41import android.os.Bundle; 42import android.os.Environment; 43import android.os.Parcel; 44import android.test.MoreAsserts; 45import android.test.ProviderTestCase2; 46 47import java.io.File; 48import java.io.IOException; 49import java.net.URISyntaxException; 50import java.util.ArrayList; 51 52/** 53 * Tests of the Email provider. 54 * 55 * You can run this entire test case with: 56 * runtest -c com.android.email.provider.ProviderTests email 57 * 58 * TODO: Add tests for cursor notification mechanism. (setNotificationUri and notifyChange) 59 * We can't test the entire notification mechanism with a mock content resolver, because which URI 60 * to notify when notifyChange() is called is in the actual content resolver. 61 * Implementing the same mechanism in a mock one is pointless. Instead what we could do is check 62 * what notification URI each cursor has, and with which URI is notified when 63 * inserting/updating/deleting. (The former require a new method from AbstractCursor) 64 */ 65public class ProviderTests extends ProviderTestCase2<EmailProvider> { 66 67 private EmailProvider mProvider; 68 private Context mMockContext; 69 70 public ProviderTests() { 71 super(EmailProvider.class, EmailContent.AUTHORITY); 72 } 73 74 @Override 75 public void setUp() throws Exception { 76 super.setUp(); 77 mMockContext = getMockContext(); 78 mProvider = getProvider(); 79 // Invalidate all caches, since we reset the database for each test 80 ContentCache.invalidateAllCachesForTest(); 81 } 82 83 @Override 84 public void tearDown() throws Exception { 85 super.tearDown(); 86 } 87 88 /** 89 * TODO: Database upgrade tests 90 */ 91 92 /** 93 * Test simple account save/retrieve 94 */ 95 public void testAccountSave() { 96 Account account1 = ProviderTestUtils.setupAccount("account-save", true, mMockContext); 97 long account1Id = account1.mId; 98 99 Account account2 = EmailContent.Account.restoreAccountWithId(mMockContext, account1Id); 100 101 ProviderTestUtils.assertAccountEqual("testAccountSave", account1, account2); 102 } 103 104 /** 105 * Test simple account save/retrieve with predefined hostauth records 106 */ 107 public void testAccountSaveHostAuth() { 108 Account account1 = ProviderTestUtils.setupAccount("account-hostauth", false, mMockContext); 109 // add hostauth data, which should be saved the first time 110 account1.mHostAuthRecv = ProviderTestUtils.setupHostAuth("account-hostauth-recv", -1, false, 111 mMockContext); 112 account1.mHostAuthSend = ProviderTestUtils.setupHostAuth("account-hostauth-send", -1, false, 113 mMockContext); 114 account1.save(mMockContext); 115 long account1Id = account1.mId; 116 117 // Confirm account reads back correctly 118 Account account1get = EmailContent.Account.restoreAccountWithId(mMockContext, account1Id); 119 ProviderTestUtils.assertAccountEqual("testAccountSave", account1, account1get); 120 121 // Confirm hostauth fields can be accessed & read back correctly 122 HostAuth hostAuth1get = EmailContent.HostAuth.restoreHostAuthWithId(mMockContext, 123 account1get.mHostAuthKeyRecv); 124 ProviderTestUtils.assertHostAuthEqual("testAccountSaveHostAuth-recv", 125 account1.mHostAuthRecv, hostAuth1get); 126 HostAuth hostAuth2get = EmailContent.HostAuth.restoreHostAuthWithId(mMockContext, 127 account1get.mHostAuthKeySend); 128 ProviderTestUtils.assertHostAuthEqual("testAccountSaveHostAuth-send", 129 account1.mHostAuthSend, hostAuth2get); 130 } 131 132 public void testAccountGetHostAuthSend() { 133 Account account = ProviderTestUtils.setupAccount("account-hostauth", false, mMockContext); 134 account.mHostAuthSend = ProviderTestUtils.setupHostAuth("account-hostauth-send", -1, false, 135 mMockContext); 136 account.save(mMockContext); 137 HostAuth authGet; 138 HostAuth authTest; 139 140 authTest = account.mHostAuthSend; 141 assertNotNull(authTest); 142 assertTrue(account.mHostAuthKeySend != 0); 143 144 // HostAuth is not changed 145 authGet = account.getOrCreateHostAuthSend(mMockContext); 146 assertTrue(authGet == authTest); // return the same object 147 148 // New HostAuth; based upon mHostAuthKeyRecv 149 authTest = EmailContent.HostAuth.restoreHostAuthWithId(mMockContext, 150 account.mHostAuthKeySend); 151 account.mHostAuthSend = null; 152 authGet = account.getOrCreateHostAuthSend(mMockContext); 153 assertNotNull(authGet); 154 assertNotNull(account.mHostAuthSend); 155 ProviderTestUtils.assertHostAuthEqual("testAccountGetHostAuthSend-1", authTest, authGet); 156 157 // New HostAuth; completely empty 158 authTest = new EmailContent.HostAuth(); 159 account.mHostAuthSend = null; 160 account.mHostAuthKeySend = 0; 161 authGet = account.getOrCreateHostAuthSend(mMockContext); 162 assertNotNull(authGet); 163 assertNotNull(account.mHostAuthSend); 164 ProviderTestUtils.assertHostAuthEqual("testAccountGetHostAuthSendv-2", authTest, authGet); 165 } 166 167 public void testAccountGetHostAuthRecv() { 168 Account account = ProviderTestUtils.setupAccount("account-hostauth", false, mMockContext); 169 account.mHostAuthRecv = ProviderTestUtils.setupHostAuth("account-hostauth-recv", -1, false, 170 mMockContext); 171 account.save(mMockContext); 172 HostAuth authGet; 173 HostAuth authTest; 174 175 authTest = account.mHostAuthRecv; 176 assertNotNull(authTest); 177 assertTrue(account.mHostAuthKeyRecv != 0); 178 179 // HostAuth is not changed 180 authGet = account.getOrCreateHostAuthRecv(mMockContext); 181 assertTrue(authGet == authTest); // return the same object 182 183 // New HostAuth; based upon mHostAuthKeyRecv 184 authTest = EmailContent.HostAuth.restoreHostAuthWithId(mMockContext, 185 account.mHostAuthKeyRecv); 186 account.mHostAuthRecv = null; 187 authGet = account.getOrCreateHostAuthRecv(mMockContext); 188 assertNotNull(authGet); 189 assertNotNull(account.mHostAuthRecv); 190 ProviderTestUtils.assertHostAuthEqual("testAccountGetHostAuthRecv-1", authTest, authGet); 191 192 // New HostAuth; completely empty 193 authTest = new EmailContent.HostAuth(); 194 account.mHostAuthRecv = null; 195 account.mHostAuthKeyRecv = 0; 196 authGet = account.getOrCreateHostAuthRecv(mMockContext); 197 assertNotNull(authGet); 198 assertNotNull(account.mHostAuthRecv); 199 ProviderTestUtils.assertHostAuthEqual("testAccountGetHostAuthRecv-2", authTest, authGet); 200 } 201 202 /** 203 * Simple test of account parceling. The rather torturous path is to ensure that the 204 * account is really flattened all the way down to a parcel and back. 205 */ 206 public void testAccountParcel() { 207 Account account1 = ProviderTestUtils.setupAccount("parcel", false, mMockContext); 208 Bundle b = new Bundle(); 209 b.putParcelable("account", account1); 210 Parcel p = Parcel.obtain(); 211 b.writeToParcel(p, 0); 212 p.setDataPosition(0); // rewind it for reading 213 Bundle b2 = new Bundle(Account.class.getClassLoader()); 214 b2.readFromParcel(p); 215 Account account2 = (Account) b2.getParcelable("account"); 216 p.recycle(); 217 218 ProviderTestUtils.assertAccountEqual("testAccountParcel", account1, account2); 219 } 220 221 /** 222 * Test for {@link Account#getShortcutSafeUri()} and 223 * {@link Account#getAccountIdFromShortcutSafeUri}. 224 */ 225 public void testAccountShortcutSafeUri() { 226 final Account account1 = ProviderTestUtils.setupAccount("account-1", true, mMockContext); 227 final Account account2 = ProviderTestUtils.setupAccount("account-2", true, mMockContext); 228 final long account1Id = account1.mId; 229 final long account2Id = account2.mId; 230 231 final Uri uri1 = account1.getShortcutSafeUri(); 232 final Uri uri2 = account2.getShortcutSafeUri(); 233 234 // Check the path part of the URIs. 235 MoreAsserts.assertEquals(new String[] {"account", account1.mCompatibilityUuid}, 236 uri1.getPathSegments().toArray()); 237 MoreAsserts.assertEquals(new String[] {"account", account2.mCompatibilityUuid}, 238 uri2.getPathSegments().toArray()); 239 240 assertEquals(account1Id, Account.getAccountIdFromShortcutSafeUri(mMockContext, uri1)); 241 assertEquals(account2Id, Account.getAccountIdFromShortcutSafeUri(mMockContext, uri2)); 242 243 // Test for the Eclair(2.0-2.1) style URI. 244 assertEquals(account1Id, Account.getAccountIdFromShortcutSafeUri(mMockContext, 245 getEclairStyleShortcutUri(account1))); 246 assertEquals(account2Id, Account.getAccountIdFromShortcutSafeUri(mMockContext, 247 getEclairStyleShortcutUri(account2))); 248 } 249 250 private static Uri getEclairStyleShortcutUri(Account account) { 251 // We used _id instead of UUID only on Eclair(2.0-2.1). 252 return Account.CONTENT_URI.buildUpon().appendEncodedPath("" + account.mId).build(); 253 } 254 255 public void testGetProtocol() { 256 Account account1 = ProviderTestUtils.setupAccount("account-hostauth", false, mMockContext); 257 // add hostauth data, with protocol 258 account1.mHostAuthRecv = ProviderTestUtils.setupHostAuth("eas", "account-hostauth-recv", -1, 259 false, mMockContext); 260 // Note that getProtocol uses the receive host auth, so the protocol here shouldn't matter 261 // to the test result 262 account1.mHostAuthSend = ProviderTestUtils.setupHostAuth("foo", "account-hostauth-send", -1, 263 false, mMockContext); 264 account1.save(mMockContext); 265 assertEquals("eas", Account.getProtocol(mMockContext, account1.mId)); 266 assertEquals("eas", account1.getProtocol(mMockContext)); 267 Account account2 = ProviderTestUtils.setupAccount("account-nohostauth", false, 268 mMockContext); 269 account2.save(mMockContext); 270 // Make sure that we return null when there's no host auth 271 assertNull(Account.getProtocol(mMockContext, account2.mId)); 272 assertNull(account2.getProtocol(mMockContext)); 273 // And when there's no account 274 assertNull(Account.getProtocol(mMockContext, 0)); 275 } 276 277 public void testAccountIsValidId() { 278 final Account account1 = ProviderTestUtils.setupAccount("account-1", true, mMockContext); 279 final Account account2 = ProviderTestUtils.setupAccount("account-2", true, mMockContext); 280 281 assertTrue(Account.isValidId(mMockContext, account1.mId)); 282 assertTrue(Account.isValidId(mMockContext, account2.mId)); 283 284 assertFalse(Account.isValidId(mMockContext, 1234567)); // Some random ID 285 assertFalse(Account.isValidId(mMockContext, -1)); 286 assertFalse(Account.isValidId(mMockContext, -500)); 287 } 288 289 private final static String[] MAILBOX_UNREAD_COUNT_PROJECTION = new String [] { 290 MailboxColumns.UNREAD_COUNT 291 }; 292 private final static int MAILBOX_UNREAD_COUNT_COLMUN = 0; 293 294 /** 295 * Get the value of the unread count in the mailbox of the account. 296 * This can be different from the actual number of unread messages in that mailbox. 297 */ 298 private int getUnreadCount(long mailboxId) { 299 String text = null; 300 Cursor c = null; 301 try { 302 c = mMockContext.getContentResolver().query( 303 Mailbox.CONTENT_URI, 304 MAILBOX_UNREAD_COUNT_PROJECTION, 305 EmailContent.RECORD_ID + "=?", 306 new String[] { String.valueOf(mailboxId) }, 307 null); 308 c.moveToFirst(); 309 text = c.getString(MAILBOX_UNREAD_COUNT_COLMUN); 310 } finally { 311 c.close(); 312 } 313 return Integer.valueOf(text); 314 } 315 316 /** 317 * TODO: HostAuth tests 318 */ 319 320 /** 321 * Test the various combinations of SSL, TLS, and trust-certificates encoded as Uris 322 */ 323 public void testHostAuthSecurityUri() 324 throws URISyntaxException { 325 HostAuth ha = ProviderTestUtils.setupHostAuth("uri-security", 1, false, mMockContext); 326 327 final int MASK = 328 HostAuth.FLAG_SSL | HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL; 329 330 // Set various URIs and check the resulting flags 331 Utility.setHostAuthFromString(ha, "protocol://user:password@server:123"); 332 assertEquals(0, ha.mFlags & MASK); 333 Utility.setHostAuthFromString(ha, "protocol+ssl+://user:password@server:123"); 334 assertEquals(HostAuth.FLAG_SSL, ha.mFlags & MASK); 335 Utility.setHostAuthFromString(ha, "protocol+ssl+trustallcerts://user:password@server:123"); 336 assertEquals(HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL, ha.mFlags & MASK); 337 Utility.setHostAuthFromString(ha, "protocol+tls+://user:password@server:123"); 338 assertEquals(HostAuth.FLAG_TLS, ha.mFlags & MASK); 339 Utility.setHostAuthFromString(ha, "protocol+tls+trustallcerts://user:password@server:123"); 340 assertEquals(HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL, ha.mFlags & MASK); 341 342 // Now check the retrival method (building URI from flags) 343 ha.mFlags &= ~MASK; 344 String uriString = ha.getStoreUri(); 345 assertTrue(uriString.startsWith("protocol://")); 346 ha.mFlags |= HostAuth.FLAG_SSL; 347 uriString = ha.getStoreUri(); 348 assertTrue(uriString.startsWith("protocol+ssl+://")); 349 ha.mFlags |= HostAuth.FLAG_TRUST_ALL; 350 uriString = ha.getStoreUri(); 351 assertTrue(uriString.startsWith("protocol+ssl+trustallcerts://")); 352 ha.mFlags &= ~MASK; 353 ha.mFlags |= HostAuth.FLAG_TLS; 354 uriString = ha.getStoreUri(); 355 assertTrue(uriString.startsWith("protocol+tls+://")); 356 ha.mFlags |= HostAuth.FLAG_TRUST_ALL; 357 uriString = ha.getStoreUri(); 358 assertTrue(uriString.startsWith("protocol+tls+trustallcerts://")); 359 } 360 361 /** 362 * Test port assignments made from Uris 363 */ 364 public void testHostAuthPortAssignments() 365 throws URISyntaxException { 366 HostAuth ha = ProviderTestUtils.setupHostAuth("uri-port", 1, false, mMockContext); 367 368 // Set various URIs and check the resulting flags 369 // Hardwired port 370 Utility.setHostAuthFromString(ha, "imap://user:password@server:123"); 371 assertEquals(123, ha.mPort); 372 // Auto-assigned ports 373 Utility.setHostAuthFromString(ha, "imap://user:password@server"); 374 assertEquals(143, ha.mPort); 375 Utility.setHostAuthFromString(ha, "imap+ssl://user:password@server"); 376 assertEquals(993, ha.mPort); 377 Utility.setHostAuthFromString(ha, "imap+ssl+trustallcerts://user:password@server"); 378 assertEquals(993, ha.mPort); 379 Utility.setHostAuthFromString(ha, "imap+tls://user:password@server"); 380 assertEquals(143, ha.mPort); 381 Utility.setHostAuthFromString(ha, "imap+tls+trustallcerts://user:password@server"); 382 assertEquals(143, ha.mPort); 383 384 // Hardwired port 385 Utility.setHostAuthFromString(ha, "pop3://user:password@server:123"); 386 assertEquals(123, ha.mPort); 387 // Auto-assigned ports 388 Utility.setHostAuthFromString(ha, "pop3://user:password@server"); 389 assertEquals(110, ha.mPort); 390 Utility.setHostAuthFromString(ha, "pop3+ssl://user:password@server"); 391 assertEquals(995, ha.mPort); 392 Utility.setHostAuthFromString(ha, "pop3+ssl+trustallcerts://user:password@server"); 393 assertEquals(995, ha.mPort); 394 Utility.setHostAuthFromString(ha, "pop3+tls://user:password@server"); 395 assertEquals(110, ha.mPort); 396 Utility.setHostAuthFromString(ha, "pop3+tls+trustallcerts://user:password@server"); 397 assertEquals(110, ha.mPort); 398 399 // Hardwired port 400 Utility.setHostAuthFromString(ha, "eas://user:password@server:123"); 401 assertEquals(123, ha.mPort); 402 // Auto-assigned ports 403 Utility.setHostAuthFromString(ha, "eas://user:password@server"); 404 assertEquals(80, ha.mPort); 405 Utility.setHostAuthFromString(ha, "eas+ssl://user:password@server"); 406 assertEquals(443, ha.mPort); 407 Utility.setHostAuthFromString(ha, "eas+ssl+trustallcerts://user:password@server"); 408 assertEquals(443, ha.mPort); 409 410 // Hardwired port 411 Utility.setHostAuthFromString(ha, "smtp://user:password@server:123"); 412 assertEquals(123, ha.mPort); 413 // Auto-assigned ports 414 Utility.setHostAuthFromString(ha, "smtp://user:password@server"); 415 assertEquals(587, ha.mPort); 416 Utility.setHostAuthFromString(ha, "smtp+ssl://user:password@server"); 417 assertEquals(465, ha.mPort); 418 Utility.setHostAuthFromString(ha, "smtp+ssl+trustallcerts://user:password@server"); 419 assertEquals(465, ha.mPort); 420 Utility.setHostAuthFromString(ha, "smtp+tls://user:password@server"); 421 assertEquals(587, ha.mPort); 422 Utility.setHostAuthFromString(ha, "smtp+tls+trustallcerts://user:password@server"); 423 assertEquals(587, ha.mPort); 424 } 425 426 /** 427 * Test preservation of username & password in URI 428 */ 429 public void testHostAuthUri() 430 throws URISyntaxException { 431 HostAuth ha = new HostAuth(); 432 Utility.setHostAuthFromString(ha, "protocol://user:password@server:123"); 433 String getUri = ha.getStoreUri(); 434 assertEquals("protocol://user:password@server:123", getUri); 435 436 // Now put spaces in/around username (they are trimmed) 437 Utility.setHostAuthFromString(ha, "protocol://%20us%20er%20:password@server:123"); 438 getUri = ha.getStoreUri(); 439 assertEquals("protocol://us%20er:password@server:123", getUri); 440 441 // Now put spaces around password (should not be trimmed) 442 Utility.setHostAuthFromString(ha, "protocol://user:%20pass%20word%20@server:123"); 443 getUri = ha.getStoreUri(); 444 assertEquals("protocol://user:%20pass%20word%20@server:123", getUri); 445 } 446 447 /** 448 * Test user name and password are set correctly 449 */ 450 public void testHostAuthSetLogin() { 451 HostAuth ha = new HostAuth(); 452 ha.setLogin("user:password"); 453 assertEquals("user", ha.mLogin); 454 assertEquals("password", ha.mPassword); 455 456 // special characters are not removed during insertion 457 ha.setLogin("%20us%20er%20:password"); 458 assertEquals("%20us%20er%20", ha.mLogin); 459 assertEquals("password", ha.mPassword); 460 461 // special characters are not removed during insertion 462 ha.setLogin("user:%20pass%20word%20"); 463 assertEquals("user", ha.mLogin); 464 assertEquals("%20pass%20word%20", ha.mPassword); 465 466 ha.setLogin("user:"); 467 assertEquals("user", ha.mLogin); 468 assertEquals("", ha.mPassword); 469 470 ha.setLogin(":password"); 471 assertEquals("", ha.mLogin); 472 assertEquals("password", ha.mPassword); 473 474 ha.setLogin(""); 475 assertNull(ha.mLogin); 476 assertNull(ha.mPassword); 477 478 ha.setLogin(null); 479 assertNull(ha.mLogin); 480 assertNull(ha.mPassword); 481 482 ha.setLogin("userpassword"); 483 assertEquals("userpassword", ha.mLogin); 484 assertNull(ha.mPassword); 485 } 486 487 /** 488 * Test the authentication flag is set correctly when setting user name and password 489 */ 490 public void testHostAuthSetLoginAuthenticate() { 491 HostAuth ha = new HostAuth(); 492 493 ha.mFlags = 0x00000000; 494 ha.setLogin("user", "password"); 495 assertEquals(HostAuth.FLAG_AUTHENTICATE, ha.mFlags); 496 497 ha.mFlags = 0x00000000; 498 ha.setLogin("user", ""); 499 assertEquals(HostAuth.FLAG_AUTHENTICATE, ha.mFlags); 500 501 ha.mFlags = 0x00000000; 502 ha.setLogin("", "password"); 503 assertEquals(HostAuth.FLAG_AUTHENTICATE, ha.mFlags); 504 505 ha.mFlags = 0x00000000; 506 ha.setLogin("user", null); 507 assertEquals(HostAuth.FLAG_AUTHENTICATE, ha.mFlags); 508 509 ha.mFlags = 0xffffffff; 510 ha.setLogin(null, "password"); 511 assertEquals(~HostAuth.FLAG_AUTHENTICATE, ha.mFlags); 512 513 ha.mFlags = 0xffffffff; 514 ha.setLogin(null, null); 515 assertEquals(~HostAuth.FLAG_AUTHENTICATE, ha.mFlags); 516 } 517 518 /** 519 * Test setting the connection using a URI scheme 520 */ 521 public void testHostAuthSetConnectionScheme() { 522 HostAuth ha = new HostAuth(); 523 524 // Set URIs for IMAP 525 // Hardwired port 526 ha.setConnection("imap", "server", 123); 527 assertEquals(0, ha.mFlags); 528 assertEquals(123, ha.mPort); 529 530 // Auto-assigned ports 531 ha.setConnection("imap", "server", -1); 532 assertEquals(0, ha.mFlags); 533 assertEquals(143, ha.mPort); 534 535 ha.setConnection("imap+ssl", "server", -1); 536 assertEquals(HostAuth.FLAG_SSL, ha.mFlags); 537 assertEquals(993, ha.mPort); 538 539 ha.setConnection("imap+ssl+trustallcerts", "server", -1); 540 assertEquals(HostAuth.FLAG_SSL|HostAuth.FLAG_TRUST_ALL, ha.mFlags); 541 assertEquals(993, ha.mPort); 542 543 ha.setConnection("imap+tls", "server", -1); 544 assertEquals(HostAuth.FLAG_TLS, ha.mFlags); 545 assertEquals(143, ha.mPort); 546 547 ha.setConnection("imap+tls+trustallcerts", "server", -1); 548 assertEquals(HostAuth.FLAG_TLS|HostAuth.FLAG_TRUST_ALL, ha.mFlags); 549 assertEquals(143, ha.mPort); 550 551 // Set URIs for POP3 552 // Hardwired port 553 ha.setConnection("pop3", "server", 123); 554 assertEquals(0, ha.mFlags); 555 assertEquals(123, ha.mPort); 556 557 // Auto-assigned ports 558 ha.setConnection("pop3", "server", -1); 559 assertEquals(0, ha.mFlags); 560 assertEquals(110, ha.mPort); 561 562 ha.setConnection("pop3+ssl", "server", -1); 563 assertEquals(HostAuth.FLAG_SSL, ha.mFlags); 564 assertEquals(995, ha.mPort); 565 566 ha.setConnection("pop3+ssl+trustallcerts", "server", -1); 567 assertEquals(HostAuth.FLAG_SSL|HostAuth.FLAG_TRUST_ALL, ha.mFlags); 568 assertEquals(995, ha.mPort); 569 570 ha.setConnection("pop3+tls", "server", -1); 571 assertEquals(HostAuth.FLAG_TLS, ha.mFlags); 572 assertEquals(110, ha.mPort); 573 574 ha.setConnection("pop3+tls+trustallcerts", "server", -1); 575 assertEquals(HostAuth.FLAG_TLS|HostAuth.FLAG_TRUST_ALL, ha.mFlags); 576 assertEquals(110, ha.mPort); 577 578 // Set URIs for Exchange 579 // Hardwired port 580 ha.setConnection("eas", "server", 123); 581 assertEquals(0, ha.mFlags); 582 assertEquals(123, ha.mPort); 583 584 // Auto-assigned ports 585 ha.setConnection("eas", "server", -1); 586 assertEquals(0, ha.mFlags); 587 assertEquals(80, ha.mPort); 588 589 ha.setConnection("eas+ssl", "server", -1); 590 assertEquals(HostAuth.FLAG_SSL, ha.mFlags); 591 assertEquals(443, ha.mPort); 592 593 ha.setConnection("eas+ssl+trustallcerts", "server", -1); 594 assertEquals(HostAuth.FLAG_SSL|HostAuth.FLAG_TRUST_ALL, ha.mFlags); 595 assertEquals(443, ha.mPort); 596 597 // Set URIs for SMTP 598 // Hardwired port 599 ha.setConnection("smtp", "server", 123); 600 assertEquals(0, ha.mFlags); 601 assertEquals(123, ha.mPort); 602 603 // Auto-assigned ports 604 ha.setConnection("smtp", "server", -1); 605 assertEquals(0, ha.mFlags); 606 assertEquals(587, ha.mPort); 607 608 ha.setConnection("smtp+ssl", "server", -1); 609 assertEquals(HostAuth.FLAG_SSL, ha.mFlags); 610 assertEquals(465, ha.mPort); 611 612 ha.setConnection("smtp+ssl+trustallcerts", "server", -1); 613 assertEquals(HostAuth.FLAG_SSL|HostAuth.FLAG_TRUST_ALL, ha.mFlags); 614 assertEquals(465, ha.mPort); 615 616 ha.setConnection("smtp+tls", "server", -1); 617 assertEquals(HostAuth.FLAG_TLS, ha.mFlags); 618 assertEquals(587, ha.mPort); 619 620 ha.setConnection("smtp+tls+trustallcerts", "server", -1); 621 assertEquals(HostAuth.FLAG_TLS|HostAuth.FLAG_TRUST_ALL, ha.mFlags); 622 assertEquals(587, ha.mPort); 623 } 624 625 /** 626 * Test setting the connection using a protocol and flags 627 */ 628 public void testHostAuthSetConnectionFlags() { 629 HostAuth ha = new HostAuth(); 630 631 // Different port types don't affect flags 632 ha.setConnection("imap", "server", 123, 0); 633 assertEquals(0, ha.mFlags); 634 ha.setConnection("imap", "server", -1, 0); 635 assertEquals(0, ha.mFlags); 636 637 // Different protocol types don't affect flags 638 ha.setConnection("pop3", "server", 123, 0); 639 assertEquals(0, ha.mFlags); 640 ha.setConnection("pop3", "server", -1, 0); 641 assertEquals(0, ha.mFlags); 642 ha.setConnection("eas", "server", 123, 0); 643 assertEquals(0, ha.mFlags); 644 ha.setConnection("eas", "server", -1, 0); 645 assertEquals(0, ha.mFlags); 646 ha.setConnection("smtp", "server", 123, 0); 647 assertEquals(0, ha.mFlags); 648 ha.setConnection("smtp", "server", -1, 0); 649 assertEquals(0, ha.mFlags); 650 651 // Sets SSL flag 652 ha.setConnection("imap", "server", -1, HostAuth.FLAG_SSL); 653 assertEquals(HostAuth.FLAG_SSL, ha.mFlags); 654 655 // Sets SSL+Trusted flags 656 ha.setConnection("imap", "server", -1, HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL); 657 assertEquals(HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL, ha.mFlags); 658 659 // Sets TLS flag 660 ha.setConnection("imap", "server", -1, HostAuth.FLAG_TLS); 661 assertEquals(HostAuth.FLAG_TLS, ha.mFlags); 662 663 // Sets TLS+Trusted flags 664 ha.setConnection("imap", "server", -1, HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL); 665 assertEquals(HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL, ha.mFlags); 666 667 // Test other defined flags; should not affect mFlags 668 ha.setConnection("imap", "server", -1, HostAuth.FLAG_AUTHENTICATE); 669 assertEquals(0, ha.mFlags); 670 671 // Test every other bit; should not affect mFlags 672 ha.setConnection("imap", "server", -1, 0xfffffff4); 673 assertEquals(0, ha.mFlags); 674 } 675 676 public void testHostAuthGetSchemeString() { 677 String scheme; 678 679 scheme = HostAuth.getSchemeString("foo", 0); 680 assertEquals("foo", scheme); 681 scheme = HostAuth.getSchemeString("foo", HostAuth.FLAG_SSL); 682 assertEquals("foo+ssl+", scheme); 683 scheme = HostAuth.getSchemeString("foo", HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL); 684 assertEquals("foo+ssl+trustallcerts", scheme); 685 scheme = HostAuth.getSchemeString("foo", HostAuth.FLAG_TLS); 686 assertEquals("foo+tls+", scheme); 687 scheme = HostAuth.getSchemeString("foo", HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL); 688 assertEquals("foo+tls+trustallcerts", scheme); 689 // error cases; no security string appended to protocol 690 scheme = HostAuth.getSchemeString("foo", HostAuth.FLAG_TRUST_ALL); 691 assertEquals("foo", scheme); 692 scheme = HostAuth.getSchemeString("foo", HostAuth.FLAG_SSL | HostAuth.FLAG_TLS); 693 assertEquals("foo", scheme); 694 scheme = HostAuth.getSchemeString("foo", HostAuth.FLAG_SSL | HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL); 695 assertEquals("foo", scheme); 696 scheme = HostAuth.getSchemeString("foo", 0xfffffff4); 697 assertEquals("foo", scheme); 698 } 699 700 public void testHostAuthGetSchemeFlags() { 701 int flags; 702 703 flags = HostAuth.getSchemeFlags(""); 704 assertEquals(0, flags); 705 flags = HostAuth.getSchemeFlags("+"); 706 assertEquals(0, flags); 707 flags = HostAuth.getSchemeFlags("foo+"); 708 assertEquals(0, flags); 709 flags = HostAuth.getSchemeFlags("foo+ssl"); 710 assertEquals(HostAuth.FLAG_SSL, flags); 711 flags = HostAuth.getSchemeFlags("foo+ssl+"); 712 assertEquals(HostAuth.FLAG_SSL, flags); 713 flags = HostAuth.getSchemeFlags("foo+ssl+trustallcerts"); 714 assertEquals(HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL, flags); 715 flags = HostAuth.getSchemeFlags("foo+tls+"); 716 assertEquals(HostAuth.FLAG_TLS, flags); 717 flags = HostAuth.getSchemeFlags("foo+tls+trustallcerts"); 718 assertEquals(HostAuth.FLAG_TLS | HostAuth.FLAG_TRUST_ALL, flags); 719 flags = HostAuth.getSchemeFlags("foo+bogus"); 720 assertEquals(0, flags); 721 flags = HostAuth.getSchemeFlags("foo+bogus+trustallcerts"); 722 assertEquals(HostAuth.FLAG_TRUST_ALL, flags); 723 flags = HostAuth.getSchemeFlags("foo+ssl+bogus"); 724 assertEquals(HostAuth.FLAG_SSL, flags); 725 flags = HostAuth.getSchemeFlags("foo+ssl+trustallcerts+bogus"); 726 assertEquals(HostAuth.FLAG_SSL | HostAuth.FLAG_TRUST_ALL, flags); 727 flags = HostAuth.getSchemeFlags("foo+bogus+bogus"); 728 assertEquals(0, flags); 729 flags = HostAuth.getSchemeFlags("foo+bogus+bogus+bogus"); 730 assertEquals(0, flags); 731 } 732 733 /** 734 * Test simple mailbox save/retrieve 735 */ 736 public void testMailboxSave() { 737 Account account1 = ProviderTestUtils.setupAccount("mailbox-save", true, mMockContext); 738 long account1Id = account1.mId; 739 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, 740 mMockContext); 741 long box1Id = box1.mId; 742 743 Mailbox box2 = EmailContent.Mailbox.restoreMailboxWithId(mMockContext, box1Id); 744 745 ProviderTestUtils.assertMailboxEqual("testMailboxSave", box1, box2); 746 } 747 748 private static String[] expectedAttachmentNames = 749 new String[] {"attachment1.doc", "attachment2.xls", "attachment3"}; 750 // The lengths need to be kept in ascending order 751 private static long[] expectedAttachmentSizes = new long[] {31415L, 97701L, 151213L}; 752 753 /* 754 * Returns null if the message has no body. 755 */ 756 private Body loadBodyForMessageId(long messageId) { 757 Cursor c = null; 758 try { 759 c = mMockContext.getContentResolver().query( 760 EmailContent.Body.CONTENT_URI, 761 EmailContent.Body.CONTENT_PROJECTION, 762 EmailContent.Body.MESSAGE_KEY + "=?", 763 new String[] {String.valueOf(messageId)}, 764 null); 765 int numBodies = c.getCount(); 766 assertTrue("at most one body", numBodies < 2); 767 return c.moveToFirst() ? EmailContent.getContent(c, Body.class) : null; 768 } finally { 769 c.close(); 770 } 771 } 772 773 /** 774 * Test simple message save/retrieve 775 * 776 * TODO: serverId vs. serverIntId 777 */ 778 public void testMessageSave() { 779 Account account1 = ProviderTestUtils.setupAccount("message-save", true, mMockContext); 780 long account1Id = account1.mId; 781 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 782 long box1Id = box1.mId; 783 784 // Test a simple message (saved with no body) 785 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 786 true, mMockContext); 787 long message1Id = message1.mId; 788 Message message1get = EmailContent.Message.restoreMessageWithId(mMockContext, message1Id); 789 ProviderTestUtils.assertMessageEqual("testMessageSave", message1, message1get); 790 791 // Test a message saved with a body 792 // Note that it will read back w/o the text & html so we must extract those 793 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 794 true, mMockContext); 795 long message2Id = message2.mId; 796 String text2 = message2.mText; 797 String html2 = message2.mHtml; 798 String textReply2 = message2.mTextReply; 799 String htmlReply2 = message2.mHtmlReply; 800 long sourceKey2 = message2.mSourceKey; 801 String introText2 = message2.mIntroText; 802 message2.mText = null; 803 message2.mHtml = null; 804 message2.mTextReply = null; 805 message2.mHtmlReply = null; 806 message2.mSourceKey = 0; 807 message2.mIntroText = null; 808 Message message2get = EmailContent.Message.restoreMessageWithId(mMockContext, message2Id); 809 ProviderTestUtils.assertMessageEqual("testMessageSave", message2, message2get); 810 811 // Now see if there's a body saved with the right stuff 812 Body body2 = loadBodyForMessageId(message2Id); 813 assertEquals("body text", text2, body2.mTextContent); 814 assertEquals("body html", html2, body2.mHtmlContent); 815 assertEquals("reply text", textReply2, body2.mTextReply); 816 assertEquals("reply html", htmlReply2, body2.mHtmlReply); 817 assertEquals("source key", sourceKey2, body2.mSourceKey); 818 assertEquals("intro text", introText2, body2.mIntroText); 819 820 // Message with attachments and body 821 Message message3 = ProviderTestUtils.setupMessage("message3", account1Id, box1Id, true, 822 false, mMockContext); 823 ArrayList<Attachment> atts = new ArrayList<Attachment>(); 824 for (int i = 0; i < 3; i++) { 825 atts.add(ProviderTestUtils.setupAttachment( 826 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 827 false, mMockContext)); 828 } 829 message3.mAttachments = atts; 830 message3.save(mMockContext); 831 long message3Id = message3.mId; 832 833 // Now check the attachments; there should be three and they should match name and size 834 Cursor c = null; 835 try { 836 // Note that there is NO guarantee of the order of returned records in the general case, 837 // so we specifically ask for ordering by size. The expectedAttachmentSizes array must 838 // be kept sorted by size (ascending) for this test to work properly 839 c = mMockContext.getContentResolver().query( 840 Attachment.CONTENT_URI, 841 Attachment.CONTENT_PROJECTION, 842 Attachment.MESSAGE_KEY + "=?", 843 new String[] { 844 String.valueOf(message3Id) 845 }, 846 Attachment.SIZE); 847 int numAtts = c.getCount(); 848 assertEquals(3, numAtts); 849 int i = 0; 850 while (c.moveToNext()) { 851 Attachment actual = EmailContent.getContent(c, Attachment.class); 852 ProviderTestUtils.assertAttachmentEqual("save-message3", atts.get(i), actual); 853 i++; 854 } 855 } finally { 856 c.close(); 857 } 858 859 // Message with attachments but no body 860 Message message4 = ProviderTestUtils.setupMessage("message4", account1Id, box1Id, false, 861 false, mMockContext); 862 atts = new ArrayList<Attachment>(); 863 for (int i = 0; i < 3; i++) { 864 atts.add(ProviderTestUtils.setupAttachment( 865 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 866 false, mMockContext)); 867 } 868 message4.mAttachments = atts; 869 message4.save(mMockContext); 870 long message4Id = message4.mId; 871 872 // Now check the attachments; there should be three and they should match name and size 873 c = null; 874 875 try { 876 // Note that there is NO guarantee of the order of returned records in the general case, 877 // so we specifically ask for ordering by size. The expectedAttachmentSizes array must 878 // be kept sorted by size (ascending) for this test to work properly 879 c = mMockContext.getContentResolver().query( 880 Attachment.CONTENT_URI, 881 Attachment.CONTENT_PROJECTION, 882 Attachment.MESSAGE_KEY + "=?", 883 new String[] { 884 String.valueOf(message4Id) 885 }, 886 Attachment.SIZE); 887 int numAtts = c.getCount(); 888 assertEquals(3, numAtts); 889 int i = 0; 890 while (c.moveToNext()) { 891 Attachment actual = EmailContent.getContent(c, Attachment.class); 892 ProviderTestUtils.assertAttachmentEqual("save-message4", atts.get(i), actual); 893 i++; 894 } 895 } finally { 896 c.close(); 897 } 898 899 // test EmailContent.restoreAttachmentsWitdMessageId() 900 Attachment[] attachments = 901 Attachment.restoreAttachmentsWithMessageId(mMockContext, message4Id); 902 int size = attachments.length; 903 assertEquals(3, size); 904 for (int i = 0; i < size; ++i) { 905 ProviderTestUtils.assertAttachmentEqual("save-message4", atts.get(i), attachments[i]); 906 } 907 } 908 909 /** 910 * Test that saving a message creates the proper snippet for that message 911 */ 912 public void testMessageSaveAddsSnippet() { 913 Account account = ProviderTestUtils.setupAccount("message-snippet", true, mMockContext); 914 Mailbox box = ProviderTestUtils.setupMailbox("box1", account.mId, true, mMockContext); 915 916 // Create a message without a body, unsaved 917 Message message = ProviderTestUtils.setupMessage("message", account.mId, box.mId, false, 918 false, mMockContext); 919 message.mText = "This is some text"; 920 message.mHtml = "<html>This is some text</html>"; 921 message.save(mMockContext); 922 Message restoredMessage = Message.restoreMessageWithId(mMockContext, message.mId); 923 // We should have the plain text as the snippet 924 assertEquals(restoredMessage.mSnippet, Snippet.fromPlainText(message.mText)); 925 926 // Start again 927 message = ProviderTestUtils.setupMessage("message", account.mId, box.mId, false, 928 false, mMockContext); 929 message.mText = null; 930 message.mHtml = "<html>This is some text</html>"; 931 message.save(mMockContext); 932 restoredMessage = Message.restoreMessageWithId(mMockContext, message.mId); 933 // We should have the plain text as the snippet 934 assertEquals(restoredMessage.mSnippet, Snippet.fromHtmlText(message.mHtml)); 935 } 936 937 /** 938 * TODO: update account 939 */ 940 941 /** 942 * TODO: update mailbox 943 */ 944 945 /** 946 * TODO: update message 947 */ 948 949 /** 950 * Test delete account 951 * TODO: hostauth 952 */ 953 public void testAccountDelete() { 954 Account account1 = ProviderTestUtils.setupAccount("account-delete-1", true, mMockContext); 955 long account1Id = account1.mId; 956 Account account2 = ProviderTestUtils.setupAccount("account-delete-2", true, mMockContext); 957 long account2Id = account2.mId; 958 959 // make sure there are two accounts 960 int numBoxes = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 961 assertEquals(2, numBoxes); 962 963 // now delete one of them 964 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, account1Id); 965 mMockContext.getContentResolver().delete(uri, null, null); 966 967 // make sure there's only one account now 968 numBoxes = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 969 assertEquals(1, numBoxes); 970 971 // now delete the other one 972 uri = ContentUris.withAppendedId(Account.CONTENT_URI, account2Id); 973 mMockContext.getContentResolver().delete(uri, null, null); 974 975 // make sure there are no accounts now 976 numBoxes = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 977 assertEquals(0, numBoxes); 978 } 979 980 /** 981 * Test for Body.lookupBodyIdWithMessageId() 982 * Verifies that: 983 * - for a message without body, -1 is returned. 984 * - for a mesage with body, the id matches the one from loadBodyForMessageId. 985 */ 986 public void testLookupBodyIdWithMessageId() { 987 final ContentResolver resolver = mMockContext.getContentResolver(); 988 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 989 long account1Id = account1.mId; 990 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 991 long box1Id = box1.mId; 992 993 // 1. create message with no body, check that returned bodyId is -1 994 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 995 true, mMockContext); 996 long message1Id = message1.mId; 997 long bodyId1 = Body.lookupBodyIdWithMessageId(mMockContext, message1Id); 998 assertEquals(bodyId1, -1); 999 1000 // 2. create message with body, check that returned bodyId is correct 1001 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 1002 true, mMockContext); 1003 long message2Id = message2.mId; 1004 long bodyId2 = Body.lookupBodyIdWithMessageId(mMockContext, message2Id); 1005 Body body = loadBodyForMessageId(message2Id); 1006 assertNotNull(body); 1007 assertEquals(body.mId, bodyId2); 1008 } 1009 1010 /** 1011 * Test for Body.updateBodyWithMessageId(). 1012 * 1. - create message without body, 1013 * - update its body (set TEXT_CONTENT) 1014 * - check correct updated body is read back 1015 * 1016 * 2. - create message with body, 1017 * - update body (set TEXT_CONTENT) 1018 * - check correct updated body is read back 1019 */ 1020 public void testUpdateBodyWithMessageId() { 1021 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 1022 long account1Id = account1.mId; 1023 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1024 long box1Id = box1.mId; 1025 1026 final String textContent = "foobar some odd text"; 1027 final String htmlContent = "and some html"; 1028 final String textReply = "plain text reply"; 1029 final String htmlReply = "or the html reply"; 1030 final String introText = "fred wrote:"; 1031 1032 ContentValues values = new ContentValues(); 1033 values.put(BodyColumns.TEXT_CONTENT, textContent); 1034 values.put(BodyColumns.HTML_CONTENT, htmlContent); 1035 values.put(BodyColumns.TEXT_REPLY, textReply); 1036 values.put(BodyColumns.HTML_REPLY, htmlReply); 1037 values.put(BodyColumns.SOURCE_MESSAGE_KEY, 17); 1038 values.put(BodyColumns.INTRO_TEXT, introText); 1039 1040 // 1 1041 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 1042 true, mMockContext); 1043 long message1Id = message1.mId; 1044 Body body1 = loadBodyForMessageId(message1Id); 1045 assertNull(body1); 1046 Body.updateBodyWithMessageId(mMockContext, message1Id, values); 1047 body1 = loadBodyForMessageId(message1Id); 1048 assertNotNull(body1); 1049 assertEquals(body1.mTextContent, textContent); 1050 assertEquals(body1.mHtmlContent, htmlContent); 1051 assertEquals(body1.mTextReply, textReply); 1052 assertEquals(body1.mHtmlReply, htmlReply); 1053 assertEquals(body1.mSourceKey, 17); 1054 assertEquals(body1.mIntroText, introText); 1055 1056 // 2 1057 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 1058 true, mMockContext); 1059 long message2Id = message2.mId; 1060 Body body2 = loadBodyForMessageId(message2Id); 1061 assertNotNull(body2); 1062 assertTrue(!body2.mTextContent.equals(textContent)); 1063 Body.updateBodyWithMessageId(mMockContext, message2Id, values); 1064 body2 = loadBodyForMessageId(message1Id); 1065 assertNotNull(body2); 1066 assertEquals(body2.mTextContent, textContent); 1067 assertEquals(body2.mHtmlContent, htmlContent); 1068 assertEquals(body2.mTextReply, textReply); 1069 assertEquals(body2.mHtmlReply, htmlReply); 1070 assertEquals(body2.mSourceKey, 17); 1071 assertEquals(body2.mIntroText, introText); 1072 } 1073 1074 /** 1075 * Test body retrieve methods 1076 */ 1077 public void testBodyRetrieve() { 1078 // No account needed 1079 // No mailbox needed 1080 Message message1 = ProviderTestUtils.setupMessage("bodyretrieve", 1, 1, true, 1081 true, mMockContext); 1082 long messageId = message1.mId; 1083 1084 assertEquals(message1.mText, 1085 Body.restoreBodyTextWithMessageId(mMockContext, messageId)); 1086 assertEquals(message1.mHtml, 1087 Body.restoreBodyHtmlWithMessageId(mMockContext, messageId)); 1088 assertEquals(message1.mTextReply, 1089 Body.restoreReplyTextWithMessageId(mMockContext, messageId)); 1090 assertEquals(message1.mHtmlReply, 1091 Body.restoreReplyHtmlWithMessageId(mMockContext, messageId)); 1092 assertEquals(message1.mIntroText, 1093 Body.restoreIntroTextWithMessageId(mMockContext, messageId)); 1094 assertEquals(message1.mSourceKey, 1095 Body.restoreBodySourceKey(mMockContext, messageId)); 1096 } 1097 1098 /** 1099 * Test delete body. 1100 * 1. create message without body (message id 1) 1101 * 2. create message with body (message id 2. The body has _id 1 and messageKey 2). 1102 * 3. delete first message. 1103 * 4. verify that body for message 2 has not been deleted. 1104 * 5. delete message 2, verify body is deleted. 1105 */ 1106 public void testDeleteBody() { 1107 final ContentResolver resolver = mMockContext.getContentResolver(); 1108 1109 // Create account and mailboxes 1110 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 1111 long account1Id = account1.mId; 1112 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1113 long box1Id = box1.mId; 1114 1115 // 1. create message without body 1116 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 1117 true, mMockContext); 1118 long message1Id = message1.mId; 1119 1120 // 2. create message with body 1121 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 1122 true, mMockContext); 1123 long message2Id = message2.mId; 1124 // verify body is there 1125 assertNotNull(loadBodyForMessageId(message2Id)); 1126 1127 // 3. delete first message 1128 resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message1Id), null, null); 1129 1130 // 4. verify body for second message wasn't deleted 1131 assertNotNull(loadBodyForMessageId(message2Id)); 1132 1133 // 5. delete second message, check its body is deleted 1134 resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message2Id), null, null); 1135 assertNull(loadBodyForMessageId(message2Id)); 1136 } 1137 1138 /** 1139 * Test delete orphan bodies. 1140 * 1. create message without body (message id 1) 1141 * 2. create message with body (message id 2. Body has _id 1 and messageKey 2). 1142 * 3. delete first message. 1143 * 4. delete some other mailbox -- this triggers delete orphan bodies. 1144 * 5. verify that body for message 2 has not been deleted. 1145 */ 1146 public void testDeleteOrphanBodies() { 1147 final ContentResolver resolver = mMockContext.getContentResolver(); 1148 1149 // Create account and two mailboxes 1150 Account account1 = ProviderTestUtils.setupAccount("orphaned body", true, mMockContext); 1151 long account1Id = account1.mId; 1152 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1153 long box1Id = box1.mId; 1154 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mMockContext); 1155 long box2Id = box2.mId; 1156 1157 // 1. create message without body 1158 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 1159 true, mMockContext); 1160 long message1Id = message1.mId; 1161 1162 // 2. create message with body 1163 Message message2 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 1164 true, mMockContext); 1165 long message2Id = message2.mId; 1166 //verify body is there 1167 assertNotNull(loadBodyForMessageId(message2Id)); 1168 1169 // 3. delete first message 1170 resolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, message1Id), null, null); 1171 1172 // 4. delete some mailbox (because it triggers "delete orphan bodies") 1173 resolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2Id), null, null); 1174 1175 // 5. verify body for second message wasn't deleted during "delete orphan bodies" 1176 assertNotNull(loadBodyForMessageId(message2Id)); 1177 } 1178 1179 /** 1180 * Note that we can't use EmailContent.count() here because it uses a projection including 1181 * count(*), and count(*) is incompatible with a LIMIT (i.e. the limit would be applied to the 1182 * single column returned with count(*), rather than to the query itself) 1183 */ 1184 private int count(Context context, Uri uri, String selection, String[] selectionArgs) { 1185 Cursor c = context.getContentResolver().query(uri, EmailContent.ID_PROJECTION, selection, 1186 selectionArgs, null); 1187 try { 1188 return c.getCount(); 1189 } finally { 1190 c.close(); 1191 } 1192 } 1193 1194 public void testMessageQueryWithLimit() { 1195 final Context context = mMockContext; 1196 1197 // Create account and two mailboxes 1198 Account acct = ProviderTestUtils.setupAccount("orphaned body", true, context); 1199 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", acct.mId, true, context); 1200 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", acct.mId, true, context); 1201 1202 // Create 4 messages in box1 1203 ProviderTestUtils.setupMessage("message1", acct.mId, box1.mId, false, true, context); 1204 ProviderTestUtils.setupMessage("message2", acct.mId, box1.mId, false, true, context); 1205 ProviderTestUtils.setupMessage("message3", acct.mId, box1.mId, false, true, context); 1206 ProviderTestUtils.setupMessage("message4", acct.mId, box1.mId, false, true, context); 1207 1208 // Create 4 messages in box2 1209 ProviderTestUtils.setupMessage("message1", acct.mId, box2.mId, false, true, context); 1210 ProviderTestUtils.setupMessage("message2", acct.mId, box2.mId, false, true, context); 1211 ProviderTestUtils.setupMessage("message3", acct.mId, box2.mId, false, true, context); 1212 ProviderTestUtils.setupMessage("message4", acct.mId, box2.mId, false, true, context); 1213 1214 // Check normal case, special case (limit 1), and arbitrary limits 1215 assertEquals(8, count(mMockContext, Message.CONTENT_URI, null, null)); 1216 assertEquals(1, count(mMockContext, EmailContent.uriWithLimit(Message.CONTENT_URI, 1), 1217 null, null)); 1218 assertEquals(3, count(mMockContext, EmailContent.uriWithLimit(Message.CONTENT_URI, 3), 1219 null, null)); 1220 assertEquals(8, count(mMockContext, EmailContent.uriWithLimit(Message.CONTENT_URI, 100), 1221 null, null)); 1222 1223 // Check that it works with selection/selection args 1224 String[] args = new String[] {Long.toString(box1.mId)}; 1225 assertEquals(4, count(mMockContext, Message.CONTENT_URI, 1226 MessageColumns.MAILBOX_KEY + "=?", args)); 1227 assertEquals(1, count(mMockContext, 1228 EmailContent.uriWithLimit(Message.CONTENT_URI, 1), 1229 MessageColumns.MAILBOX_KEY + "=?", args)); 1230 } 1231 1232 /** 1233 * Test delete orphan messages 1234 * 1. create message without body (message id 1) 1235 * 2. create message with body (message id 2. Body has _id 1 and messageKey 2). 1236 * 3. delete first message. 1237 * 4. delete some other mailbox -- this triggers delete orphan bodies. 1238 * 5. verify that body for message 2 has not been deleted. 1239 */ 1240 public void testDeleteOrphanMessages() { 1241 final ContentResolver resolver = mMockContext.getContentResolver(); 1242 final Context context = mMockContext; 1243 1244 // Create account and two mailboxes 1245 Account acct = ProviderTestUtils.setupAccount("orphaned body", true, context); 1246 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", acct.mId, true, context); 1247 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", acct.mId, true, context); 1248 1249 // Create 4 messages in box1 1250 Message msg1_1 = 1251 ProviderTestUtils.setupMessage("message1", acct.mId, box1.mId, false, true, context); 1252 Message msg1_2 = 1253 ProviderTestUtils.setupMessage("message2", acct.mId, box1.mId, false, true, context); 1254 Message msg1_3 = 1255 ProviderTestUtils.setupMessage("message3", acct.mId, box1.mId, false, true, context); 1256 Message msg1_4 = 1257 ProviderTestUtils.setupMessage("message4", acct.mId, box1.mId, false, true, context); 1258 1259 // Create 4 messages in box2 1260 Message msg2_1 = 1261 ProviderTestUtils.setupMessage("message1", acct.mId, box2.mId, false, true, context); 1262 Message msg2_2 = 1263 ProviderTestUtils.setupMessage("message2", acct.mId, box2.mId, false, true, context); 1264 Message msg2_3 = 1265 ProviderTestUtils.setupMessage("message3", acct.mId, box2.mId, false, true, context); 1266 Message msg2_4 = 1267 ProviderTestUtils.setupMessage("message4", acct.mId, box2.mId, false, true, context); 1268 1269 // Delete 2 from each mailbox 1270 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg1_1.mId), 1271 null, null); 1272 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg1_2.mId), 1273 null, null); 1274 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg2_1.mId), 1275 null, null); 1276 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg2_2.mId), 1277 null, null); 1278 1279 // There should be 4 items in the deleted item table 1280 assertEquals(4, EmailContent.count(context, Message.DELETED_CONTENT_URI, null, null)); 1281 1282 // Update 2 from each mailbox 1283 ContentValues v = new ContentValues(); 1284 v.put(MessageColumns.DISPLAY_NAME, "--updated--"); 1285 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg1_3.mId), 1286 v, null, null); 1287 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg1_4.mId), 1288 v, null, null); 1289 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg2_3.mId), 1290 v, null, null); 1291 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, msg2_4.mId), 1292 v, null, null); 1293 1294 // There should be 4 items in the updated item table 1295 assertEquals(4, EmailContent.count(context, Message.UPDATED_CONTENT_URI, null, null)); 1296 1297 // Manually add 2 messages from a "deleted" mailbox to deleted and updated tables 1298 // Use a value > 2 for the deleted box id 1299 long delBoxId = 10; 1300 // Create 4 messages in the "deleted" mailbox 1301 Message msgX_A = 1302 ProviderTestUtils.setupMessage("messageA", acct.mId, delBoxId, false, false, context); 1303 Message msgX_B = 1304 ProviderTestUtils.setupMessage("messageB", acct.mId, delBoxId, false, false, context); 1305 Message msgX_C = 1306 ProviderTestUtils.setupMessage("messageC", acct.mId, delBoxId, false, false, context); 1307 Message msgX_D = 1308 ProviderTestUtils.setupMessage("messageD", acct.mId, delBoxId, false, false, context); 1309 1310 ContentValues cv; 1311 // We have to assign id's manually because there are no autoincrement id's for these tables 1312 // Start with an id that won't exist, since id's in these tables must be unique 1313 long msgId = 10; 1314 // It's illegal to manually insert these, so we need to catch the exception 1315 // NOTE: The insert succeeds, and then throws the exception 1316 try { 1317 cv = msgX_A.toContentValues(); 1318 cv.put(EmailContent.RECORD_ID, msgId++); 1319 resolver.insert(Message.DELETED_CONTENT_URI, cv); 1320 } catch (IllegalArgumentException e) { 1321 } 1322 try { 1323 cv = msgX_B.toContentValues(); 1324 cv.put(EmailContent.RECORD_ID, msgId++); 1325 resolver.insert(Message.DELETED_CONTENT_URI, cv); 1326 } catch (IllegalArgumentException e) { 1327 } 1328 try { 1329 cv = msgX_C.toContentValues(); 1330 cv.put(EmailContent.RECORD_ID, msgId++); 1331 resolver.insert(Message.UPDATED_CONTENT_URI, cv); 1332 } catch (IllegalArgumentException e) { 1333 } 1334 try { 1335 cv = msgX_D.toContentValues(); 1336 cv.put(EmailContent.RECORD_ID, msgId++); 1337 resolver.insert(Message.UPDATED_CONTENT_URI, cv); 1338 } catch (IllegalArgumentException e) { 1339 } 1340 1341 // There should be 6 items in the deleted and updated tables 1342 assertEquals(6, EmailContent.count(context, Message.UPDATED_CONTENT_URI, null, null)); 1343 assertEquals(6, EmailContent.count(context, Message.DELETED_CONTENT_URI, null, null)); 1344 1345 // Delete the orphans 1346 EmailProvider.deleteOrphans(EmailProvider.getReadableDatabase(context), 1347 Message.DELETED_TABLE_NAME); 1348 EmailProvider.deleteOrphans(EmailProvider.getReadableDatabase(context), 1349 Message.UPDATED_TABLE_NAME); 1350 1351 // There should now be 4 messages in each of the deleted and updated tables again 1352 assertEquals(4, EmailContent.count(context, Message.UPDATED_CONTENT_URI, null, null)); 1353 assertEquals(4, EmailContent.count(context, Message.DELETED_CONTENT_URI, null, null)); 1354 } 1355 1356 /** 1357 * Test delete mailbox 1358 */ 1359 public void testMailboxDelete() { 1360 Account account1 = ProviderTestUtils.setupAccount("mailbox-delete", true, mMockContext); 1361 long account1Id = account1.mId; 1362 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1363 long box1Id = box1.mId; 1364 Mailbox box2 = ProviderTestUtils.setupMailbox("box2", account1Id, true, mMockContext); 1365 long box2Id = box2.mId; 1366 1367 String selection = EmailContent.MailboxColumns.ACCOUNT_KEY + "=?"; 1368 String[] selArgs = new String[] { String.valueOf(account1Id) }; 1369 1370 // make sure there are two mailboxes 1371 int numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs); 1372 assertEquals(2, numBoxes); 1373 1374 // now delete one of them 1375 Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box1Id); 1376 mMockContext.getContentResolver().delete(uri, null, null); 1377 1378 // make sure there's only one mailbox now 1379 numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs); 1380 assertEquals(1, numBoxes); 1381 1382 // now delete the other one 1383 uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box2Id); 1384 mMockContext.getContentResolver().delete(uri, null, null); 1385 1386 // make sure there are no mailboxes now 1387 numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, selection, selArgs); 1388 assertEquals(0, numBoxes); 1389 } 1390 1391 /** 1392 * Test delete message 1393 * TODO: body 1394 * TODO: attachments 1395 */ 1396 public void testMessageDelete() { 1397 Account account1 = ProviderTestUtils.setupAccount("message-delete", true, mMockContext); 1398 long account1Id = account1.mId; 1399 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1400 long box1Id = box1.mId; 1401 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 1402 true, mMockContext); 1403 long message1Id = message1.mId; 1404 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, 1405 true, mMockContext); 1406 long message2Id = message2.mId; 1407 1408 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " + 1409 EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 1410 String[] selArgs = new String[] { String.valueOf(account1Id), String.valueOf(box1Id) }; 1411 1412 // make sure there are two messages 1413 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1414 assertEquals(2, numMessages); 1415 1416 // now delete one of them 1417 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1Id); 1418 mMockContext.getContentResolver().delete(uri, null, null); 1419 1420 // make sure there's only one message now 1421 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1422 assertEquals(1, numMessages); 1423 1424 // now delete the other one 1425 uri = ContentUris.withAppendedId(Message.CONTENT_URI, message2Id); 1426 mMockContext.getContentResolver().delete(uri, null, null); 1427 1428 // make sure there are no messages now 1429 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1430 assertEquals(0, numMessages); 1431 } 1432 1433 /** 1434 * Test delete synced message 1435 * TODO: body 1436 * TODO: attachments 1437 */ 1438 public void testSyncedMessageDelete() { 1439 Account account1 = ProviderTestUtils.setupAccount("synced-message-delete", true, 1440 mMockContext); 1441 long account1Id = account1.mId; 1442 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1443 long box1Id = box1.mId; 1444 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 1445 true, mMockContext); 1446 long message1Id = message1.mId; 1447 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, 1448 true, mMockContext); 1449 long message2Id = message2.mId; 1450 1451 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " 1452 + EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 1453 String[] selArgs = new String[] { 1454 String.valueOf(account1Id), String.valueOf(box1Id) 1455 }; 1456 1457 // make sure there are two messages 1458 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1459 assertEquals(2, numMessages); 1460 1461 // make sure we start with no synced deletions 1462 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 1463 selArgs); 1464 assertEquals(0, numMessages); 1465 1466 // now delete one of them SYNCED 1467 Uri uri = ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message1Id); 1468 mMockContext.getContentResolver().delete(uri, null, null); 1469 1470 // make sure there's only one message now 1471 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1472 assertEquals(1, numMessages); 1473 1474 // make sure there's one synced deletion now 1475 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 1476 selArgs); 1477 assertEquals(1, numMessages); 1478 1479 // now delete the other one NOT SYNCED 1480 uri = ContentUris.withAppendedId(Message.CONTENT_URI, message2Id); 1481 mMockContext.getContentResolver().delete(uri, null, null); 1482 1483 // make sure there are no messages now 1484 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1485 assertEquals(0, numMessages); 1486 1487 // make sure there's still one deletion now 1488 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 1489 selArgs); 1490 assertEquals(1, numMessages); 1491 } 1492 1493 /** 1494 * Test message update 1495 * TODO: body 1496 * TODO: attachments 1497 */ 1498 public void testMessageUpdate() { 1499 Account account1 = ProviderTestUtils.setupAccount("message-update", true, mMockContext); 1500 long account1Id = account1.mId; 1501 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1502 long box1Id = box1.mId; 1503 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, false, 1504 true, mMockContext); 1505 long message1Id = message1.mId; 1506 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, false, 1507 true, mMockContext); 1508 long message2Id = message2.mId; 1509 ContentResolver cr = mMockContext.getContentResolver(); 1510 1511 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " 1512 + EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 1513 String[] selArgs = new String[] { 1514 String.valueOf(account1Id), String.valueOf(box1Id) 1515 }; 1516 1517 // make sure there are two messages 1518 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1519 assertEquals(2, numMessages); 1520 1521 // change the first one 1522 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1Id); 1523 ContentValues cv = new ContentValues(); 1524 cv.put(MessageColumns.FROM_LIST, "from-list"); 1525 cr.update(uri, cv, null, null); 1526 1527 // make sure there's no updated message 1528 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1529 selArgs); 1530 assertEquals(0, numMessages); 1531 1532 // get the message back from the provider, make sure the change "stuck" 1533 Message restoredMessage = Message.restoreMessageWithId(mMockContext, message1Id); 1534 assertEquals("from-list", restoredMessage.mFrom); 1535 1536 // change the second one 1537 uri = ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message2Id); 1538 cv = new ContentValues(); 1539 cv.put(MessageColumns.FROM_LIST, "from-list"); 1540 cr.update(uri, cv, null, null); 1541 1542 // make sure there's one updated message 1543 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1544 selArgs); 1545 assertEquals(1, numMessages); 1546 1547 // get the message back from the provider, make sure the change "stuck", 1548 // as before 1549 restoredMessage = Message.restoreMessageWithId(mMockContext, message2Id); 1550 assertEquals("from-list", restoredMessage.mFrom); 1551 1552 // get the original message back from the provider 1553 Cursor c = cr.query(Message.UPDATED_CONTENT_URI, Message.CONTENT_PROJECTION, null, null, 1554 null); 1555 try { 1556 assertTrue(c.moveToFirst()); 1557 Message originalMessage = EmailContent.getContent(c, Message.class); 1558 // make sure this has the original value 1559 assertEquals("from message2", originalMessage.mFrom); 1560 // Should only be one 1561 assertFalse(c.moveToNext()); 1562 } finally { 1563 c.close(); 1564 } 1565 1566 // delete the second message 1567 cr.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message2Id), null, null); 1568 1569 // hey, presto! the change should be gone 1570 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1571 selArgs); 1572 assertEquals(0, numMessages); 1573 1574 // and there should now be a deleted record 1575 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 1576 selArgs); 1577 assertEquals(1, numMessages); 1578 } 1579 1580 /** 1581 * TODO: cascaded delete account 1582 * TODO: hostauth 1583 * TODO: body 1584 * TODO: attachments 1585 * TODO: create other account, mailbox & messages and confirm the right objects were deleted 1586 */ 1587 public void testCascadeDeleteAccount() { 1588 Account account1 = ProviderTestUtils.setupAccount("account-delete-cascade", true, 1589 mMockContext); 1590 long account1Id = account1.mId; 1591 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1592 long box1Id = box1.mId; 1593 /* Message message1 = */ ProviderTestUtils.setupMessage("message1", account1Id, box1Id, 1594 false, true, mMockContext); 1595 /* Message message2 = */ ProviderTestUtils.setupMessage("message2", account1Id, box1Id, 1596 false, true, mMockContext); 1597 1598 // make sure there is one account, one mailbox, and two messages 1599 int numAccounts = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 1600 assertEquals(1, numAccounts); 1601 int numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, null, null); 1602 assertEquals(1, numBoxes); 1603 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 1604 assertEquals(2, numMessages); 1605 1606 // delete the account 1607 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, account1Id); 1608 mMockContext.getContentResolver().delete(uri, null, null); 1609 1610 // make sure there are no accounts, mailboxes, or messages 1611 numAccounts = EmailContent.count(mMockContext, Account.CONTENT_URI, null, null); 1612 assertEquals(0, numAccounts); 1613 numBoxes = EmailContent.count(mMockContext, Mailbox.CONTENT_URI, null, null); 1614 assertEquals(0, numBoxes); 1615 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 1616 assertEquals(0, numMessages); 1617 } 1618 1619 /** 1620 * Test cascaded delete mailbox 1621 * TODO: body 1622 * TODO: attachments 1623 * TODO: create other mailbox & messages and confirm the right objects were deleted 1624 */ 1625 public void testCascadeDeleteMailbox() { 1626 Account account1 = ProviderTestUtils.setupAccount("mailbox-delete-cascade", true, 1627 mMockContext); 1628 long account1Id = account1.mId; 1629 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1630 long box1Id = box1.mId; 1631 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, 1632 false, true, mMockContext); 1633 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, 1634 false, true, mMockContext); 1635 Message message3 = ProviderTestUtils.setupMessage("message3", account1Id, box1Id, 1636 false, true, mMockContext); 1637 Message message4 = ProviderTestUtils.setupMessage("message4", account1Id, box1Id, 1638 false, true, mMockContext); 1639 ProviderTestUtils.setupMessage("message5", account1Id, box1Id, false, true, mMockContext); 1640 ProviderTestUtils.setupMessage("message6", account1Id, box1Id, false, true, mMockContext); 1641 1642 String selection = EmailContent.MessageColumns.ACCOUNT_KEY + "=? AND " + 1643 EmailContent.MessageColumns.MAILBOX_KEY + "=?"; 1644 String[] selArgs = new String[] { String.valueOf(account1Id), String.valueOf(box1Id) }; 1645 1646 // make sure there are six messages 1647 int numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1648 assertEquals(6, numMessages); 1649 1650 ContentValues cv = new ContentValues(); 1651 cv.put(Message.SERVER_ID, "SERVER_ID"); 1652 ContentResolver resolver = mMockContext.getContentResolver(); 1653 1654 // Update two messages 1655 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message1.mId), 1656 cv, null, null); 1657 resolver.update(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message2.mId), 1658 cv, null, null); 1659 // Delete two messages 1660 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message3.mId), 1661 null, null); 1662 resolver.delete(ContentUris.withAppendedId(Message.SYNCED_CONTENT_URI, message4.mId), 1663 null, null); 1664 1665 // There should now be two messages in updated/deleted, and 4 in messages 1666 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1667 assertEquals(4, numMessages); 1668 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 1669 selArgs); 1670 assertEquals(2, numMessages); 1671 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1672 selArgs); 1673 assertEquals(2, numMessages); 1674 1675 // now delete the mailbox 1676 Uri uri = ContentUris.withAppendedId(Mailbox.CONTENT_URI, box1Id); 1677 resolver.delete(uri, null, null); 1678 1679 // there should now be zero messages in all three tables 1680 numMessages = EmailContent.count(mMockContext, Message.CONTENT_URI, selection, selArgs); 1681 assertEquals(0, numMessages); 1682 numMessages = EmailContent.count(mMockContext, Message.DELETED_CONTENT_URI, selection, 1683 selArgs); 1684 assertEquals(0, numMessages); 1685 numMessages = EmailContent.count(mMockContext, Message.UPDATED_CONTENT_URI, selection, 1686 selArgs); 1687 assertEquals(0, numMessages); 1688 } 1689 1690 /** 1691 * Test cascaded delete message 1692 * Confirms that deleting a message will also delete its body & attachments 1693 */ 1694 public void testCascadeMessageDelete() { 1695 Account account1 = ProviderTestUtils.setupAccount("message-cascade", true, mMockContext); 1696 long account1Id = account1.mId; 1697 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", account1Id, true, mMockContext); 1698 long box1Id = box1.mId; 1699 1700 // Each message has a body, and also give each 2 attachments 1701 Message message1 = ProviderTestUtils.setupMessage("message1", account1Id, box1Id, true, 1702 false, mMockContext); 1703 ArrayList<Attachment> atts = new ArrayList<Attachment>(); 1704 for (int i = 0; i < 2; i++) { 1705 atts.add(ProviderTestUtils.setupAttachment( 1706 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 1707 false, mMockContext)); 1708 } 1709 message1.mAttachments = atts; 1710 message1.save(mMockContext); 1711 long message1Id = message1.mId; 1712 1713 Message message2 = ProviderTestUtils.setupMessage("message2", account1Id, box1Id, true, 1714 false, mMockContext); 1715 atts = new ArrayList<Attachment>(); 1716 for (int i = 0; i < 2; i++) { 1717 atts.add(ProviderTestUtils.setupAttachment( 1718 -1, expectedAttachmentNames[i], expectedAttachmentSizes[i], 1719 false, mMockContext)); 1720 } 1721 message2.mAttachments = atts; 1722 message2.save(mMockContext); 1723 long message2Id = message2.mId; 1724 1725 // Set up to test total counts of bodies & attachments for our test messages 1726 String bodySelection = BodyColumns.MESSAGE_KEY + " IN (?,?)"; 1727 String attachmentSelection = AttachmentColumns.MESSAGE_KEY + " IN (?,?)"; 1728 String[] selArgs = new String[] { String.valueOf(message1Id), String.valueOf(message2Id) }; 1729 1730 // make sure there are two bodies 1731 int numBodies = EmailContent.count(mMockContext, Body.CONTENT_URI, bodySelection, selArgs); 1732 assertEquals(2, numBodies); 1733 1734 // make sure there are four attachments 1735 int numAttachments = EmailContent.count(mMockContext, Attachment.CONTENT_URI, 1736 attachmentSelection, selArgs); 1737 assertEquals(4, numAttachments); 1738 1739 // now delete one of the messages 1740 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1Id); 1741 mMockContext.getContentResolver().delete(uri, null, null); 1742 1743 // there should be one body and two attachments 1744 numBodies = EmailContent.count(mMockContext, Body.CONTENT_URI, bodySelection, selArgs); 1745 assertEquals(1, numBodies); 1746 1747 numAttachments = EmailContent.count(mMockContext, Attachment.CONTENT_URI, 1748 attachmentSelection, selArgs); 1749 assertEquals(2, numAttachments); 1750 1751 // now delete the other message 1752 uri = ContentUris.withAppendedId(Message.CONTENT_URI, message2Id); 1753 mMockContext.getContentResolver().delete(uri, null, null); 1754 1755 // make sure there are no bodies or attachments 1756 numBodies = EmailContent.count(mMockContext, Body.CONTENT_URI, bodySelection, selArgs); 1757 assertEquals(0, numBodies); 1758 1759 numAttachments = EmailContent.count(mMockContext, Attachment.CONTENT_URI, 1760 attachmentSelection, selArgs); 1761 assertEquals(0, numAttachments); 1762 } 1763 1764 /** 1765 * Test that our unique file name algorithm works as expected. Since this test requires an 1766 * SD card, we check the environment first, and return immediately if none is mounted. 1767 * @throws IOException 1768 */ 1769 public void testCreateUniqueFile() throws IOException { 1770 // Delete existing files, if they exist 1771 if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 1772 return; 1773 } 1774 try { 1775 String fileName = "A11achm3n1.doc"; 1776 File uniqueFile = Attachment.createUniqueFile(fileName); 1777 assertEquals(fileName, uniqueFile.getName()); 1778 if (uniqueFile.createNewFile()) { 1779 uniqueFile = Attachment.createUniqueFile(fileName); 1780 assertEquals("A11achm3n1-2.doc", uniqueFile.getName()); 1781 if (uniqueFile.createNewFile()) { 1782 uniqueFile = Attachment.createUniqueFile(fileName); 1783 assertEquals("A11achm3n1-3.doc", uniqueFile.getName()); 1784 } 1785 } 1786 fileName = "A11achm3n1"; 1787 uniqueFile = Attachment.createUniqueFile(fileName); 1788 assertEquals(fileName, uniqueFile.getName()); 1789 if (uniqueFile.createNewFile()) { 1790 uniqueFile = Attachment.createUniqueFile(fileName); 1791 assertEquals("A11achm3n1-2", uniqueFile.getName()); 1792 } 1793 } finally { 1794 File directory = Environment.getExternalStorageDirectory(); 1795 // These are the files that should be created earlier in the test. Make sure 1796 // they are deleted for the next go-around 1797 String[] fileNames = new String[] {"A11achm3n1.doc", "A11achm3n1-2.doc", "A11achm3n1"}; 1798 int length = fileNames.length; 1799 for (int i = 0; i < length; i++) { 1800 File file = new File(directory, fileNames[i]); 1801 if (file.exists()) { 1802 file.delete(); 1803 } 1804 } 1805 } 1806 } 1807 1808 /** 1809 * Test retrieving attachments by message ID (using EmailContent.Attachment.MESSAGE_ID_URI) 1810 */ 1811 public void testGetAttachmentByMessageIdUri() { 1812 1813 // Note, we don't strictly need accounts, mailboxes or messages to run this test. 1814 Attachment a1 = ProviderTestUtils.setupAttachment(1, "a1", 100, true, mMockContext); 1815 Attachment a2 = ProviderTestUtils.setupAttachment(1, "a2", 200, true, mMockContext); 1816 ProviderTestUtils.setupAttachment(2, "a3", 300, true, mMockContext); 1817 ProviderTestUtils.setupAttachment(2, "a4", 400, true, mMockContext); 1818 1819 // Now ask for the attachments of message id=1 1820 // Note: Using the "sort by size" trick to bring them back in expected order 1821 Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, 1); 1822 Cursor c = mMockContext.getContentResolver().query(uri, Attachment.CONTENT_PROJECTION, 1823 null, null, Attachment.SIZE); 1824 assertEquals(2, c.getCount()); 1825 1826 try { 1827 c.moveToFirst(); 1828 Attachment a1Get = EmailContent.getContent(c, Attachment.class); 1829 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-1", a1, a1Get); 1830 c.moveToNext(); 1831 Attachment a2Get = EmailContent.getContent(c, Attachment.class); 1832 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-2", a2, a2Get); 1833 } finally { 1834 c.close(); 1835 } 1836 } 1837 1838 /** 1839 * Test deleting attachments by message ID (using EmailContent.Attachment.MESSAGE_ID_URI) 1840 */ 1841 public void testDeleteAttachmentByMessageIdUri() { 1842 ContentResolver mockResolver = mMockContext.getContentResolver(); 1843 1844 // Note, we don't strictly need accounts, mailboxes or messages to run this test. 1845 ProviderTestUtils.setupAttachment(1, "a1", 100, true, mMockContext); 1846 ProviderTestUtils.setupAttachment(1, "a2", 200, true, mMockContext); 1847 Attachment a3 = ProviderTestUtils.setupAttachment(2, "a3", 300, true, mMockContext); 1848 Attachment a4 = ProviderTestUtils.setupAttachment(2, "a4", 400, true, mMockContext); 1849 1850 // Delete all attachments for message id=1 1851 Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, 1); 1852 mockResolver.delete(uri, null, null); 1853 1854 // Read back all attachments and confirm that we have the expected remaining attachments 1855 // (the attachments that are set for message id=2). Note order-by size to simplify test. 1856 Cursor c = mockResolver.query(Attachment.CONTENT_URI, Attachment.CONTENT_PROJECTION, 1857 null, null, Attachment.SIZE); 1858 assertEquals(2, c.getCount()); 1859 1860 try { 1861 c.moveToFirst(); 1862 Attachment a3Get = EmailContent.getContent(c, Attachment.class); 1863 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-3", a3, a3Get); 1864 c.moveToNext(); 1865 Attachment a4Get = EmailContent.getContent(c, Attachment.class); 1866 ProviderTestUtils.assertAttachmentEqual("getAttachByUri-4", a4, a4Get); 1867 } finally { 1868 c.close(); 1869 } 1870 } 1871 1872 /** 1873 * Tests of default account behavior 1874 * 1875 * 1. Simple set/get 1876 * 2. Moving default between 3 accounts 1877 * 3. Delete default, make sure another becomes default 1878 */ 1879 public void testSetGetDefaultAccount() { 1880 // There should be no default account if there are no accounts 1881 long defaultAccountId = Account.getDefaultAccountId(mMockContext); 1882 assertEquals(-1, defaultAccountId); 1883 1884 Account account1 = ProviderTestUtils.setupAccount("account-default-1", true, mMockContext); 1885 long account1Id = account1.mId; 1886 Account account2 = ProviderTestUtils.setupAccount("account-default-2", true, mMockContext); 1887 long account2Id = account2.mId; 1888 Account account3 = ProviderTestUtils.setupAccount("account-default-3", true, mMockContext); 1889 long account3Id = account3.mId; 1890 1891 // With three accounts, but none marked default, confirm that some default account 1892 // is returned. Which one is undefined here. 1893 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1894 assertTrue(defaultAccountId == account1Id 1895 || defaultAccountId == account2Id 1896 || defaultAccountId == account3Id); 1897 1898 updateIsDefault(account1, true); 1899 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1900 assertEquals(account1Id, defaultAccountId); 1901 1902 updateIsDefault(account2, true); 1903 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1904 assertEquals(account2Id, defaultAccountId); 1905 1906 updateIsDefault(account3, true); 1907 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1908 assertEquals(account3Id, defaultAccountId); 1909 1910 // Now delete a non-default account and confirm no change 1911 Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, account1Id); 1912 mMockContext.getContentResolver().delete(uri, null, null); 1913 1914 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1915 assertEquals(account3Id, defaultAccountId); 1916 1917 // Now confirm deleting the default account and it switches to another one 1918 uri = ContentUris.withAppendedId(Account.CONTENT_URI, account3Id); 1919 mMockContext.getContentResolver().delete(uri, null, null); 1920 1921 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1922 assertEquals(account2Id, defaultAccountId); 1923 1924 // Now delete the final account and confirm there are no default accounts again 1925 uri = ContentUris.withAppendedId(Account.CONTENT_URI, account2Id); 1926 mMockContext.getContentResolver().delete(uri, null, null); 1927 1928 defaultAccountId = Account.getDefaultAccountId(mMockContext); 1929 assertEquals(-1, defaultAccountId); 1930 } 1931 1932 private void updateIsDefault(Account account, boolean newState) { 1933 account.setDefaultAccount(newState); 1934 ContentValues cv = new ContentValues(); 1935 cv.put(AccountColumns.IS_DEFAULT, account.mIsDefault); 1936 account.update(mMockContext, cv); 1937 } 1938 1939 public static Message setupUnreadMessage(String name, long accountId, long mailboxId, 1940 boolean addBody, boolean saveIt, Context context) { 1941 Message msg = 1942 ProviderTestUtils.setupMessage(name, accountId, mailboxId, addBody, false, context); 1943 msg.mFlagRead = false; 1944 if (saveIt) { 1945 msg.save(context); 1946 } 1947 return msg; 1948 } 1949 1950 public void testUnreadCountTriggers() { 1951 // Start with one account and three mailboxes 1952 Account account = ProviderTestUtils.setupAccount("triggers", true, mMockContext); 1953 Mailbox boxA = ProviderTestUtils.setupMailbox("boxA", account.mId, true, mMockContext); 1954 Mailbox boxB = ProviderTestUtils.setupMailbox("boxB", account.mId, true, mMockContext); 1955 Mailbox boxC = ProviderTestUtils.setupMailbox("boxC", account.mId, true, mMockContext); 1956 1957 // Make sure there are no unreads 1958 assertEquals(0, getUnreadCount(boxA.mId)); 1959 assertEquals(0, getUnreadCount(boxB.mId)); 1960 assertEquals(0, getUnreadCount(boxC.mId)); 1961 1962 // Create 4 unread messages (only 3 named) in boxA 1963 Message message1 = setupUnreadMessage("message1", account.mId, boxA.mId, 1964 false, true, mMockContext); 1965 Message message2= setupUnreadMessage("message2", account.mId, boxA.mId, 1966 false, true, mMockContext); 1967 Message message3 = setupUnreadMessage("message3", account.mId, boxA.mId, 1968 false, true, mMockContext); 1969 setupUnreadMessage("message4", account.mId, boxC.mId, false, true, mMockContext); 1970 1971 // Make sure the unreads are where we expect them 1972 assertEquals(3, getUnreadCount(boxA.mId)); 1973 assertEquals(0, getUnreadCount(boxB.mId)); 1974 assertEquals(1, getUnreadCount(boxC.mId)); 1975 1976 // After deleting message 1, the count in box A should be decremented (to 2) 1977 ContentResolver cr = mMockContext.getContentResolver(); 1978 Uri uri = ContentUris.withAppendedId(Message.CONTENT_URI, message1.mId); 1979 cr.delete(uri, null, null); 1980 assertEquals(2, getUnreadCount(boxA.mId)); 1981 assertEquals(0, getUnreadCount(boxB.mId)); 1982 assertEquals(1, getUnreadCount(boxC.mId)); 1983 1984 // Move message 2 to box B, leaving 1 in box A and 1 in box B 1985 message2.mMailboxKey = boxB.mId; 1986 ContentValues cv = new ContentValues(); 1987 cv.put(MessageColumns.MAILBOX_KEY, boxB.mId); 1988 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message2.mId), cv, null, null); 1989 assertEquals(1, getUnreadCount(boxA.mId)); 1990 assertEquals(1, getUnreadCount(boxB.mId)); 1991 assertEquals(1, getUnreadCount(boxC.mId)); 1992 1993 // Mark message 3 (from box A) read, leaving 0 in box A 1994 cv.clear(); 1995 cv.put(MessageColumns.FLAG_READ, 1); 1996 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message3.mId), cv, null, null); 1997 assertEquals(0, getUnreadCount(boxA.mId)); 1998 assertEquals(1, getUnreadCount(boxB.mId)); 1999 assertEquals(1, getUnreadCount(boxC.mId)); 2000 2001 // Move message 3 to box C; should be no change (it's read) 2002 message3.mMailboxKey = boxC.mId; 2003 cv.clear(); 2004 cv.put(MessageColumns.MAILBOX_KEY, boxC.mId); 2005 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message3.mId), cv, null, null); 2006 assertEquals(0, getUnreadCount(boxA.mId)); 2007 assertEquals(1, getUnreadCount(boxB.mId)); 2008 assertEquals(1, getUnreadCount(boxC.mId)); 2009 2010 // Mark message 3 unread; it's now in box C, so that box's count should go up to 3 2011 cv.clear(); 2012 cv.put(MessageColumns.FLAG_READ, 0); 2013 cr.update(ContentUris.withAppendedId(Message.CONTENT_URI, message3.mId), cv, null, null); 2014 assertEquals(0, getUnreadCount(boxA.mId)); 2015 assertEquals(1, getUnreadCount(boxB.mId)); 2016 assertEquals(2, getUnreadCount(boxC.mId)); 2017 } 2018 2019 /** 2020 * Test for EmailProvider.createIndex(). 2021 * Check that it returns exacly the same string as the one used previously for index creation. 2022 */ 2023 public void testCreateIndex() { 2024 String oldStr = "create index message_" + MessageColumns.TIMESTAMP 2025 + " on " + Message.TABLE_NAME + " (" + MessageColumns.TIMESTAMP + ");"; 2026 String newStr = EmailProvider.createIndex(Message.TABLE_NAME, MessageColumns.TIMESTAMP); 2027 assertEquals(newStr, oldStr); 2028 } 2029 2030 public void testDatabaseCorruptionRecovery() { 2031 final ContentResolver resolver = mMockContext.getContentResolver(); 2032 final Context context = mMockContext; 2033 2034 // Create account and two mailboxes 2035 Account acct = ProviderTestUtils.setupAccount("acct1", true, context); 2036 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", acct.mId, true, context); 2037 2038 // Create 4 messages in box1 with bodies 2039 ProviderTestUtils.setupMessage("message1", acct.mId, box1.mId, true, true, context); 2040 ProviderTestUtils.setupMessage("message2", acct.mId, box1.mId, true, true, context); 2041 ProviderTestUtils.setupMessage("message3", acct.mId, box1.mId, true, true, context); 2042 ProviderTestUtils.setupMessage("message4", acct.mId, box1.mId, true, true, context); 2043 2044 // Confirm there are four messages 2045 int count = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 2046 assertEquals(4, count); 2047 // Confirm there are four bodies 2048 count = EmailContent.count(mMockContext, Body.CONTENT_URI, null, null); 2049 assertEquals(4, count); 2050 2051 // Find the EmailProvider.db file 2052 File dbFile = mMockContext.getDatabasePath(EmailProvider.DATABASE_NAME); 2053 // The EmailProvider.db database should exist (the provider creates it automatically) 2054 assertTrue(dbFile != null); 2055 assertTrue(dbFile.exists()); 2056 // Delete it, and confirm it is gone 2057 assertTrue(dbFile.delete()); 2058 assertFalse(dbFile.exists()); 2059 2060 // Find the EmailProviderBody.db file 2061 dbFile = mMockContext.getDatabasePath(EmailProvider.BODY_DATABASE_NAME); 2062 // The EmailProviderBody.db database should still exist 2063 assertTrue(dbFile != null); 2064 assertTrue(dbFile.exists()); 2065 2066 // URI to uncache the databases 2067 // This simulates the Provider starting up again (otherwise, it will still be pointing to 2068 // the already opened files) 2069 // Note that we only have access to the EmailProvider via the ContentResolver; therefore, 2070 // we cannot directly call into the provider and use a URI for this 2071 resolver.update(EmailProvider.INTEGRITY_CHECK_URI, null, null, null); 2072 2073 // TODO We should check for the deletion of attachment files once this is implemented in 2074 // the provider 2075 2076 // Explanation for what happens below... 2077 // The next time the database is created by the provider, it will notice that there's 2078 // already a EmailProviderBody.db file. In this case, it will delete that database to 2079 // ensure that both are in sync (and empty) 2080 2081 // Confirm there are no bodies 2082 count = EmailContent.count(mMockContext, Body.CONTENT_URI, null, null); 2083 assertEquals(0, count); 2084 2085 // Confirm there are no messages 2086 count = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 2087 assertEquals(0, count); 2088 } 2089 2090 public void testBodyDatabaseCorruptionRecovery() { 2091 final ContentResolver resolver = mMockContext.getContentResolver(); 2092 final Context context = mMockContext; 2093 2094 // Create account and two mailboxes 2095 Account acct = ProviderTestUtils.setupAccount("acct1", true, context); 2096 Mailbox box1 = ProviderTestUtils.setupMailbox("box1", acct.mId, true, context); 2097 2098 // Create 4 messages in box1 with bodies 2099 ProviderTestUtils.setupMessage("message1", acct.mId, box1.mId, true, true, context); 2100 ProviderTestUtils.setupMessage("message2", acct.mId, box1.mId, true, true, context); 2101 ProviderTestUtils.setupMessage("message3", acct.mId, box1.mId, true, true, context); 2102 ProviderTestUtils.setupMessage("message4", acct.mId, box1.mId, true, true, context); 2103 2104 // Confirm there are four messages 2105 int count = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 2106 assertEquals(4, count); 2107 // Confirm there are four bodies 2108 count = EmailContent.count(mMockContext, Body.CONTENT_URI, null, null); 2109 assertEquals(4, count); 2110 2111 // Find the EmailProviderBody.db file 2112 File dbFile = mMockContext.getDatabasePath(EmailProvider.BODY_DATABASE_NAME); 2113 // The EmailProviderBody.db database should exist (the provider creates it automatically) 2114 assertTrue(dbFile != null); 2115 assertTrue(dbFile.exists()); 2116 // Delete it, and confirm it is gone 2117 assertTrue(dbFile.delete()); 2118 assertFalse(dbFile.exists()); 2119 2120 // Find the EmailProvider.db file 2121 dbFile = mMockContext.getDatabasePath(EmailProvider.DATABASE_NAME); 2122 // The EmailProviderBody.db database should still exist 2123 assertTrue(dbFile != null); 2124 assertTrue(dbFile.exists()); 2125 2126 // URI to uncache the databases 2127 // This simulates the Provider starting up again (otherwise, it will still be pointing to 2128 // the already opened files) 2129 // Note that we only have access to the EmailProvider via the ContentResolver; therefore, 2130 // we cannot directly call into the provider and use a URI for this 2131 resolver.update(EmailProvider.INTEGRITY_CHECK_URI, null, null, null); 2132 2133 // TODO We should check for the deletion of attachment files once this is implemented in 2134 // the provider 2135 2136 // Explanation for what happens below... 2137 // The next time the body database is created by the provider, it will notice that there's 2138 // already a populated EmailProvider.db file. In this case, it will delete that database to 2139 // ensure that both are in sync (and empty) 2140 2141 // Confirm there are no messages 2142 count = EmailContent.count(mMockContext, Message.CONTENT_URI, null, null); 2143 assertEquals(0, count); 2144 2145 // Confirm there are no bodies 2146 count = EmailContent.count(mMockContext, Body.CONTENT_URI, null, null); 2147 assertEquals(0, count); 2148 } 2149 2150 public void testFindMailboxOfType() { 2151 final Context context = mMockContext; 2152 2153 // Create two accounts and a variety of mailbox types 2154 Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context); 2155 Mailbox acct1Inbox = 2156 ProviderTestUtils.setupMailbox("Inbox1", acct1.mId, true, context, Mailbox.TYPE_INBOX); 2157 Mailbox acct1Calendar 2158 = ProviderTestUtils.setupMailbox("Cal1", acct1.mId, true, context, Mailbox.TYPE_CALENDAR); 2159 Mailbox acct1Contacts = 2160 ProviderTestUtils.setupMailbox("Con1", acct1.mId, true, context, Mailbox.TYPE_CONTACTS); 2161 Account acct2 = ProviderTestUtils.setupAccount("acct1", true, context); 2162 Mailbox acct2Inbox = 2163 ProviderTestUtils.setupMailbox("Inbox2", acct2.mId, true, context, Mailbox.TYPE_INBOX); 2164 Mailbox acct2Calendar = 2165 ProviderTestUtils.setupMailbox("Cal2", acct2.mId, true, context, Mailbox.TYPE_CALENDAR); 2166 Mailbox acct2Contacts = 2167 ProviderTestUtils.setupMailbox("Con2", acct2.mId, true, context, Mailbox.TYPE_CONTACTS); 2168 2169 // Check that we can find them by type 2170 assertEquals(acct1Inbox.mId, 2171 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX)); 2172 assertEquals(acct2Inbox.mId, 2173 Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_INBOX)); 2174 assertEquals(acct1Calendar.mId, 2175 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR)); 2176 assertEquals(acct2Calendar.mId, 2177 Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_CALENDAR)); 2178 assertEquals(acct1Contacts.mId, 2179 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS)); 2180 assertEquals(acct2Contacts.mId, 2181 Mailbox.findMailboxOfType(context, acct2.mId, Mailbox.TYPE_CONTACTS)); 2182 2183 // Check that nonexistent mailboxes are not returned 2184 assertEquals(Mailbox.NO_MAILBOX, 2185 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_DRAFTS)); 2186 assertEquals(Mailbox.NO_MAILBOX, 2187 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_OUTBOX)); 2188 2189 // delete account 1 and confirm no mailboxes are returned 2190 context.getContentResolver().delete( 2191 ContentUris.withAppendedId(Account.CONTENT_URI, acct1.mId), null, null); 2192 assertEquals(Mailbox.NO_MAILBOX, 2193 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX)); 2194 assertEquals(Mailbox.NO_MAILBOX, 2195 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR)); 2196 assertEquals(Mailbox.NO_MAILBOX, 2197 Mailbox.findMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS)); 2198 } 2199 2200 public void testRestoreMailboxOfType() { 2201 final Context context = mMockContext; 2202 2203 // Create two accounts and a variety of mailbox types 2204 Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context); 2205 Mailbox acct1Inbox = 2206 ProviderTestUtils.setupMailbox("Inbox1", acct1.mId, true, context, Mailbox.TYPE_INBOX); 2207 Mailbox acct1Calendar 2208 = ProviderTestUtils.setupMailbox("Cal1", acct1.mId, true, context, Mailbox.TYPE_CALENDAR); 2209 Mailbox acct1Contacts = 2210 ProviderTestUtils.setupMailbox("Con1", acct1.mId, true, context, Mailbox.TYPE_CONTACTS); 2211 Account acct2 = ProviderTestUtils.setupAccount("acct1", true, context); 2212 Mailbox acct2Inbox = 2213 ProviderTestUtils.setupMailbox("Inbox2", acct2.mId, true, context, Mailbox.TYPE_INBOX); 2214 Mailbox acct2Calendar = 2215 ProviderTestUtils.setupMailbox("Cal2", acct2.mId, true, context, Mailbox.TYPE_CALENDAR); 2216 Mailbox acct2Contacts = 2217 ProviderTestUtils.setupMailbox("Con2", acct2.mId, true, context, Mailbox.TYPE_CONTACTS); 2218 2219 // Check that we can find them by type 2220 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Inbox, 2221 Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_INBOX)); 2222 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Inbox, 2223 Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_INBOX)); 2224 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Calendar, 2225 Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_CALENDAR)); 2226 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Calendar, 2227 Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_CALENDAR)); 2228 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct1Contacts, 2229 Mailbox.restoreMailboxOfType(context, acct1.mId, Mailbox.TYPE_CONTACTS)); 2230 ProviderTestUtils.assertMailboxEqual("testRestoreMailboxOfType", acct2Contacts, 2231 Mailbox.restoreMailboxOfType(context, acct2.mId, Mailbox.TYPE_CONTACTS)); 2232 } 2233 2234 public void testAccountIsSecurityHold() { 2235 final Context context = mMockContext; 2236 Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context); 2237 2238 Account acct2 = ProviderTestUtils.setupAccount("acct2", false, context); 2239 acct2.mFlags |= Account.FLAGS_SECURITY_HOLD; 2240 acct2.save(context); 2241 2242 assertFalse(Account.isSecurityHold(context, acct1.mId)); 2243 assertTrue(Account.isSecurityHold(context, acct2.mId)); 2244 assertFalse(Account.isSecurityHold(context, 9999999)); // No such account 2245 } 2246 2247 public void testClearAccountHoldFlags() { 2248 Account a1 = ProviderTestUtils.setupAccount("holdflag-1", false, mMockContext); 2249 a1.mFlags = Account.FLAGS_NOTIFY_NEW_MAIL; 2250 a1.save(mMockContext); 2251 Account a2 = ProviderTestUtils.setupAccount("holdflag-2", false, mMockContext); 2252 a2.mFlags = Account.FLAGS_VIBRATE_ALWAYS | Account.FLAGS_SECURITY_HOLD; 2253 a2.save(mMockContext); 2254 2255 // bulk clear 2256 Account.clearSecurityHoldOnAllAccounts(mMockContext); 2257 2258 // confirm new values as expected - no hold flags; other flags unmolested 2259 Account a1a = Account.restoreAccountWithId(mMockContext, a1.mId); 2260 assertEquals(Account.FLAGS_NOTIFY_NEW_MAIL, a1a.mFlags); 2261 Account a2a = Account.restoreAccountWithId(mMockContext, a2.mId); 2262 assertEquals(Account.FLAGS_VIBRATE_ALWAYS, a2a.mFlags); 2263 } 2264 2265 /** 2266 * @return the number of messages in a mailbox. 2267 */ 2268 private int getMessageCount(long mailboxId) { 2269 return Utility.getFirstRowInt(mMockContext, 2270 ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId), 2271 new String[] {MailboxColumns.MESSAGE_COUNT}, null, null, null, 0); 2272 } 2273 2274 /** Set -1 to the message count of all mailboxes for the recalculateMessageCount test. */ 2275 private void setMinusOneToMessageCounts() { 2276 ContentValues values = new ContentValues(); 2277 values.put(MailboxColumns.MESSAGE_COUNT, -1); 2278 2279 // EmailProvider.update() doesn't allow updating messageCount, so directly use the DB. 2280 SQLiteDatabase db = getProvider().getDatabase(mMockContext); 2281 db.update(Mailbox.TABLE_NAME, values, null, null); 2282 } 2283 2284 /** 2285 * Test for the message count triggers (insert/delete/move mailbox), and also 2286 * {@link EmailProvider#recalculateMessageCount}. 2287 * 2288 * It also covers: 2289 * - {@link Mailbox#getMessageCountByMailboxType(Context, int)} 2290 * - {@link Mailbox#getUnreadCountByAccountAndMailboxType(Context, long, int)} 2291 * - {@link Mailbox#getUnreadCountByMailboxType(Context, int)} 2292 * - {@link Message#getFavoriteMessageCount(Context)} 2293 * - {@link Message#getFavoriteMessageCount(Context, long)} 2294 */ 2295 public void testMessageCount() { 2296 final Context c = mMockContext; 2297 2298 // Create 2 accounts 2299 Account a1 = ProviderTestUtils.setupAccount("holdflag-1", true, c); 2300 Account a2 = ProviderTestUtils.setupAccount("holdflag-2", true, c); 2301 2302 // Create 2 mailboxes for each account 2303 Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c, Mailbox.TYPE_INBOX); 2304 Mailbox b2 = ProviderTestUtils.setupMailbox("box2", a1.mId, true, c, Mailbox.TYPE_OUTBOX); 2305 Mailbox b3 = ProviderTestUtils.setupMailbox("box3", a2.mId, true, c, Mailbox.TYPE_INBOX); 2306 Mailbox b4 = ProviderTestUtils.setupMailbox("box4", a2.mId, true, c, Mailbox.TYPE_OUTBOX); 2307 Mailbox bt = ProviderTestUtils.setupMailbox("boxT", a2.mId, true, c, Mailbox.TYPE_TRASH); 2308 2309 // 0. Check the initial values, just in case. 2310 2311 assertEquals(0, getMessageCount(b1.mId)); 2312 assertEquals(0, getMessageCount(b2.mId)); 2313 assertEquals(0, getMessageCount(b3.mId)); 2314 assertEquals(0, getMessageCount(b4.mId)); 2315 assertEquals(0, getMessageCount(bt.mId)); 2316 2317 assertEquals(0, Message.getFavoriteMessageCount(c)); 2318 assertEquals(0, Message.getFavoriteMessageCount(c, a1.mId)); 2319 assertEquals(0, Message.getFavoriteMessageCount(c, a2.mId)); 2320 assertEquals(0, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_INBOX)); 2321 assertEquals(0, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_OUTBOX)); 2322 assertEquals(0, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_INBOX)); 2323 assertEquals(0, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_OUTBOX)); 2324 assertEquals(0, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_TRASH)); 2325 2326 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2327 a1.mId, Mailbox.TYPE_INBOX)); 2328 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2329 a1.mId, Mailbox.TYPE_OUTBOX)); 2330 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2331 a1.mId, Mailbox.TYPE_TRASH)); 2332 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2333 a2.mId, Mailbox.TYPE_INBOX)); 2334 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2335 a2.mId, Mailbox.TYPE_OUTBOX)); 2336 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2337 a2.mId, Mailbox.TYPE_TRASH)); 2338 2339 // 1. Test for insert triggers. 2340 2341 // Create some messages 2342 // b1 (account 1, inbox): 1 message, including 1 starred 2343 Message m11 = createMessage(c, b1, true, false, Message.FLAG_LOADED_COMPLETE); 2344 2345 // b2 (account 1, outbox): 2 message, including 1 starred 2346 Message m21 = createMessage(c, b2, false, false, Message.FLAG_LOADED_COMPLETE); 2347 Message m22 = createMessage(c, b2, true, true, Message.FLAG_LOADED_COMPLETE); 2348 2349 // b3 (account 2, inbox): 3 message, including 1 starred 2350 Message m31 = createMessage(c, b3, false, false, Message.FLAG_LOADED_COMPLETE); 2351 Message m32 = createMessage(c, b3, false, false, Message.FLAG_LOADED_COMPLETE); 2352 Message m33 = createMessage(c, b3, true, true, Message.FLAG_LOADED_COMPLETE); 2353 2354 // b4 (account 2, outbox) has no messages. 2355 2356 // bt (account 2, trash) has 3 messages, including 2 starred 2357 Message mt1 = createMessage(c, bt, true, false, Message.FLAG_LOADED_COMPLETE); 2358 Message mt2 = createMessage(c, bt, true, false, Message.FLAG_LOADED_COMPLETE); 2359 Message mt3 = createMessage(c, bt, false, false, Message.FLAG_LOADED_COMPLETE); 2360 2361 // Check message counts 2362 assertEquals(1, getMessageCount(b1.mId)); 2363 assertEquals(2, getMessageCount(b2.mId)); 2364 assertEquals(3, getMessageCount(b3.mId)); 2365 assertEquals(0, getMessageCount(b4.mId)); 2366 assertEquals(3, getMessageCount(bt.mId)); 2367 2368 // Check the simple counting methods. 2369 assertEquals(3, Message.getFavoriteMessageCount(c)); // excludes starred in trash 2370 assertEquals(2, Message.getFavoriteMessageCount(c, a1.mId)); 2371 assertEquals(1, Message.getFavoriteMessageCount(c, a2.mId)); // excludes starred in trash 2372 assertEquals(3, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_INBOX)); 2373 assertEquals(1, Mailbox.getUnreadCountByMailboxType(c, Mailbox.TYPE_OUTBOX)); 2374 assertEquals(4, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_INBOX)); 2375 assertEquals(2, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_OUTBOX)); 2376 assertEquals(3, Mailbox.getMessageCountByMailboxType(c, Mailbox.TYPE_TRASH)); 2377 2378 assertEquals(1, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2379 a1.mId, Mailbox.TYPE_INBOX)); 2380 assertEquals(1, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2381 a1.mId, Mailbox.TYPE_OUTBOX)); 2382 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2383 a1.mId, Mailbox.TYPE_TRASH)); 2384 assertEquals(2, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2385 a2.mId, Mailbox.TYPE_INBOX)); 2386 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2387 a2.mId, Mailbox.TYPE_OUTBOX)); 2388 assertEquals(3, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2389 a2.mId, Mailbox.TYPE_TRASH)); 2390 2391 // 2. test for recalculateMessageCount. 2392 2393 // First, invalidate the message counts. 2394 setMinusOneToMessageCounts(); 2395 assertEquals(-1, getMessageCount(b1.mId)); 2396 assertEquals(-1, getMessageCount(b2.mId)); 2397 assertEquals(-1, getMessageCount(b3.mId)); 2398 assertEquals(-1, getMessageCount(b4.mId)); 2399 2400 // Batch update. 2401 SQLiteDatabase db = getProvider().getDatabase(mMockContext); 2402 EmailProvider.recalculateMessageCount(db); 2403 2404 // Check message counts 2405 assertEquals(1, getMessageCount(b1.mId)); 2406 assertEquals(2, getMessageCount(b2.mId)); 2407 assertEquals(3, getMessageCount(b3.mId)); 2408 assertEquals(0, getMessageCount(b4.mId)); 2409 2410 // 3. Check the "move mailbox" trigger. 2411 2412 // Move m32 (in mailbox 3) to mailbox 4. 2413 ContentValues values = new ContentValues(); 2414 values.put(MessageColumns.MAILBOX_KEY, b4.mId); 2415 2416 getProvider().update(Message.CONTENT_URI, values, EmailContent.ID_SELECTION, 2417 new String[] {"" + m32.mId}); 2418 2419 // Check message counts 2420 assertEquals(1, getMessageCount(b1.mId)); 2421 assertEquals(2, getMessageCount(b2.mId)); 2422 assertEquals(2, getMessageCount(b3.mId)); 2423 assertEquals(1, getMessageCount(b4.mId)); 2424 2425 // 4. Check the delete trigger. 2426 2427 // Delete m11 (in mailbox 1) 2428 getProvider().delete(Message.CONTENT_URI, EmailContent.ID_SELECTION, 2429 new String[] {"" + m11.mId}); 2430 // Delete m21 (in mailbox 2) 2431 getProvider().delete(Message.CONTENT_URI, EmailContent.ID_SELECTION, 2432 new String[] {"" + m21.mId}); 2433 2434 // Check message counts 2435 assertEquals(0, getMessageCount(b1.mId)); 2436 assertEquals(1, getMessageCount(b2.mId)); 2437 assertEquals(2, getMessageCount(b3.mId)); 2438 assertEquals(1, getMessageCount(b4.mId)); 2439 2440 // No such mailbox type. 2441 assertEquals(0, Mailbox.getMessageCountByMailboxType(c, 99999)); 2442 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, a1.mId, 99999)); 2443 assertEquals(0, Mailbox.getUnreadCountByMailboxType(c, 99999)); 2444 2445 // No such account 2446 assertEquals(0, Mailbox.getUnreadCountByAccountAndMailboxType(c, 2447 99999, Mailbox.TYPE_INBOX)); 2448 } 2449 2450 private static Message createMessage(Context c, Mailbox b, boolean starred, boolean read) { 2451 return ProviderTestUtils.setupMessage( 2452 "1", b.mAccountKey, b.mId, true, true, c, starred, read); 2453 } 2454 2455 private static Message createMessage(Context c, Mailbox b, boolean starred, boolean read, 2456 int flagLoaded) { 2457 Message message = ProviderTestUtils.setupMessage( 2458 "1", b.mAccountKey, b.mId, true, false, c, starred, read); 2459 message.mFlagLoaded = flagLoaded; 2460 message.save(c); 2461 return message; 2462 } 2463 2464 public void testAccountIsEasAccount() { 2465 Account account = new Account(); 2466 // No hostauth 2467 assertFalse(account.isEasAccount(mMockContext)); 2468 2469 checkAccountIsEasAccount(null, false); 2470 checkAccountIsEasAccount("", false); 2471 checkAccountIsEasAccount("x", false); 2472 checkAccountIsEasAccount("eas", true); 2473 } 2474 2475 private void checkAccountIsEasAccount(String protocol, boolean expected) { 2476 Account account = ProviderTestUtils.setupAccount("account", false, mMockContext); 2477 account.mHostAuthRecv = ProviderTestUtils.setupHostAuth(protocol, "account-hostauth-recv", 2478 account.mId, false, mMockContext); 2479 account.save(mMockContext); 2480 assertEquals(expected, account.isEasAccount(mMockContext)); 2481 } 2482 2483 public void testGetKeyColumnLong() { 2484 final Context c = mMockContext; 2485 Account a = ProviderTestUtils.setupAccount("acct", true, c); 2486 Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a.mId, true, c, Mailbox.TYPE_MAIL); 2487 Mailbox b2 = ProviderTestUtils.setupMailbox("box2", a.mId, true, c, Mailbox.TYPE_MAIL); 2488 Message m1 = createMessage(c, b1, false, false); 2489 Message m2 = createMessage(c, b2, false, false); 2490 assertEquals(a.mId, Message.getKeyColumnLong(c, m1.mId, MessageColumns.ACCOUNT_KEY)); 2491 assertEquals(a.mId, Message.getKeyColumnLong(c, m2.mId, MessageColumns.ACCOUNT_KEY)); 2492 assertEquals(b1.mId, Message.getKeyColumnLong(c, m1.mId, MessageColumns.MAILBOX_KEY)); 2493 assertEquals(b2.mId, Message.getKeyColumnLong(c, m2.mId, MessageColumns.MAILBOX_KEY)); 2494 } 2495 2496 public void testGetAccountIdForMessageId() { 2497 final Context c = mMockContext; 2498 Account a1 = ProviderTestUtils.setupAccount("acct1", true, c); 2499 Account a2 = ProviderTestUtils.setupAccount("acct2", true, c); 2500 Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c, Mailbox.TYPE_MAIL); 2501 Mailbox b2 = ProviderTestUtils.setupMailbox("box2", a2.mId, true, c, Mailbox.TYPE_MAIL); 2502 Message m1 = createMessage(c, b1, false, false); 2503 Message m2 = createMessage(c, b2, false, false); 2504 2505 assertEquals(a1.mId, Account.getAccountIdForMessageId(c, m1.mId)); 2506 assertEquals(a2.mId, Account.getAccountIdForMessageId(c, m2.mId)); 2507 2508 // message desn't exist 2509 assertEquals(-1, Account.getAccountIdForMessageId(c, 12345)); 2510 } 2511 2512 public void testGetAccountMailboxFromMessageId() { 2513 final Context c = mMockContext; 2514 Account a = ProviderTestUtils.setupAccount("acct", true, c); 2515 Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a.mId, true, c, Mailbox.TYPE_MAIL); 2516 Mailbox b2 = ProviderTestUtils.setupMailbox("box2", a.mId, true, c, Mailbox.TYPE_MAIL); 2517 Message m1 = createMessage(c, b1, false, false); 2518 Message m2 = createMessage(c, b2, false, false); 2519 ProviderTestUtils.assertAccountEqual("x", a, Account.getAccountForMessageId(c, m1.mId)); 2520 ProviderTestUtils.assertAccountEqual("x", a, Account.getAccountForMessageId(c, m2.mId)); 2521 // Restore the mailboxes, since the unread & total counts will have changed 2522 b1 = Mailbox.restoreMailboxWithId(c, b1.mId); 2523 b2 = Mailbox.restoreMailboxWithId(c, b2.mId); 2524 ProviderTestUtils.assertMailboxEqual("x", b1, Mailbox.getMailboxForMessageId(c, m1.mId)); 2525 ProviderTestUtils.assertMailboxEqual("x", b2, Mailbox.getMailboxForMessageId(c, m2.mId)); 2526 } 2527 2528 public void testGetAccountGetInboxIdTest() { 2529 final Context c = mMockContext; 2530 2531 // Prepare some data with red-herrings. 2532 Account a1 = ProviderTestUtils.setupAccount("acct1", true, c); 2533 Account a2 = ProviderTestUtils.setupAccount("acct2", true, c); 2534 Mailbox b1i = ProviderTestUtils.setupMailbox("b1i", a1.mId, true, c, Mailbox.TYPE_INBOX); 2535 Mailbox b2a = ProviderTestUtils.setupMailbox("b2a", a2.mId, true, c, Mailbox.TYPE_MAIL); 2536 Mailbox b2i = ProviderTestUtils.setupMailbox("b2b", a2.mId, true, c, Mailbox.TYPE_INBOX); 2537 2538 assertEquals(b2i.mId, Account.getInboxId(c, a2.mId)); 2539 2540 // No account found. 2541 assertEquals(-1, Account.getInboxId(c, 999999)); 2542 } 2543 2544 public void testGetMailboxType() { 2545 final Context c = mMockContext; 2546 2547 Account a = ProviderTestUtils.setupAccount("acct1", true, c); 2548 Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX); 2549 Mailbox bm = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_MAIL); 2550 2551 assertEquals(Mailbox.TYPE_INBOX, Mailbox.getMailboxType(c, bi.mId)); 2552 assertEquals(Mailbox.TYPE_MAIL, Mailbox.getMailboxType(c, bm.mId)); 2553 assertEquals(-1, Mailbox.getMailboxType(c, 999999)); // mailbox not found 2554 } 2555 2556 public void testGetDisplayName() { 2557 final Context c = mMockContext; 2558 2559 Account a = ProviderTestUtils.setupAccount("acct1", true, c); 2560 Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX); 2561 Mailbox bm = ProviderTestUtils.setupMailbox("b2", a.mId, true, c, Mailbox.TYPE_MAIL); 2562 2563 assertEquals("b1", Mailbox.getDisplayName(c, bi.mId)); 2564 assertEquals("b2", Mailbox.getDisplayName(c, bm.mId)); 2565 assertEquals(null, Mailbox.getDisplayName(c, 999999)); // mailbox not found 2566 } 2567 2568 public void testMailboxIsRefreshable() { 2569 final Context c = mMockContext; 2570 2571 Account a = ProviderTestUtils.setupAccount("acct1", true, c); 2572 Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX); 2573 Mailbox bm = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_MAIL); 2574 Mailbox bd = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_DRAFTS); 2575 Mailbox bo = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_OUTBOX); 2576 2577 assertTrue(Mailbox.isRefreshable(c, bi.mId)); 2578 assertTrue(Mailbox.isRefreshable(c, bm.mId)); 2579 assertFalse(Mailbox.isRefreshable(c, bd.mId)); 2580 assertFalse(Mailbox.isRefreshable(c, bo.mId)); 2581 2582 // No such mailbox 2583 assertFalse(Mailbox.isRefreshable(c, 9999999)); 2584 2585 // Magic mailboxes can't be refreshed. 2586 assertFalse(Mailbox.isRefreshable(c, Mailbox.QUERY_ALL_DRAFTS)); 2587 assertFalse(Mailbox.isRefreshable(c, Mailbox.QUERY_ALL_INBOXES)); 2588 } 2589 2590 public void testMailboxCanMoveFrom() { 2591 final Context c = mMockContext; 2592 2593 Account a = ProviderTestUtils.setupAccount("acct1", true, c); 2594 Mailbox bi = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_INBOX); 2595 Mailbox bm = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_MAIL); 2596 Mailbox bd = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_DRAFTS); 2597 Mailbox bo = ProviderTestUtils.setupMailbox("b1", a.mId, true, c, Mailbox.TYPE_OUTBOX); 2598 2599 assertTrue(Mailbox.canMoveFrom(c, bi.mId)); 2600 assertTrue(Mailbox.canMoveFrom(c, bm.mId)); 2601 assertFalse(Mailbox.canMoveFrom(c, bd.mId)); 2602 assertFalse(Mailbox.canMoveFrom(c, bo.mId)); 2603 } 2604 2605 /** 2606 * Check if update to {@link Account#RESET_NEW_MESSAGE_COUNT_URI} resets the new message count. 2607 */ 2608 public void testResetNewMessageCount() { 2609 final Context c = mMockContext; 2610 final ContentResolver cr = c.getContentResolver(); 2611 2612 // Prepare test data 2613 Account a1 = ProviderTestUtils.setupAccount("acct1", false, c); 2614 a1.mNewMessageCount = 1; 2615 a1.save(c); 2616 Account a2 = ProviderTestUtils.setupAccount("acct2", false, c); 2617 a2.mNewMessageCount = 2; 2618 a2.save(c); 2619 Account a3 = ProviderTestUtils.setupAccount("acct3", false, c); 2620 a3.mNewMessageCount = 3; 2621 a3.save(c); 2622 Account a4 = ProviderTestUtils.setupAccount("acct4", false, c); 2623 a4.mNewMessageCount = 4; 2624 a4.save(c); 2625 Account a5 = ProviderTestUtils.setupAccount("acct5", false, c); 2626 a5.mNewMessageCount = 5; 2627 a5.save(c); 2628 2629 // With ID in URI, no selection 2630 cr.update(ContentUris.withAppendedId(Account.RESET_NEW_MESSAGE_COUNT_URI, a1.mId), 2631 null, null, null); 2632 assertEquals(0, Account.restoreAccountWithId(c, a1.mId).mNewMessageCount); 2633 assertEquals(2, Account.restoreAccountWithId(c, a2.mId).mNewMessageCount); 2634 assertEquals(3, Account.restoreAccountWithId(c, a3.mId).mNewMessageCount); 2635 assertEquals(4, Account.restoreAccountWithId(c, a4.mId).mNewMessageCount); 2636 assertEquals(5, Account.restoreAccountWithId(c, a5.mId).mNewMessageCount); 2637 2638 // No ID in URI, with selection 2639 cr.update(Account.RESET_NEW_MESSAGE_COUNT_URI, null, 2640 EmailContent.ID_SELECTION, new String[] {Long.toString(a2.mId)}); 2641 assertEquals(0, Account.restoreAccountWithId(c, a1.mId).mNewMessageCount); 2642 assertEquals(0, Account.restoreAccountWithId(c, a2.mId).mNewMessageCount); 2643 assertEquals(3, Account.restoreAccountWithId(c, a3.mId).mNewMessageCount); 2644 assertEquals(4, Account.restoreAccountWithId(c, a4.mId).mNewMessageCount); 2645 assertEquals(5, Account.restoreAccountWithId(c, a5.mId).mNewMessageCount); 2646 2647 // With ID, with selection 2648 cr.update(ContentUris.withAppendedId(Account.RESET_NEW_MESSAGE_COUNT_URI, a3.mId), null, 2649 EmailContent.ID_SELECTION, new String[] {Long.toString(a3.mId)}); 2650 assertEquals(0, Account.restoreAccountWithId(c, a1.mId).mNewMessageCount); 2651 assertEquals(0, Account.restoreAccountWithId(c, a2.mId).mNewMessageCount); 2652 assertEquals(0, Account.restoreAccountWithId(c, a3.mId).mNewMessageCount); 2653 assertEquals(4, Account.restoreAccountWithId(c, a4.mId).mNewMessageCount); 2654 assertEquals(5, Account.restoreAccountWithId(c, a5.mId).mNewMessageCount); 2655 2656 // No ID in URI, no selection 2657 cr.update(Account.RESET_NEW_MESSAGE_COUNT_URI, null, null, null); 2658 assertEquals(0, Account.restoreAccountWithId(c, a1.mId).mNewMessageCount); 2659 assertEquals(0, Account.restoreAccountWithId(c, a2.mId).mNewMessageCount); 2660 assertEquals(0, Account.restoreAccountWithId(c, a3.mId).mNewMessageCount); 2661 assertEquals(0, Account.restoreAccountWithId(c, a4.mId).mNewMessageCount); 2662 assertEquals(0, Account.restoreAccountWithId(c, a5.mId).mNewMessageCount); 2663 } 2664 2665 private static Message createMessageWithTimestamp(Context c, Mailbox b, long timestamp) { 2666 Message m = ProviderTestUtils.setupMessage("1", b.mAccountKey, b.mId, true, false, c, false, 2667 false); 2668 m.mTimeStamp = timestamp; 2669 m.save(c); 2670 return m; 2671 } 2672 2673 public void testMessageGetLatestIncomingMessage() { 2674 final Context c = mMockContext; 2675 2676 // Create 2 accounts with a inbox. 2677 Account a1 = ProviderTestUtils.setupAccount("a1", true, c); 2678 Account a2 = ProviderTestUtils.setupAccount("a2", true, c); 2679 2680 Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c, Mailbox.TYPE_INBOX); 2681 Mailbox b1d = ProviderTestUtils.setupMailbox("box1d", a1.mId, true, c, Mailbox.TYPE_DRAFTS); 2682 Mailbox b1o = ProviderTestUtils.setupMailbox("box1o", a1.mId, true, c, Mailbox.TYPE_OUTBOX); 2683 Mailbox b1s = ProviderTestUtils.setupMailbox("box1s", a1.mId, true, c, Mailbox.TYPE_SENT); 2684 Mailbox b2 = ProviderTestUtils.setupMailbox("box2", a2.mId, true, c, Mailbox.TYPE_MAIL); 2685 2686 // Create some messages 2687 Message m11 = createMessageWithTimestamp(c, b1, 33); 2688 Message m12 = createMessageWithTimestamp(c, b1, 10); 2689 Message m13 = createMessageWithTimestamp(c, b1, 1000); // latest incoming 2690 Message m1d = createMessageWithTimestamp(c, b1d, 2000); 2691 Message m1o = createMessageWithTimestamp(c, b1o, 2000); 2692 Message m1s = createMessageWithTimestamp(c, b1s, 2000); 2693 2694 Message m21 = createMessageWithTimestamp(c, b2, 99); // latest incoming 2695 Message m22 = createMessageWithTimestamp(c, b2, 1); 2696 Message m23 = createMessageWithTimestamp(c, b2, 2); 2697 2698 // Check! 2699 assertEquals(m13.mId, Message.getLatestIncomingMessage(c, a1.mId).mId); 2700 assertEquals(m21.mId, Message.getLatestIncomingMessage(c, a2.mId).mId); 2701 2702 // No such account 2703 assertEquals(null, Message.getLatestIncomingMessage(c, 9999999L)); 2704 } 2705 2706 /** 2707 * Check if update on ACCOUNT_ID_ADD_TO_FIELD updates the cache properly. 2708 */ 2709 public void testUpdateCacheAccountIdAddToField() { 2710 final Context c = mMockContext; 2711 Account a1 = ProviderTestUtils.setupAccount("a1", true, c); 2712 2713 int start = Account.restoreAccountWithId(c, a1.mId).mNewMessageCount; 2714 2715 // +1 to NEW_MESSAGE_COUNT 2716 ContentValues cv = new ContentValues(); 2717 cv.put(EmailContent.FIELD_COLUMN_NAME, AccountColumns.NEW_MESSAGE_COUNT); 2718 cv.put(EmailContent.ADD_COLUMN_NAME, 1); 2719 mProvider.update(ContentUris.withAppendedId(Account.ADD_TO_FIELD_URI, a1.mId), cv, 2720 null, null); 2721 2722 // Check 2723 assertEquals(start + 1, Account.restoreAccountWithId(c, a1.mId).mNewMessageCount); 2724 } 2725 2726 /** 2727 * Check if update on ACCOUNT_RESET_NEW_COUNT updates the cache properly. 2728 */ 2729 public void testUpdateCacheAccountResetNewCount() { 2730 final Context c = mMockContext; 2731 Account a1 = ProviderTestUtils.setupAccount("a1", true, c); 2732 2733 // precondition 2734 assertTrue(Account.restoreAccountWithId(c, a1.mId).mNewMessageCount > 0); 2735 2736 // Reset 2737 mProvider.update(Account.RESET_NEW_MESSAGE_COUNT_URI, null, null, null); 2738 2739 // Check 2740 assertEquals(0, Account.restoreAccountWithId(c, a1.mId).mNewMessageCount); 2741 } 2742 2743 /** 2744 * Check if update on ACCOUNT_RESET_NEW_COUNT_ID updates the cache properly. 2745 */ 2746 public void testUpdateCacheAccountResetNewCountId() { 2747 final Context c = mMockContext; 2748 Account a1 = ProviderTestUtils.setupAccount("a1", true, c); 2749 2750 // precondition 2751 assertTrue(Account.restoreAccountWithId(c, a1.mId).mNewMessageCount > 0); 2752 2753 // Reset 2754 mProvider.update(ContentUris.withAppendedId(Account.RESET_NEW_MESSAGE_COUNT_URI, a1.mId), 2755 null, null, null); 2756 2757 // Check 2758 assertEquals(0, Account.restoreAccountWithId(c, a1.mId).mNewMessageCount); 2759 } 2760 2761 /** 2762 * Check if update on MAILBOX_ID_ADD_TO_FIELD updates the cache properly. 2763 */ 2764 public void testUpdateCacheMailboxIdAddToField() { 2765 final Context c = mMockContext; 2766 Account a1 = ProviderTestUtils.setupAccount("a1", true, c); 2767 Mailbox b1 = ProviderTestUtils.setupMailbox("box1", a1.mId, true, c, Mailbox.TYPE_INBOX); 2768 2769 int start = Mailbox.restoreMailboxWithId(c, b1.mId).mSyncInterval; 2770 2771 // +1 to SYNC_INTERVAL 2772 ContentValues cv = new ContentValues(); 2773 cv.put(EmailContent.FIELD_COLUMN_NAME, MailboxColumns.SYNC_INTERVAL); 2774 cv.put(EmailContent.ADD_COLUMN_NAME, 1); 2775 mProvider.update(ContentUris.withAppendedId(Mailbox.ADD_TO_FIELD_URI, a1.mId), cv, 2776 null, null); 2777 2778 // Check 2779 assertEquals(start + 1, Mailbox.restoreMailboxWithId(c, b1.mId).mSyncInterval); 2780 } 2781 2782 /** 2783 * Check that we're handling illegal uri's properly (by throwing an exception unless it's a 2784 * query for an id of -1, in which case we return a zero-length cursor) 2785 */ 2786 public void testIllegalUri() { 2787 final ContentResolver cr = mMockContext.getContentResolver(); 2788 2789 ContentValues cv = new ContentValues(); 2790 Uri uri = Uri.parse("content://" + EmailContent.AUTHORITY + "/fooble"); 2791 try { 2792 cr.insert(uri, cv); 2793 fail("Insert should have thrown exception"); 2794 } catch (IllegalArgumentException e) { 2795 } 2796 try { 2797 cr.update(uri, cv, null, null); 2798 fail("Update should have thrown exception"); 2799 } catch (IllegalArgumentException e) { 2800 } 2801 try { 2802 cr.delete(uri, null, null); 2803 fail("Delete should have thrown exception"); 2804 } catch (IllegalArgumentException e) { 2805 } 2806 try { 2807 cr.query(uri, EmailContent.ID_PROJECTION, null, null, null); 2808 fail("Query should have thrown exception"); 2809 } catch (IllegalArgumentException e) { 2810 } 2811 uri = Uri.parse("content://" + EmailContent.AUTHORITY + "/mailbox/fred"); 2812 try { 2813 cr.query(uri, EmailContent.ID_PROJECTION, null, null, null); 2814 fail("Query should have thrown exception"); 2815 } catch (IllegalArgumentException e) { 2816 } 2817 uri = Uri.parse("content://" + EmailContent.AUTHORITY + "/mailbox/-1"); 2818 Cursor c = cr.query(uri, EmailContent.ID_PROJECTION, null, null, null); 2819 assertNotNull(c); 2820 assertEquals(0, c.getCount()); 2821 c.close(); 2822 } 2823} 2824