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.email; 18 19 import com.android.email.provider.EmailContent; 20 import com.android.email.provider.EmailProvider; 21 import com.android.email.provider.ProviderTestUtils; 22 23 import android.content.Context; 24 import android.database.Cursor; 25 import android.test.ProviderTestCase2; 26 import android.test.suitebuilder.annotation.MediumTest; 27 28 /** 29 * This is a series of unit tests for backup/restore of the Account class. 30 * 31 * Technically these are functional because they use the underlying preferences framework. 32 * 33 * NOTE: These tests are destructive of any "legacy" accounts that might be lying around. 34 */ 35 @MediumTest 36 public class AccountBackupRestoreTests extends ProviderTestCase2<EmailProvider> { 37 38 private Preferences mPreferences; 39 private Context mMockContext; 40 41 public AccountBackupRestoreTests() { 42 super(EmailProvider.class, EmailProvider.EMAIL_AUTHORITY); 43 } 44 45 @Override 46 protected void setUp() throws Exception { 47 super.setUp(); 48 49 mMockContext = getMockContext(); 50 // Note: preferences are not supported by this mock context, so we must 51 // explicitly use (and clean out) the real ones for now. 52 mPreferences = Preferences.getPreferences(mContext); 53 } 54 55 /** 56 * Delete any dummy accounts we set up for this test 57 */ 58 @Override 59 protected void tearDown() throws Exception { 60 super.tearDown(); 61 deleteLegacyAccounts(); 62 } 63 64 /** 65 * Delete *all* legacy accounts 66 */ 67 private void deleteLegacyAccounts() { 68 Account[] oldAccounts = mPreferences.getAccounts(); 69 for (Account oldAccount : oldAccounts) { 70 oldAccount.delete(mPreferences); 71 } 72 } 73 74 /** 75 * Test backup with no accounts 76 */ 77 public void testNoAccountBackup() { 78 // create some "old" backups or legacy accounts 79 Account backupAccount = new Account(mMockContext); 80 backupAccount.save(mPreferences); 81 // confirm they are there 82 Account[] oldBackups = mPreferences.getAccounts(); 83 assertTrue(oldBackups.length >= 1); 84 // make sure there are no accounts in the provider 85 int numAccounts = EmailContent.count(mMockContext, EmailContent.Account.CONTENT_URI, 86 null, null); 87 assertEquals(0, numAccounts); 88 // run backups 89 AccountBackupRestore.doBackupAccounts(mMockContext, mPreferences); 90 // confirm there are no backups made 91 Account[] backups = mPreferences.getAccounts(); 92 assertEquals(0, backups.length); 93 } 94 95 /** 96 * Test backup with accounts 97 */ 98 public void testBackup() { 99 // Clear the decks 100 deleteLegacyAccounts(); 101 102 // Create real accounts in need of backup 103 EmailContent.Account liveAccount1 = 104 ProviderTestUtils.setupAccount("testBackup1", false, mMockContext); 105 liveAccount1.mHostAuthRecv = 106 ProviderTestUtils.setupHostAuth("legacy-recv", 0, false, mMockContext); 107 liveAccount1.mHostAuthSend = 108 ProviderTestUtils.setupHostAuth("legacy-send", 0, false, mMockContext); 109 liveAccount1.setDefaultAccount(true); 110 liveAccount1.save(mMockContext); 111 EmailContent.Account liveAccount2 = 112 ProviderTestUtils.setupAccount("testBackup2", false, mMockContext); 113 liveAccount2.mHostAuthRecv = 114 ProviderTestUtils.setupHostAuth("legacy-recv", 0, false, mMockContext); 115 liveAccount2.mHostAuthSend = 116 ProviderTestUtils.setupHostAuth("legacy-send", 0, false, mMockContext); 117 liveAccount2.setDefaultAccount(false); 118 liveAccount2.save(mMockContext); 119 120 // run backups 121 AccountBackupRestore.doBackupAccounts(mMockContext, mPreferences); 122 123 // Confirm we have two backups now 124 // Deep inspection is not performed here - see LegacyConversionsTests 125 // We just check for basic identity & flags 126 Account[] backups = mPreferences.getAccounts(); 127 assertEquals(2, backups.length); 128 for (Account backup : backups) { 129 if ("testBackup1".equals(backup.getDescription())) { 130 assertTrue(0 != (backup.mBackupFlags & Account.BACKUP_FLAGS_IS_DEFAULT)); 131 } else if ("testBackup2".equals(backup.getDescription())) { 132 assertFalse(0 != (backup.mBackupFlags & Account.BACKUP_FLAGS_IS_DEFAULT)); 133 } else { 134 fail("unexpected backup name=" + backup.getDescription()); 135 } 136 } 137 Account backup1 = backups[0]; 138 assertTrue(0 != (backup1.mBackupFlags & Account.BACKUP_FLAGS_IS_BACKUP)); 139 assertEquals(liveAccount1.getDisplayName(), backup1.getDescription()); 140 } 141 142 /** 143 * TODO: Test backup EAS accounts, with and without contacts sync 144 * 145 * Blocker: We need to inject the dependency on ContentResolver.getSyncAutomatically() 146 * so we can make our fake accounts appear to be syncable or non-syncable 147 */ 148 149 /** 150 * Test no-restore with accounts found 151 */ 152 public void testNoAccountRestore1() { 153 // make sure there are no real backups 154 deleteLegacyAccounts(); 155 156 // make sure there are test backups available 157 Account backupAccount1 = setupLegacyBackupAccount("backup1"); 158 backupAccount1.save(mPreferences); 159 Account backupAccount2 = setupLegacyBackupAccount("backup2"); 160 backupAccount2.save(mPreferences); 161 162 // make sure there are accounts 163 EmailContent.Account existing = 164 ProviderTestUtils.setupAccount("existing", true, mMockContext); 165 166 // run the restore 167 boolean anyRestored = AccountBackupRestore.doRestoreAccounts(mMockContext, mPreferences); 168 assertFalse(anyRestored); 169 170 // make sure accounts still there 171 int numAccounts = EmailContent.count(mMockContext, EmailContent.Account.CONTENT_URI, 172 null, null); 173 assertEquals(1, numAccounts); 174 } 175 176 /** 177 * Test no-restore with no accounts & no backups 178 */ 179 public void testNoAccountRestore2() { 180 // make sure there are no real backups 181 deleteLegacyAccounts(); 182 183 // make sure there are no accounts 184 int numAccounts = EmailContent.count(mMockContext, EmailContent.Account.CONTENT_URI, 185 null, null); 186 assertEquals(0, numAccounts); 187 188 // run the restore 189 boolean anyRestored = AccountBackupRestore.doRestoreAccounts(mMockContext, mPreferences); 190 assertFalse(anyRestored); 191 192 // make sure accounts still there 193 numAccounts = EmailContent.count(mMockContext, EmailContent.Account.CONTENT_URI, 194 null, null); 195 assertEquals(0, numAccounts); 196 } 197 198 /** 199 * Test restore with 2 accounts. 200 * Repeats test to verify restore of default account 201 */ 202 public void testAccountRestore() { 203 // make sure there are no real backups 204 deleteLegacyAccounts(); 205 206 // create test backups 207 Account backupAccount1 = setupLegacyBackupAccount("backup1"); 208 backupAccount1.mBackupFlags |= Account.BACKUP_FLAGS_IS_DEFAULT; 209 backupAccount1.save(mPreferences); 210 Account backupAccount2 = setupLegacyBackupAccount("backup2"); 211 backupAccount2.save(mPreferences); 212 213 // run the restore 214 boolean anyRestored = AccountBackupRestore.doRestoreAccounts(mMockContext, mPreferences); 215 assertTrue(anyRestored); 216 217 // Check the restored accounts 218 // Deep inspection is not performed here - see LegacyConversionsTests for that 219 // We just check for basic identity & flags 220 Cursor c = mMockContext.getContentResolver().query(EmailContent.Account.CONTENT_URI, 221 EmailContent.Account.CONTENT_PROJECTION, null, null, null); 222 try { 223 assertEquals(2, c.getCount()); 224 while (c.moveToNext()) { 225 EmailContent.Account restored = 226 EmailContent.getContent(c, EmailContent.Account.class); 227 if ("backup1".equals(restored.getDisplayName())) { 228 assertTrue(restored.mIsDefault); 229 } else if ("backup2".equals(restored.getDisplayName())) { 230 assertFalse(restored.mIsDefault); 231 } else { 232 fail("Unexpected restore account name=" + restored.getDisplayName()); 233 } 234 checkRestoredTransientValues(restored); 235 } 236 } finally { 237 c.close(); 238 } 239 240 // clear out the backups & accounts and try again 241 deleteLegacyAccounts(); 242 mMockContext.getContentResolver().delete(EmailContent.Account.CONTENT_URI, null, null); 243 244 Account backupAccount3 = setupLegacyBackupAccount("backup3"); 245 backupAccount3.save(mPreferences); 246 Account backupAccount4 = setupLegacyBackupAccount("backup4"); 247 backupAccount4.mBackupFlags |= Account.BACKUP_FLAGS_IS_DEFAULT; 248 backupAccount4.save(mPreferences); 249 250 // run the restore 251 AccountBackupRestore.doRestoreAccounts(mMockContext, mPreferences); 252 253 // Check the restored accounts 254 // Deep inspection is not performed here - see LegacyConversionsTests for that 255 // We just check for basic identity & flags 256 c = mMockContext.getContentResolver().query(EmailContent.Account.CONTENT_URI, 257 EmailContent.Account.CONTENT_PROJECTION, null, null, null); 258 try { 259 assertEquals(2, c.getCount()); 260 while (c.moveToNext()) { 261 EmailContent.Account restored = 262 EmailContent.getContent(c, EmailContent.Account.class); 263 if ("backup3".equals(restored.getDisplayName())) { 264 assertFalse(restored.mIsDefault); 265 } else if ("backup4".equals(restored.getDisplayName())) { 266 assertTrue(restored.mIsDefault); 267 } else { 268 fail("Unexpected restore account name=" + restored.getDisplayName()); 269 } 270 checkRestoredTransientValues(restored); 271 } 272 } finally { 273 c.close(); 274 } 275 } 276 277 /** 278 * Check a given restored account to make sure that transient (non-backed-up) values 279 * are initialized to reasonable values. 280 */ 281 private void checkRestoredTransientValues(EmailContent.Account restored) { 282 // sync key == null 283 assertNull(restored.mSyncKey); 284 // hostauth id's are no longer zero or -1 285 assertTrue(restored.mHostAuthKeyRecv > 0); 286 assertTrue(restored.mHostAuthKeySend > 0); 287 // protocol version == null or non-empty string 288 assertTrue(restored.mProtocolVersion == null || restored.mProtocolVersion.length() > 0); 289 } 290 291 /** 292 * TODO: Test restore EAS accounts, with and without contacts sync 293 * 294 * Blocker: We need to inject the dependency on account manager to catch the calls to it 295 */ 296 297 /** 298 * Setup a legacy backup account with many fields prefilled. 299 */ 300 private Account setupLegacyBackupAccount(String name) { 301 Account backup = new Account(mMockContext); 302 303 // fill in useful fields 304 backup.mUuid = "test-uid-" + name; 305 backup.mStoreUri = "store://test/" + name; 306 backup.mLocalStoreUri = "local://localhost/" + name; 307 backup.mSenderUri = "sender://test/" + name; 308 backup.mDescription = name; 309 backup.mName = "name " + name; 310 backup.mEmail = "email " + name; 311 backup.mAutomaticCheckIntervalMinutes = 100; 312 backup.mLastAutomaticCheckTime = 200; 313 backup.mNotifyNewMail = true; 314 backup.mDraftsFolderName = "drafts " + name; 315 backup.mSentFolderName = "sent " + name; 316 backup.mTrashFolderName = "trash " + name; 317 backup.mOutboxFolderName = "outbox " + name; 318 backup.mAccountNumber = 300; 319 backup.mVibrate = true; 320 backup.mVibrateWhenSilent = false; 321 backup.mRingtoneUri = "ringtone://test/" + name; 322 backup.mSyncWindow = 400; 323 backup.mBackupFlags = Account.BACKUP_FLAGS_IS_BACKUP; 324 backup.mProtocolVersion = "proto version" + name; 325 backup.mDeletePolicy = Account.DELETE_POLICY_NEVER; 326 backup.mSecurityFlags = 500; 327 return backup; 328 } 329 } 330