Harden MailService against half-created accounts

* Add simple sanity checks to scanned accounts, skip over if bad
* Fix existing unit tests and add new unit test for this change
* Also fixed minor bug in EmailContent that was never triggered in
  production code (only discovered it via a unit test).
* Also fixed minor bug in an existing unit test

Bug: 2937595
Change-Id: Id60bbb5d8bd923db043d46891c7f89d7debb0a11
This commit is contained in:
Andy Stadler 2011-01-06 12:53:40 -08:00
parent 2f1a7e8d0a
commit 201a24f51e
3 changed files with 58 additions and 3 deletions

View File

@ -1648,7 +1648,7 @@ public abstract class EmailContent {
}
if (mHostAuthSend != null) {
sendIndex = index++;
ops.add(ContentProviderOperation.newInsert(mHostAuthRecv.mBaseUri)
ops.add(ContentProviderOperation.newInsert(mHostAuthSend.mBaseUri)
.withValues(mHostAuthSend.toContentValues())
.build());
}

View File

@ -52,6 +52,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import java.io.IOException;
@ -596,8 +597,18 @@ public class MailService extends Service {
Cursor c = resolver.query(uri, Account.CONTENT_PROJECTION, null, null, null);
try {
while (c.moveToNext()) {
AccountSyncReport report = new AccountSyncReport();
Account account = Account.getContent(c, Account.class);
// The following sanity checks are primarily for the sake of ignoring non-user
// accounts that may have been left behind e.g. by failed unit tests.
// Properly-formed accounts will always pass these simple checks.
if (TextUtils.isEmpty(account.mEmailAddress)
|| account.mHostAuthKeyRecv <= 0
|| account.mHostAuthKeySend <= 0) {
continue;
}
// The account is OK, so proceed
AccountSyncReport report = new AccountSyncReport();
int syncInterval = account.mSyncInterval;
// If we're not using MessagingController (EAS at this point), don't schedule syncs

View File

@ -105,7 +105,8 @@ public class MailServiceTests extends AccountTestCase {
* from the UI thread); it shouldn't crash
*/
public void testThrashOnAccountsUpdated() {
final MailService mailService = MailService.getMailServiceForTest();
final MailService mailService = new MailService();
mailService.mController = new TestController(mMockContext, getContext());
assertNotNull(mailService);
final android.accounts.Account[] accounts = getExchangeAccounts();
Utility.runAsync(new Runnable() {
@ -203,14 +204,17 @@ public class MailServiceTests extends AccountTestCase {
// Setup accounts of each type, all with manual sync at different intervals
Account easAccount = ProviderTestUtils.setupAccount("account1", false, mMockContext);
easAccount.mHostAuthRecv = setupSimpleHostAuth("eas");
easAccount.mHostAuthSend = easAccount.mHostAuthRecv;
easAccount.mSyncInterval = 30;
easAccount.save(mMockContext);
Account imapAccount = ProviderTestUtils.setupAccount("account2", false, mMockContext);
imapAccount.mHostAuthRecv = setupSimpleHostAuth("imap");
imapAccount.mHostAuthSend = setupSimpleHostAuth("smtp");
imapAccount.mSyncInterval = 60;
imapAccount.save(mMockContext);
Account pop3Account = ProviderTestUtils.setupAccount("account3", false, mMockContext);
pop3Account.mHostAuthRecv = setupSimpleHostAuth("pop3");
pop3Account.mHostAuthSend = setupSimpleHostAuth("smtp");
pop3Account.mSyncInterval = 90;
pop3Account.save(mMockContext);
@ -249,4 +253,44 @@ public class MailServiceTests extends AccountTestCase {
mailService.mController.cleanupForTest();
}
}
/**
* Test that setupSyncReports will skip over poorly-formed accounts which can be left
* over after unit tests.
*/
public void testSetupSyncReportsWithBadAccounts() {
// Setup accounts that trigger each skip-over case
// 1: no email address
Account account1 = ProviderTestUtils.setupAccount("account1", false, mMockContext);
account1.mHostAuthRecv = setupSimpleHostAuth("imap");
account1.mHostAuthSend = setupSimpleHostAuth("smtp");
account1.mSyncInterval = 30;
account1.mEmailAddress = null;
account1.save(mMockContext);
// 2: no receiver hostauth
Account account2 = ProviderTestUtils.setupAccount("account2", false, mMockContext);
account2.mHostAuthRecv = null;
account2.mHostAuthSend = setupSimpleHostAuth("smtp");
account2.mSyncInterval = 30;
account2.save(mMockContext);
// 3: no sender hostauth
Account account3 = ProviderTestUtils.setupAccount("account3", false, mMockContext);
account3.mHostAuthRecv = setupSimpleHostAuth("imap");
account3.mHostAuthSend = null;
account3.mSyncInterval = 30;
account3.save(mMockContext);
// Setup the SyncReport's for these Accounts
MailService mailService = new MailService();
mailService.mController = new TestController(mMockContext, getContext());
try {
mailService.setupSyncReportsLocked(MailService.SYNC_REPORTS_RESET, mMockContext);
// Get back the map created by MailService - it should be empty
HashMap<Long, AccountSyncReport> syncReportMap = MailService.mSyncReports;
assertEquals(0, syncReportMap.size());
} finally {
mailService.mController.cleanupForTest();
}
}
}