• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.exchange;
18 
19 import android.accounts.Account;
20 import android.accounts.AccountManager;
21 import android.accounts.AccountManagerFuture;
22 import android.accounts.AuthenticatorException;
23 import android.accounts.OperationCanceledException;
24 import android.app.NotificationManager;
25 import android.content.ContentResolver;
26 import android.content.Context;
27 import android.database.Cursor;
28 import android.provider.CalendarContract;
29 import android.test.MoreAsserts;
30 import android.test.suitebuilder.annotation.MediumTest;
31 import android.text.TextUtils;
32 import android.util.Log;
33 
34 import com.android.emailcommon.AccountManagerTypes;
35 import com.android.emailcommon.Logging;
36 import com.android.exchange.utility.ExchangeTestCase;
37 
38 import java.io.IOException;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.HashMap;
42 import java.util.HashSet;
43 @MediumTest
44 public class CalendarSyncEnablerTest extends ExchangeTestCase {
45 
46     protected static final String TEST_ACCOUNT_PREFIX = "__test";
47     protected static final String TEST_ACCOUNT_SUFFIX = "@android.com";
48 
49     private HashMap<Account, Boolean> origCalendarSyncStates = new HashMap<Account, Boolean>();
50 
51     // To make the rest of the code shorter thus more readable...
52     private static final String EAT = AccountManagerTypes.TYPE_EXCHANGE;
53 
54     @Override
setUp()55     public void setUp() throws Exception {
56         super.setUp();
57         // Delete any test accounts we might have created earlier
58         deleteTemporaryAccountManagerAccounts();
59 
60         // Save the original calendar sync states.
61         for (Account account : AccountManager.get(getContext()).getAccounts()) {
62             origCalendarSyncStates.put(account,
63                     ContentResolver.getSyncAutomatically(account, CalendarContract.AUTHORITY));
64         }
65     }
66 
67     @Override
tearDown()68     public void tearDown() throws Exception {
69         super.tearDown();
70         // Delete any test accounts we might have created earlier
71         deleteTemporaryAccountManagerAccounts();
72 
73         // Restore the original calendar sync states.
74         // Note we restore only for Exchange accounts.
75         // Other accounts should remain intact throughout the tests.  Plus we don't know if the
76         // Calendar.AUTHORITY is supported by other types of accounts.
77         for (Account account : getExchangeAccounts()) {
78             Boolean state = origCalendarSyncStates.get(account);
79             if (state == null) continue; // Shouldn't happen, but just in case.
80 
81             ContentResolver.setSyncAutomatically(account, CalendarContract.AUTHORITY, state);
82         }
83     }
84 
testEnableEasCalendarSync()85     public void testEnableEasCalendarSync() {
86         final Account[] baseAccounts = getExchangeAccounts();
87 
88         String a1 = getTestAccountEmailAddress("1");
89         String a2 = getTestAccountEmailAddress("2");
90 
91         // 1. Test with 1 account
92 
93         CalendarSyncEnabler enabler = new CalendarSyncEnabler(getContext());
94 
95         // Add exchange accounts
96         createAccountManagerAccount(a1);
97 
98         String emailAddresses = enabler.enableEasCalendarSyncInternalForTest();
99 
100         // Verify
101         verifyCalendarSyncState();
102 
103         // There seems to be no good way to examine the contents of Notification, so let's verify
104         // we at least (tried to) show the correct email addresses.
105         checkNotificationEmailAddresses(emailAddresses, baseAccounts, a1);
106 
107         // Delete added account.
108         deleteTemporaryAccountManagerAccounts();
109 
110         // 2. Test with 2 accounts
111         enabler = new CalendarSyncEnabler(getContext());
112 
113         // Add exchange accounts
114         createAccountManagerAccount(a1);
115         createAccountManagerAccount(a2);
116 
117         emailAddresses = enabler.enableEasCalendarSyncInternalForTest();
118 
119         // Verify
120         verifyCalendarSyncState();
121 
122         // Check
123         checkNotificationEmailAddresses(emailAddresses, baseAccounts, a1, a2);
124     }
125 
checkNotificationEmailAddresses(String actual, Account[] baseAccounts, String... addedAddresses)126     private static void checkNotificationEmailAddresses(String actual, Account[] baseAccounts,
127             String... addedAddresses) {
128         // Build and sort actual string array.
129         final String[] actualArray = TextUtils.split(actual, " ");
130         Arrays.sort(actualArray);
131 
132         // Build and sort expected string array.
133         ArrayList<String> expected = new ArrayList<String>();
134         for (Account account : baseAccounts) {
135             expected.add(account.name);
136         }
137         for (String address : addedAddresses) {
138             expected.add(address);
139         }
140         final String[] expectedArray = new String[expected.size()];
141         expected.toArray(expectedArray);
142         Arrays.sort(expectedArray);
143 
144         // Check!
145         MoreAsserts.assertEquals(expectedArray, actualArray);
146     }
147 
148     /**
149      * For all {@link Account}, confirm that:
150      * <ol>
151      *   <li>Calendar sync is enabled if it's an Exchange account.<br>
152      *       Unfortunately setSyncAutomatically() doesn't take effect immediately, so we skip this
153      *       check for now.
154              TODO Find a stable way to check this.
155      *   <li>Otherwise, calendar sync state isn't changed.
156      * </ol>
157      */
verifyCalendarSyncState()158     private void verifyCalendarSyncState() {
159         // It's very unfortunate that setSyncAutomatically doesn't take effect immediately.
160         for (Account account : AccountManager.get(getContext()).getAccounts()) {
161             String message = "account=" + account.name + "(" + account.type + ")";
162             boolean enabled = ContentResolver.getSyncAutomatically(account,
163                     CalendarContract.AUTHORITY);
164             int syncable = ContentResolver.getIsSyncable(account, CalendarContract.AUTHORITY);
165 
166             if (EAT.equals(account.type)) {
167                 // Should be enabled.
168                 // assertEquals(message, Boolean.TRUE, (Boolean) enabled);
169                 // assertEquals(message, 1, syncable);
170             } else {
171                 // Shouldn't change.
172                 assertEquals(message, origCalendarSyncStates.get(account), (Boolean) enabled);
173             }
174         }
175     }
176 
testEnableEasCalendarSyncWithNoExchangeAccounts()177     public void testEnableEasCalendarSyncWithNoExchangeAccounts() {
178         // This test can only meaningfully run when there's no exchange accounts
179         // set up on the device.  Otherwise there'll be no difference from
180         // testEnableEasCalendarSync.
181         if (AccountManager.get(getContext()).getAccountsByType(EAT).length > 0) {
182             Log.w(Logging.LOG_TAG, "testEnableEasCalendarSyncWithNoExchangeAccounts skipped:"
183                     + " It only runs when there's no Exchange account on the device.");
184             return;
185         }
186         CalendarSyncEnabler enabler = new CalendarSyncEnabler(getContext());
187         String emailAddresses = enabler.enableEasCalendarSyncInternalForTest();
188 
189         // Verify (nothing should change)
190         verifyCalendarSyncState();
191 
192         // No exchange accounts found.
193         assertEquals(0, emailAddresses.length());
194     }
195 
testShowNotification()196     public void testShowNotification() {
197         CalendarSyncEnabler enabler = new CalendarSyncEnabler(getContext());
198 
199         // We can't really check the result, but at least we can make sure it won't crash....
200         enabler.showNotificationForTest("a@b.com");
201 
202         // Remove the notification.  Comment it out when you want to know how it looks like.
203         // TODO If NotificationController supports this notification, we can just mock it out
204         // and remove this code.
205         ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE))
206                 .cancel(CalendarSyncEnabler.NOTIFICATION_ID_EXCHANGE_CALENDAR_ADDED);
207     }
208 
getExchangeAccounts()209     protected Account[] getExchangeAccounts() {
210         return AccountManager.get(getContext()).getAccountsByType(
211                 AccountManagerTypes.TYPE_EXCHANGE);
212     }
213 
makeAccountManagerAccount(String username)214     protected Account makeAccountManagerAccount(String username) {
215         return new Account(username, AccountManagerTypes.TYPE_EXCHANGE);
216     }
217 
createAccountManagerAccount(String username)218     protected void createAccountManagerAccount(String username) {
219         final Account account = makeAccountManagerAccount(username);
220         AccountManager.get(getContext()).addAccountExplicitly(account, "password", null);
221     }
222 
223     protected com.android.emailcommon.provider.Account
setupProviderAndAccountManagerAccount(String username)224         setupProviderAndAccountManagerAccount(String username) {
225         // Note that setupAccount creates the email address username@android.com, so that's what
226         // we need to use for the account manager
227         createAccountManagerAccount(username + TEST_ACCOUNT_SUFFIX);
228         return setupTestAccount(username, true);
229     }
230 
makeExchangeServiceAccountList()231     protected ArrayList<com.android.emailcommon.provider.Account> makeExchangeServiceAccountList() {
232         ArrayList<com.android.emailcommon.provider.Account> accountList =
233             new ArrayList<com.android.emailcommon.provider.Account>();
234         Cursor c = mProviderContext.getContentResolver().query(
235                 com.android.emailcommon.provider.Account.CONTENT_URI,
236                 com.android.emailcommon.provider.Account.CONTENT_PROJECTION, null, null, null);
237         try {
238             while (c.moveToNext()) {
239                 com.android.emailcommon.provider.Account account =
240                     new com.android.emailcommon.provider.Account();
241                 account.restore(c);
242                 accountList.add(account);
243             }
244         } finally {
245             c.close();
246         }
247         return accountList;
248     }
249 
deleteAccountManagerAccount(Account account)250     protected void deleteAccountManagerAccount(Account account) {
251         AccountManagerFuture<Boolean> future =
252             AccountManager.get(getContext()).removeAccount(account, null, null);
253         try {
254             future.getResult();
255         } catch (OperationCanceledException e) {
256         } catch (AuthenticatorException e) {
257         } catch (IOException e) {
258         }
259     }
260 
deleteTemporaryAccountManagerAccounts()261     protected void deleteTemporaryAccountManagerAccounts() {
262         for (Account accountManagerAccount: getExchangeAccounts()) {
263             if (accountManagerAccount.name.startsWith(TEST_ACCOUNT_PREFIX) &&
264                     accountManagerAccount.name.endsWith(TEST_ACCOUNT_SUFFIX)) {
265                 deleteAccountManagerAccount(accountManagerAccount);
266             }
267         }
268     }
269 
getTestAccountName(String name)270     protected String getTestAccountName(String name) {
271         return TEST_ACCOUNT_PREFIX + name;
272     }
273 
getTestAccountEmailAddress(String name)274     protected String getTestAccountEmailAddress(String name) {
275         return TEST_ACCOUNT_PREFIX + name + TEST_ACCOUNT_SUFFIX;
276     }
277 
278 
279     /**
280      * Helper to retrieve account manager accounts *and* remove any preexisting accounts
281      * from the list, to "hide" them from the reconciler.
282      */
getAccountManagerAccounts(Account[] baseline)283     protected Account[] getAccountManagerAccounts(Account[] baseline) {
284         Account[] rawList = getExchangeAccounts();
285         if (baseline.length == 0) {
286             return rawList;
287         }
288         HashSet<Account> set = new HashSet<Account>();
289         for (Account addAccount : rawList) {
290             set.add(addAccount);
291         }
292         for (Account removeAccount : baseline) {
293             set.remove(removeAccount);
294         }
295         return set.toArray(new Account[0]);
296     }
297 }
298