1 2/* 3 * Copyright (C) 2016 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 18package com.android.server.accounts; 19 20import android.accounts.Account; 21import android.content.Context; 22import android.database.Cursor; 23import android.support.test.InstrumentationRegistry; 24import android.support.test.runner.AndroidJUnit4; 25import android.test.suitebuilder.annotation.SmallTest; 26import android.util.Pair; 27 28import org.junit.After; 29import org.junit.Before; 30import org.junit.Test; 31import org.junit.runner.RunWith; 32 33import java.io.File; 34import java.util.Arrays; 35import java.util.List; 36import java.util.Map; 37 38import static org.junit.Assert.assertEquals; 39import static org.junit.Assert.assertFalse; 40import static org.junit.Assert.assertNull; 41import static org.junit.Assert.assertTrue; 42 43/** 44 * Tests for {@link AccountsDb}. 45 * <p>Run with:<pre> 46 * m FrameworksServicesTests && 47 * adb install \ 48 * -r out/target/product/marlin/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && 49 * adb shell am instrument -e class com.android.server.accounts.AccountsDbTest \ 50 * -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner 51 * </pre> 52 */ 53@RunWith(AndroidJUnit4.class) 54@SmallTest 55public class AccountsDbTest { 56 private static final String PREN_DB = "pren.db"; 57 private static final String DE_DB = "de.db"; 58 private static final String CE_DB = "ce.db"; 59 60 private AccountsDb mAccountsDb; 61 private File preNDb; 62 private File deDb; 63 private File ceDb; 64 65 @Before 66 public void setUp() { 67 Context context = InstrumentationRegistry.getContext(); 68 preNDb = new File(context.getCacheDir(), PREN_DB); 69 ceDb = new File(context.getCacheDir(), CE_DB); 70 deDb = new File(context.getCacheDir(), DE_DB); 71 deleteDbFiles(); 72 mAccountsDb = AccountsDb.create(context, 0, preNDb, deDb); 73 } 74 75 @After 76 public void tearDown() { 77 deleteDbFiles(); 78 } 79 80 private void deleteDbFiles() { 81 AccountsDb.deleteDbFileWarnIfFailed(preNDb); 82 AccountsDb.deleteDbFileWarnIfFailed(ceDb); 83 AccountsDb.deleteDbFileWarnIfFailed(deDb); 84 } 85 86 @Test 87 public void testCeNotAvailableInitially() { 88 Account account = new Account("name", "example.com"); 89 long id = mAccountsDb.insertCeAccount(account, ""); 90 assertEquals("Insert into CE should fail until CE database is attached", -1, id); 91 } 92 93 @Test 94 public void testDeAccountInsertFindDelete() { 95 Account account = new Account("name", "example.com"); 96 long accId = 1; 97 mAccountsDb.insertDeAccount(account, accId); 98 long actualId = mAccountsDb.findDeAccountId(account); 99 assertEquals(accId, actualId); 100 // Delete and verify that account no longer exists 101 mAccountsDb.deleteDeAccount(accId); 102 actualId = mAccountsDb.findDeAccountId(account); 103 assertEquals(-1, actualId); 104 } 105 106 @Test 107 public void testCeAccountInsertFindDelete() { 108 mAccountsDb.attachCeDatabase(ceDb); 109 Account account = new Account("name", "example.com"); 110 long accId = mAccountsDb.insertCeAccount(account, "password"); 111 long actualId = mAccountsDb.findCeAccountId(account); 112 assertEquals(accId, actualId); 113 // Delete and verify that account no longer exists 114 mAccountsDb.deleteCeAccount(accId); 115 actualId = mAccountsDb.findCeAccountId(account); 116 assertEquals(-1, actualId); 117 } 118 119 @Test 120 public void testAuthTokenInsertFindDelete() { 121 mAccountsDb.attachCeDatabase(ceDb); 122 Account account = new Account("name", "example.com"); 123 long accId = mAccountsDb.insertCeAccount(account, "password"); 124 mAccountsDb.insertDeAccount(account, accId); 125 long authTokenId = mAccountsDb.insertAuthToken(accId, "type", "token"); 126 Map<String, String> authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account); 127 assertEquals(1, authTokensByAccount.size()); 128 try (Cursor cursor = mAccountsDb.findAuthtokenForAllAccounts(account.type, "token")) { 129 assertTrue(cursor.moveToNext()); 130 } 131 try (Cursor cursor = mAccountsDb.findAuthtokenForAllAccounts(account.type, "nosuchtoken")) { 132 assertFalse(cursor.moveToNext()); 133 } 134 mAccountsDb.deleteAuthToken(String.valueOf(authTokenId)); 135 // Verify that token no longer exists 136 authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account); 137 assertEquals(0, authTokensByAccount.size()); 138 } 139 140 @Test 141 public void testAuthTokenDeletes() { 142 mAccountsDb.attachCeDatabase(ceDb); 143 // 1st account 144 Account account = new Account("name", "example.com"); 145 long accId = mAccountsDb.insertCeAccount(account, "password"); 146 mAccountsDb.insertDeAccount(account, accId); 147 mAccountsDb.insertAuthToken(accId, "type", "token"); 148 mAccountsDb.insertAuthToken(accId, "type2", "token2"); 149 // 2nd account 150 Account account2 = new Account("name", "example2.com"); 151 long accId2 = mAccountsDb.insertCeAccount(account2, "password"); 152 mAccountsDb.insertDeAccount(account2, accId2); 153 mAccountsDb.insertAuthToken(accId2, "type", "token"); 154 155 mAccountsDb.deleteAuthTokensByAccountId(accId2); 156 Map<String, String> authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account2); 157 assertEquals(0, authTokensByAccount.size()); 158 // Authtokens from account 1 are still there 159 authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account); 160 assertEquals(2, authTokensByAccount.size()); 161 162 // Delete authtokens from account 1 and verify 163 mAccountsDb.deleteAuthtokensByAccountIdAndType(accId, "type"); 164 authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account); 165 assertEquals(1, authTokensByAccount.size()); 166 mAccountsDb.deleteAuthtokensByAccountIdAndType(accId, "type2"); 167 authTokensByAccount = mAccountsDb.findAuthTokensByAccount(account); 168 assertEquals(0, authTokensByAccount.size()); 169 } 170 171 @Test 172 public void testExtrasInsertFindDelete() { 173 mAccountsDb.attachCeDatabase(ceDb); 174 Account account = new Account("name", "example.com"); 175 long accId = mAccountsDb.insertCeAccount(account, "password"); 176 mAccountsDb.insertDeAccount(account, accId); 177 String extraKey = "extra_key"; 178 String extraValue = "extra_value"; 179 long extraId = mAccountsDb.insertExtra(accId, extraKey, extraValue); 180 // Test find methods 181 long actualExtraId = mAccountsDb.findExtrasIdByAccountId(accId, extraKey); 182 assertEquals(extraId, actualExtraId); 183 Map<String, String> extras = mAccountsDb.findUserExtrasForAccount(account); 184 assertEquals(1, extras.size()); 185 assertEquals(extraValue, extras.get(extraKey)); 186 // Test update 187 String newExtraValue = "extra_value2"; 188 mAccountsDb.updateExtra(extraId, newExtraValue); 189 String newValue = mAccountsDb.findUserExtrasForAccount(account).get(extraKey); 190 assertEquals(newExtraValue, newValue); 191 192 // Delete account and verify that extras cascade removed 193 mAccountsDb.deleteCeAccount(accId); 194 actualExtraId = mAccountsDb.findExtrasIdByAccountId(accId, extraKey); 195 assertEquals(-1, actualExtraId); 196 } 197 198 @Test 199 public void testGrantsInsertFindDelete() { 200 mAccountsDb.attachCeDatabase(ceDb); 201 Account account = new Account("name", "example.com"); 202 long accId = mAccountsDb.insertCeAccount(account, "password"); 203 mAccountsDb.insertDeAccount(account, accId); 204 int testUid = 100500; 205 long grantId = mAccountsDb.insertGrant(accId, "tokenType", testUid); 206 assertTrue(grantId > 0); 207 List<Integer> allUidGrants = mAccountsDb.findAllUidGrants(); 208 List<Integer> expectedUids = Arrays.asList(testUid); 209 assertEquals(expectedUids, allUidGrants); 210 211 long matchingGrantsCount = mAccountsDb.findMatchingGrantsCount( 212 testUid, "tokenType", account); 213 assertEquals(1, matchingGrantsCount); 214 // Test nonexistent type 215 matchingGrantsCount = mAccountsDb.findMatchingGrantsCount( 216 testUid, "noSuchType", account); 217 assertEquals(0, matchingGrantsCount); 218 219 matchingGrantsCount = mAccountsDb.findMatchingGrantsCountAnyToken(testUid, account); 220 assertEquals(1, matchingGrantsCount); 221 222 List<Pair<String, Integer>> allAccountGrants = mAccountsDb.findAllAccountGrants(); 223 assertEquals(1, allAccountGrants.size()); 224 assertEquals(account.name, allAccountGrants.get(0).first); 225 assertEquals(testUid, (int)allAccountGrants.get(0).second); 226 227 mAccountsDb.deleteGrantsByUid(testUid); 228 allUidGrants = mAccountsDb.findAllUidGrants(); 229 assertTrue("Test grants should be removed", allUidGrants.isEmpty()); 230 } 231 232 @Test 233 public void testSharedAccountsInsertFindDelete() { 234 Account account = new Account("name", "example.com"); 235 long accId = 0; 236 mAccountsDb.insertDeAccount(account, accId); 237 long sharedAccId = mAccountsDb.insertSharedAccount(account); 238 long foundSharedAccountId = mAccountsDb.findSharedAccountId(account); 239 assertEquals(sharedAccId, foundSharedAccountId); 240 List<Account> sharedAccounts = mAccountsDb.getSharedAccounts(); 241 List<Account> expectedList = Arrays.asList(account); 242 assertEquals(expectedList, sharedAccounts); 243 244 // Delete and verify 245 mAccountsDb.deleteSharedAccount(account); 246 foundSharedAccountId = mAccountsDb.findSharedAccountId(account); 247 assertEquals(-1, foundSharedAccountId); 248 } 249 250 @Test 251 public void testMetaInsertFindDelete() { 252 int testUid = 100500; 253 String authenticatorType = "authType"; 254 mAccountsDb.insertOrReplaceMetaAuthTypeAndUid(authenticatorType, testUid); 255 Map<String, Integer> metaAuthUid = mAccountsDb.findMetaAuthUid(); 256 assertEquals(1, metaAuthUid.size()); 257 assertEquals(testUid, (int)metaAuthUid.get(authenticatorType)); 258 259 // Delete and verify 260 boolean deleteResult = mAccountsDb.deleteMetaByAuthTypeAndUid(authenticatorType, testUid); 261 assertTrue(deleteResult); 262 metaAuthUid = mAccountsDb.findMetaAuthUid(); 263 assertEquals(0, metaAuthUid.size()); 264 } 265 266 @Test 267 public void testUpdateDeAccountLastAuthenticatedTime() { 268 Account account = new Account("name", "example.com"); 269 long accId = 1; 270 mAccountsDb.insertDeAccount(account, accId); 271 long now = System.currentTimeMillis(); 272 mAccountsDb.updateAccountLastAuthenticatedTime(account); 273 long time = mAccountsDb.findAccountLastAuthenticatedTime(account); 274 assertTrue("LastAuthenticatedTime should be current", time >= now); 275 } 276 277 @Test 278 public void testRenameAccount() { 279 mAccountsDb.attachCeDatabase(ceDb); 280 Account account = new Account("name", "example.com"); 281 long accId = mAccountsDb.insertCeAccount(account, "password"); 282 mAccountsDb.insertDeAccount(account, accId); 283 mAccountsDb.renameDeAccount(accId, "newName", "name"); 284 Account newAccount = mAccountsDb.findAllDeAccounts().get(accId); 285 assertEquals("newName", newAccount.name); 286 287 String prevName = mAccountsDb.findDeAccountPreviousName(newAccount); 288 assertEquals("name", prevName); 289 mAccountsDb.renameCeAccount(accId, "newName"); 290 long foundAccId = mAccountsDb.findCeAccountId(account); 291 assertEquals("Account shouldn't be found under the old name", -1, foundAccId); 292 foundAccId = mAccountsDb.findCeAccountId(newAccount); 293 assertEquals(accId, foundAccId); 294 } 295 296 @Test 297 public void testUpdateCeAccountPassword() { 298 mAccountsDb.attachCeDatabase(ceDb); 299 Account account = new Account("name", "example.com"); 300 long accId = mAccountsDb.insertCeAccount(account, "password"); 301 String newPassword = "newPassword"; 302 mAccountsDb.updateCeAccountPassword(accId, newPassword); 303 String actualPassword = mAccountsDb 304 .findAccountPasswordByNameAndType(account.name, account.type); 305 assertEquals(newPassword, actualPassword); 306 } 307 308 @Test 309 public void testFindCeAccountsNotInDe() { 310 mAccountsDb.attachCeDatabase(ceDb); 311 Account account = new Account("name", "example.com"); 312 long accId = mAccountsDb.insertCeAccount(account, "password"); 313 mAccountsDb.insertDeAccount(account, accId); 314 315 Account accountNotInDe = new Account("name2", "example.com"); 316 mAccountsDb.insertCeAccount(accountNotInDe, "password"); 317 318 List<Account> ceAccounts = mAccountsDb.findCeAccountsNotInDe(); 319 List<Account> expectedList = Arrays.asList(accountNotInDe); 320 assertEquals(expectedList, ceAccounts); 321 } 322 323 @Test 324 public void testCrossDbTransactions() { 325 mAccountsDb.attachCeDatabase(ceDb); 326 mAccountsDb.beginTransaction(); 327 Account account = new Account("name", "example.com"); 328 long accId; 329 accId = mAccountsDb.insertCeAccount(account, "password"); 330 accId = mAccountsDb.insertDeAccount(account, accId); 331 long actualId = mAccountsDb.findCeAccountId(account); 332 assertEquals(accId, actualId); 333 actualId = mAccountsDb.findDeAccountId(account); 334 assertEquals(accId, actualId); 335 mAccountsDb.endTransaction(); 336 // Verify that records were removed 337 actualId = mAccountsDb.findCeAccountId(account); 338 assertEquals(-1, actualId); 339 actualId = mAccountsDb.findDeAccountId(account); 340 assertEquals(-1, actualId); 341 } 342 343 @Test 344 public void testFindDeAccountByAccountId() { 345 long accId = 10; 346 Account account = new Account("name", "example.com"); 347 assertNull(mAccountsDb.findDeAccountByAccountId(accId)); 348 349 mAccountsDb.insertDeAccount(account, accId); 350 351 Account foundAccount = mAccountsDb.findDeAccountByAccountId(accId); 352 assertEquals(account, foundAccount); 353 } 354 355 @Test 356 public void testVisibilityFindSetDelete() { 357 long accId = 10; 358 String packageName1 = "com.example.one"; 359 String packageName2 = "com.example.two"; 360 Account account = new Account("name", "example.com"); 361 assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); 362 363 mAccountsDb.insertDeAccount(account, accId); 364 assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); 365 assertNull(mAccountsDb.findAccountVisibility(accId, packageName1)); 366 367 mAccountsDb.setAccountVisibility(accId, packageName1, 1); 368 assertEquals(mAccountsDb.findAccountVisibility(account, packageName1), Integer.valueOf(1)); 369 assertEquals(mAccountsDb.findAccountVisibility(accId, packageName1), Integer.valueOf(1)); 370 371 mAccountsDb.setAccountVisibility(accId, packageName2, 2); 372 assertEquals(mAccountsDb.findAccountVisibility(accId, packageName2), Integer.valueOf(2)); 373 374 mAccountsDb.setAccountVisibility(accId, packageName2, 3); 375 assertEquals(mAccountsDb.findAccountVisibility(accId, packageName2), Integer.valueOf(3)); 376 377 Map<String, Integer> vis = mAccountsDb.findAllVisibilityValuesForAccount(account); 378 assertEquals(vis.size(), 2); 379 assertEquals(vis.get(packageName1), Integer.valueOf(1)); 380 assertEquals(vis.get(packageName2), Integer.valueOf(3)); 381 382 assertTrue(mAccountsDb.deleteAccountVisibilityForPackage(packageName1)); 383 assertNull(mAccountsDb.findAccountVisibility(accId, packageName1)); 384 assertFalse(mAccountsDb.deleteAccountVisibilityForPackage(packageName1)); // 2nd attempt. 385 } 386 387 @Test 388 public void testFindAllVisibilityValues() { 389 long accId = 10; 390 long accId2 = 11; 391 String packageName1 = "com.example.one"; 392 String packageName2 = "com.example.two"; 393 Account account = new Account("name", "example.com"); 394 Account account2 = new Account("name2", "example2.com"); 395 assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); 396 397 mAccountsDb.insertDeAccount(account, accId); 398 assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); 399 assertNull(mAccountsDb.findAccountVisibility(accId, packageName1)); 400 mAccountsDb.insertDeAccount(account2, accId2); 401 402 mAccountsDb.setAccountVisibility(accId, packageName1, 1); 403 mAccountsDb.setAccountVisibility(accId, packageName2, 2); 404 mAccountsDb.setAccountVisibility(accId2, packageName1, 1); 405 406 Map<Account, Map<String, Integer>> vis = mAccountsDb.findAllVisibilityValues(); 407 assertEquals(vis.size(), 2); 408 Map<String, Integer> accnt1Visibility = vis.get(account); 409 assertEquals(accnt1Visibility.size(), 2); 410 assertEquals(accnt1Visibility.get(packageName1), Integer.valueOf(1)); 411 assertEquals(accnt1Visibility.get(packageName2), Integer.valueOf(2)); 412 Map<String, Integer> accnt2Visibility = vis.get(account2); 413 assertEquals(accnt2Visibility.size(), 1); 414 assertEquals(accnt2Visibility.get(packageName1), Integer.valueOf(1)); 415 416 mAccountsDb.setAccountVisibility(accId2, packageName2, 3); 417 vis = mAccountsDb.findAllVisibilityValues(); 418 accnt2Visibility = vis.get(account2); 419 assertEquals(accnt2Visibility.size(), 2); 420 assertEquals(accnt2Visibility.get(packageName2), Integer.valueOf(3)); 421 } 422 423 @Test 424 public void testVisibilityCleanupTrigger() { 425 long accId = 10; 426 String packageName1 = "com.example.one"; 427 Account account = new Account("name", "example.com"); 428 429 assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); 430 mAccountsDb.insertDeAccount(account, accId); 431 assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); 432 433 mAccountsDb.setAccountVisibility(accId, packageName1, 1); 434 assertEquals(mAccountsDb.findAccountVisibility(accId, packageName1), Integer.valueOf(1)); 435 436 assertTrue(mAccountsDb.deleteDeAccount(accId)); // Trigger should remove visibility. 437 assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); 438 } 439} 440