Home | History | Annotate | Download | only in exchange
      1 /*
      2  * Copyright (C) 2009 Marc Blank
      3  * Licensed to The Android Open Source Project.
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package com.android.exchange;
     19 
     20 import com.android.email.AccountTestCase;
     21 import com.android.email.Email;
     22 import com.android.email.provider.EmailContent;
     23 import com.android.email.provider.EmailProvider;
     24 import com.android.email.provider.ProviderTestUtils;
     25 import com.android.email.provider.EmailContent.Account;
     26 import com.android.email.provider.EmailContent.Mailbox;
     27 import com.android.exchange.SyncManager.SyncError;
     28 
     29 import android.accounts.AccountManager;
     30 import android.content.ContentResolver;
     31 import android.content.ContentUris;
     32 import android.content.Context;
     33 
     34 import java.util.HashMap;
     35 
     36 /**
     37  * You can run this entire test case with:
     38  *   runtest -c com.android.exchange.SyncManagerAccountTests email
     39  */
     40 public class SyncManagerAccountTests extends AccountTestCase {
     41 
     42     EmailProvider mProvider;
     43     Context mMockContext;
     44 
     45     public SyncManagerAccountTests() {
     46         super();
     47     }
     48 
     49     @Override
     50     public void setUp() throws Exception {
     51         super.setUp();
     52         mMockContext = getMockContext();
     53         // Delete any test accounts we might have created earlier
     54         deleteTemporaryAccountManagerAccounts();
     55     }
     56 
     57     @Override
     58     public void tearDown() throws Exception {
     59         super.tearDown();
     60         // Delete any test accounts we might have created earlier
     61         deleteTemporaryAccountManagerAccounts();
     62     }
     63 
     64     /**
     65      * Confirm that the test below is functional (and non-destructive) when there are
     66      * prexisting (non-test) accounts in the account manager.
     67      */
     68     public void testTestReconcileAccounts() {
     69         Account firstAccount = null;
     70         final String TEST_USER_ACCOUNT = "__user_account_test_1";
     71         Context context = getContext();
     72         try {
     73             // Note:  Unlike calls to setupProviderAndAccountManagerAccount(), we are creating
     74             // *real* accounts here (not in the mock provider)
     75             createAccountManagerAccount(TEST_USER_ACCOUNT + TEST_ACCOUNT_SUFFIX);
     76             firstAccount = ProviderTestUtils.setupAccount(TEST_USER_ACCOUNT, true, context);
     77             // Now run the test with the "user" accounts in place
     78             testReconcileAccounts();
     79         } finally {
     80             if (firstAccount != null) {
     81                 boolean firstAccountFound = false;
     82                 // delete the provider account
     83                 context.getContentResolver().delete(firstAccount.getUri(), null, null);
     84                 // delete the account manager account
     85                 android.accounts.Account[] accountManagerAccounts = AccountManager.get(context)
     86                         .getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
     87                 for (android.accounts.Account accountManagerAccount: accountManagerAccounts) {
     88                     if ((TEST_USER_ACCOUNT + TEST_ACCOUNT_SUFFIX)
     89                             .equals(accountManagerAccount.name)) {
     90                         deleteAccountManagerAccount(accountManagerAccount);
     91                         firstAccountFound = true;
     92                     }
     93                 }
     94                 assertTrue(firstAccountFound);
     95             }
     96         }
     97     }
     98 
     99     /**
    100      * Note, there is some inherent risk in this test, as it creates *real* accounts in the
    101      * system (it cannot use the mock context with the Account Manager).
    102      */
    103     public void testReconcileAccounts() {
    104         // Note that we can't use mMockContext for AccountManager interactions, as it isn't a fully
    105         // functional Context.
    106         Context context = getContext();
    107 
    108         // Capture the baseline (account manager accounts) so we can measure the changes
    109         // we're making, irrespective of the number of actual accounts, and not destroy them
    110         android.accounts.Account[] baselineAccounts =
    111             AccountManager.get(context).getAccountsByType(Email.EXCHANGE_ACCOUNT_MANAGER_TYPE);
    112 
    113         // Set up three accounts, both in AccountManager and in EmailProvider
    114         Account firstAccount = setupProviderAndAccountManagerAccount(getTestAccountName("1"));
    115         setupProviderAndAccountManagerAccount(getTestAccountName("2"));
    116         setupProviderAndAccountManagerAccount(getTestAccountName("3"));
    117 
    118         // Check that they're set up properly
    119         assertEquals(3, EmailContent.count(mMockContext, Account.CONTENT_URI, null, null));
    120         android.accounts.Account[] accountManagerAccounts =
    121                 getAccountManagerAccounts(baselineAccounts);
    122         assertEquals(3, accountManagerAccounts.length);
    123 
    124         // Delete account "2" from AccountManager
    125         android.accounts.Account removedAccount =
    126             makeAccountManagerAccount(getTestAccountEmailAddress("2"));
    127         deleteAccountManagerAccount(removedAccount);
    128 
    129         // Confirm it's deleted
    130         accountManagerAccounts = getAccountManagerAccounts(baselineAccounts);
    131         assertEquals(2, accountManagerAccounts.length);
    132 
    133         // Run the reconciler
    134         ContentResolver resolver = mMockContext.getContentResolver();
    135         SyncManager.reconcileAccountsWithAccountManager(context,
    136                 makeSyncManagerAccountList(), accountManagerAccounts, true, resolver);
    137 
    138         // There should now be only two EmailProvider accounts
    139         assertEquals(2, EmailContent.count(mMockContext, Account.CONTENT_URI, null, null));
    140 
    141         // Ok, now we've got two of each; let's delete a provider account
    142         resolver.delete(ContentUris.withAppendedId(Account.CONTENT_URI, firstAccount.mId),
    143                 null, null);
    144         // ...and then there was one
    145         assertEquals(1, EmailContent.count(mMockContext, Account.CONTENT_URI, null, null));
    146 
    147         // Run the reconciler
    148         SyncManager.reconcileAccountsWithAccountManager(context,
    149                 makeSyncManagerAccountList(), accountManagerAccounts, true, resolver);
    150 
    151         // There should now be only one AccountManager account
    152         accountManagerAccounts = getAccountManagerAccounts(baselineAccounts);
    153         assertEquals(1, accountManagerAccounts.length);
    154         // ... and it should be account "3"
    155         assertEquals(getTestAccountEmailAddress("3"), accountManagerAccounts[0].name);
    156     }
    157 
    158     public void testReleaseSyncHolds() {
    159         Context context = mMockContext;
    160         SyncManager syncManager = new SyncManager();
    161         SyncError securityErrorAccount1 =
    162             syncManager.new SyncError(AbstractSyncService.EXIT_SECURITY_FAILURE, false);
    163         SyncError ioError =
    164             syncManager.new SyncError(AbstractSyncService.EXIT_IO_ERROR, false);
    165         SyncError securityErrorAccount2 =
    166             syncManager.new SyncError(AbstractSyncService.EXIT_SECURITY_FAILURE, false);
    167         // Create account and two mailboxes
    168         Account acct1 = ProviderTestUtils.setupAccount("acct1", true, context);
    169         Mailbox box1 = ProviderTestUtils.setupMailbox("box1", acct1.mId, true, context);
    170         Mailbox box2 = ProviderTestUtils.setupMailbox("box2", acct1.mId, true, context);
    171         Account acct2 = ProviderTestUtils.setupAccount("acct2", true, context);
    172         Mailbox box3 = ProviderTestUtils.setupMailbox("box3", acct2.mId, true, context);
    173         Mailbox box4 = ProviderTestUtils.setupMailbox("box4", acct2.mId, true, context);
    174 
    175         HashMap<Long, SyncError> errorMap = syncManager.mSyncErrorMap;
    176         // Add errors into the map
    177         errorMap.put(box1.mId, securityErrorAccount1);
    178         errorMap.put(box2.mId, ioError);
    179         errorMap.put(box3.mId, securityErrorAccount2);
    180         errorMap.put(box4.mId, securityErrorAccount2);
    181         // We should have 4
    182         assertEquals(4, errorMap.keySet().size());
    183         // Release the holds on acct2 (there are two of them)
    184         syncManager.releaseSyncHolds(context, AbstractSyncService.EXIT_SECURITY_FAILURE, acct2);
    185         // There should be two left
    186         assertEquals(2, errorMap.keySet().size());
    187         // And these are the two...
    188         assertNotNull(errorMap.get(box2.mId));
    189         assertNotNull(errorMap.get(box1.mId));
    190 
    191         // Put the two back
    192         errorMap.put(box3.mId, securityErrorAccount2);
    193         errorMap.put(box4.mId, securityErrorAccount2);
    194         // We should have 4 again
    195         assertEquals(4, errorMap.keySet().size());
    196         // Release all of the security holds
    197         syncManager.releaseSyncHolds(context, AbstractSyncService.EXIT_SECURITY_FAILURE, null);
    198         // There should be one left
    199         assertEquals(1, errorMap.keySet().size());
    200         // And this is the one
    201         assertNotNull(errorMap.get(box2.mId));
    202 
    203         // Release the i/o holds on account 2 (there aren't any)
    204         syncManager.releaseSyncHolds(context, AbstractSyncService.EXIT_IO_ERROR, acct2);
    205         // There should still be one left
    206         assertEquals(1, errorMap.keySet().size());
    207 
    208         // Release the i/o holds on account 1 (there's one)
    209         syncManager.releaseSyncHolds(context, AbstractSyncService.EXIT_IO_ERROR, acct1);
    210         // There should still be one left
    211         assertEquals(0, errorMap.keySet().size());
    212     }
    213 
    214 }
    215