1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; 4 import static android.os.Build.VERSION_CODES.LOLLIPOP; 5 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 6 import static com.google.common.truth.Truth.assertThat; 7 import static org.junit.Assert.fail; 8 import static org.robolectric.Shadows.shadowOf; 9 10 import android.accounts.Account; 11 import android.accounts.AccountManager; 12 import android.accounts.AccountManagerCallback; 13 import android.accounts.AccountManagerFuture; 14 import android.accounts.AuthenticatorDescription; 15 import android.accounts.AuthenticatorException; 16 import android.accounts.OnAccountsUpdateListener; 17 import android.accounts.OperationCanceledException; 18 import android.app.Activity; 19 import android.content.Context; 20 import android.content.Intent; 21 import android.os.Bundle; 22 import android.os.Handler; 23 import androidx.test.core.app.ApplicationProvider; 24 import androidx.test.ext.junit.runners.AndroidJUnit4; 25 import java.io.IOException; 26 import org.junit.Before; 27 import org.junit.Test; 28 import org.junit.runner.RunWith; 29 import org.robolectric.Robolectric; 30 import org.robolectric.annotation.Config; 31 import org.robolectric.util.Scheduler; 32 33 @RunWith(AndroidJUnit4.class) 34 public class ShadowAccountManagerTest { 35 private AccountManager am; 36 private Scheduler scheduler; 37 private Activity activity; 38 39 @Before 40 public void setUp() throws Exception { 41 am = AccountManager.get(ApplicationProvider.getApplicationContext()); 42 scheduler = Robolectric.getForegroundThreadScheduler(); 43 activity = new Activity(); 44 } 45 46 @Test 47 public void testGet() { 48 assertThat(am).isNotNull(); 49 assertThat(am).isSameAs(AccountManager.get(ApplicationProvider.getApplicationContext())); 50 51 AccountManager activityAM = AccountManager.get(ApplicationProvider.getApplicationContext()); 52 assertThat(activityAM).isNotNull(); 53 assertThat(activityAM).isSameAs(am); 54 } 55 56 @Test 57 public void testGetAccounts() { 58 assertThat(am.getAccounts()).isNotNull(); 59 assertThat(am.getAccounts().length).isEqualTo(0); 60 61 Account a1 = new Account("name_a", "type_a"); 62 shadowOf(am).addAccount(a1); 63 assertThat(am.getAccounts()).isNotNull(); 64 assertThat(am.getAccounts().length).isEqualTo(1); 65 assertThat(am.getAccounts()[0]).isSameAs(a1); 66 67 Account a2 = new Account("name_b", "type_b"); 68 shadowOf(am).addAccount(a2); 69 assertThat(am.getAccounts()).isNotNull(); 70 assertThat(am.getAccounts().length).isEqualTo(2); 71 assertThat(am.getAccounts()[1]).isSameAs(a2); 72 } 73 74 @Test 75 public void getAccountsByType_nullTypeReturnsAllAccounts() { 76 shadowOf(am).addAccount(new Account("name_1", "type_1")); 77 shadowOf(am).addAccount(new Account("name_2", "type_2")); 78 shadowOf(am).addAccount(new Account("name_3", "type_3")); 79 80 assertThat(am.getAccountsByType(null)).asList().containsAllIn(am.getAccounts()); 81 } 82 83 @Test 84 public void testGetAccountsByType() { 85 assertThat(am.getAccountsByType("name_a")).isNotNull(); 86 assertThat(am.getAccounts().length).isEqualTo(0); 87 88 Account a1 = new Account("name_a", "type_a"); 89 shadowOf(am).addAccount(a1); 90 Account[] accounts = am.getAccountsByType("type_a"); 91 assertThat(accounts).isNotNull(); 92 assertThat(accounts.length).isEqualTo(1); 93 assertThat(accounts[0]).isSameAs(a1); 94 95 Account a2 = new Account("name_b", "type_b"); 96 shadowOf(am).addAccount(a2); 97 accounts = am.getAccountsByType("type_a"); 98 assertThat(accounts).isNotNull(); 99 assertThat(accounts.length).isEqualTo(1); 100 assertThat(accounts[0]).isSameAs(a1); 101 102 Account a3 = new Account("name_c", "type_a"); 103 shadowOf(am).addAccount(a3); 104 accounts = am.getAccountsByType("type_a"); 105 assertThat(accounts).isNotNull(); 106 assertThat(accounts.length).isEqualTo(2); 107 assertThat(accounts[0]).isSameAs(a1); 108 assertThat(accounts[1]).isSameAs(a3); 109 } 110 111 @Test 112 public void addAuthToken() { 113 Account account = new Account("name", "type"); 114 shadowOf(am).addAccount(account); 115 116 am.setAuthToken(account, "token_type_1", "token1"); 117 am.setAuthToken(account, "token_type_2", "token2"); 118 119 assertThat(am.peekAuthToken(account, "token_type_1")).isEqualTo("token1"); 120 assertThat(am.peekAuthToken(account, "token_type_2")).isEqualTo("token2"); 121 } 122 123 @Test 124 public void setAuthToken_shouldNotAddTokenIfAccountNotPresent() { 125 Account account = new Account("name", "type"); 126 am.setAuthToken(account, "token_type_1", "token1"); 127 assertThat(am.peekAuthToken(account, "token_type_1")).isNull(); 128 } 129 130 @Test 131 public void testAddAccountExplicitly_noPasswordNoExtras() { 132 Account account = new Account("name", "type"); 133 boolean accountAdded = am.addAccountExplicitly(account, null, null); 134 135 assertThat(accountAdded).isTrue(); 136 assertThat(am.getAccountsByType("type").length).isEqualTo(1); 137 assertThat(am.getAccountsByType("type")[0].name).isEqualTo("name"); 138 139 boolean accountAddedTwice = am.addAccountExplicitly(account, null, null); 140 assertThat(accountAddedTwice).isFalse(); 141 142 account = new Account("another_name", "type"); 143 accountAdded = am.addAccountExplicitly(account, null, null); 144 assertThat(accountAdded).isTrue(); 145 assertThat(am.getAccountsByType("type").length).isEqualTo(2); 146 assertThat(am.getAccountsByType("type")[0].name).isEqualTo("name"); 147 assertThat(am.getAccountsByType("type")[1].name).isEqualTo("another_name"); 148 assertThat(am.getPassword(account)).isNull(); 149 150 try { 151 am.addAccountExplicitly(null, null, null); 152 fail("An illegal argument exception should have been thrown when trying to add a null account"); 153 } catch (IllegalArgumentException iae) { 154 // NOP 155 } 156 } 157 158 @Test 159 public void testAddAccountExplicitly_withPassword() { 160 Account account = new Account("name", "type"); 161 boolean accountAdded = am.addAccountExplicitly(account, "passwd", null); 162 163 assertThat(accountAdded).isTrue(); 164 assertThat(am.getPassword(account)).isEqualTo("passwd"); 165 } 166 167 @Test 168 public void testAddAccountExplicitly_withExtras() { 169 Account account = new Account("name", "type"); 170 Bundle extras = new Bundle(); 171 extras.putString("key123", "value123"); 172 boolean accountAdded = am.addAccountExplicitly(account, null, extras); 173 174 assertThat(accountAdded).isTrue(); 175 assertThat(am.getUserData(account, "key123")).isEqualTo("value123"); 176 assertThat(am.getUserData(account, "key456")).isNull(); 177 } 178 179 @Test 180 public void testAddAccountExplicitly_notifiesListenersIfSuccessful() { 181 TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener(); 182 am.addOnAccountsUpdatedListener(listener, null, false); 183 assertThat(listener.getInvocationCount()).isEqualTo(0); 184 185 Account account = new Account("name", "type"); 186 boolean accountAdded = am.addAccountExplicitly(account, "passwd", null); 187 188 assertThat(accountAdded).isTrue(); 189 assertThat(listener.getInvocationCount()).isEqualTo(1); 190 } 191 192 @Test 193 public void testAddAccountExplicitly_doesNotNotifyListenersIfUnsuccessful() { 194 Account account = new Account("name", "type"); 195 boolean accountAdded = am.addAccountExplicitly(account, "passwd", null); 196 assertThat(accountAdded).isTrue(); 197 198 TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener(); 199 am.addOnAccountsUpdatedListener(listener, null, false); 200 assertThat(listener.getInvocationCount()).isEqualTo(0); 201 202 // This account is added already, so it'll fail 203 boolean accountAdded2 = am.addAccountExplicitly(account, "passwd", null); 204 assertThat(accountAdded2).isFalse(); 205 assertThat(listener.getInvocationCount()).isEqualTo(0); 206 } 207 208 @Test 209 public void testGetSetUserData_addToInitiallyEmptyExtras() { 210 Account account = new Account("name", "type"); 211 boolean accountAdded = am.addAccountExplicitly(account, null, null); 212 213 assertThat(accountAdded).isTrue(); 214 215 am.setUserData(account, "key123", "value123"); 216 assertThat(am.getUserData(account, "key123")).isEqualTo("value123"); 217 } 218 219 @Test 220 public void testGetSetUserData_overwrite() { 221 Account account = new Account("name", "type"); 222 boolean accountAdded = am.addAccountExplicitly(account, null, null); 223 224 assertThat(accountAdded).isTrue(); 225 226 am.setUserData(account, "key123", "value123"); 227 assertThat(am.getUserData(account, "key123")).isEqualTo("value123"); 228 229 am.setUserData(account, "key123", "value456"); 230 assertThat(am.getUserData(account, "key123")).isEqualTo("value456"); 231 } 232 233 @Test 234 public void testGetSetUserData_remove() { 235 Account account = new Account("name", "type"); 236 boolean accountAdded = am.addAccountExplicitly(account, null, null); 237 238 assertThat(accountAdded).isTrue(); 239 240 am.setUserData(account, "key123", "value123"); 241 assertThat(am.getUserData(account, "key123")).isEqualTo("value123"); 242 243 am.setUserData(account, "key123", null); 244 assertThat(am.getUserData(account, "key123")).isNull(); 245 } 246 247 @Test 248 public void testGetSetPassword_setInAccountInitiallyWithNoPassword() { 249 Account account = new Account("name", "type"); 250 boolean accountAdded = am.addAccountExplicitly(account, null, null); 251 252 assertThat(accountAdded).isTrue(); 253 assertThat(am.getPassword(account)).isNull(); 254 255 am.setPassword(account, "passwd"); 256 assertThat(am.getPassword(account)).isEqualTo("passwd"); 257 } 258 259 @Test 260 public void testGetSetPassword_overwrite() { 261 Account account = new Account("name", "type"); 262 boolean accountAdded = am.addAccountExplicitly(account, "passwd1", null); 263 264 assertThat(accountAdded).isTrue(); 265 assertThat(am.getPassword(account)).isEqualTo("passwd1"); 266 267 am.setPassword(account, "passwd2"); 268 assertThat(am.getPassword(account)).isEqualTo("passwd2"); 269 } 270 271 @Test 272 public void testGetSetPassword_remove() { 273 Account account = new Account("name", "type"); 274 boolean accountAdded = am.addAccountExplicitly(account, "passwd1", null); 275 276 assertThat(accountAdded).isTrue(); 277 assertThat(am.getPassword(account)).isEqualTo("passwd1"); 278 279 am.setPassword(account, null); 280 assertThat(am.getPassword(account)).isNull(); 281 } 282 283 @Test 284 public void testBlockingGetAuthToken() throws AuthenticatorException, OperationCanceledException, IOException { 285 Account account = new Account("name", "type"); 286 shadowOf(am).addAccount(account); 287 288 am.setAuthToken(account, "token_type_1", "token1"); 289 am.setAuthToken(account, "token_type_2", "token2"); 290 291 assertThat(am.blockingGetAuthToken(account, "token_type_1", false)).isEqualTo("token1"); 292 assertThat(am.blockingGetAuthToken(account, "token_type_2", false)).isEqualTo("token2"); 293 294 try { 295 am.blockingGetAuthToken(null, "token_type_1", false); 296 fail("blockingGetAuthToken() should throw an illegal argument exception if the account is null"); 297 } catch (IllegalArgumentException iae) { 298 // Expected 299 } 300 try { 301 am.blockingGetAuthToken(account, null, false); 302 fail("blockingGetAuthToken() should throw an illegal argument exception if the auth token type is null"); 303 } catch (IllegalArgumentException iae) { 304 // Expected 305 } 306 307 Account account1 = new Account("unknown", "type"); 308 assertThat(am.blockingGetAuthToken(account1, "token_type_1", false)).isNull(); 309 } 310 311 @Test 312 public void removeAccount_throwsIllegalArgumentException_whenPassedNullAccount() { 313 Account account = new Account("name", "type"); 314 shadowOf(am).addAccount(account); 315 316 try { 317 am.removeAccount(null, null, null); 318 fail("removeAccount() should throw an illegal argument exception if the account is null"); 319 } catch (IllegalArgumentException iae) { 320 // Expected 321 } 322 } 323 324 @Test 325 public void removeAccount_doesNotRemoveAccountOfDifferentName() throws Exception { 326 Account account = new Account("name", "type"); 327 shadowOf(am).addAccount(account); 328 329 Account wrongAccount = new Account("wrong_name", "type"); 330 AccountManagerFuture<Boolean> future = am.removeAccount(wrongAccount, null, null); 331 assertThat(future.getResult()).isFalse(); 332 assertThat(am.getAccountsByType("type")).isNotEmpty(); 333 } 334 335 @Test 336 public void removeAccount_does() throws Exception { 337 Account account = new Account("name", "type"); 338 shadowOf(am).addAccount(account); 339 340 TestAccountManagerCallback<Boolean> testAccountManagerCallback = new TestAccountManagerCallback<>(); 341 AccountManagerFuture<Boolean> future = am.removeAccount(account, testAccountManagerCallback, null); 342 assertThat(future.getResult()).isTrue(); 343 assertThat(am.getAccountsByType("type")).isEmpty(); 344 345 assertThat(testAccountManagerCallback.accountManagerFuture).isNotNull(); 346 } 347 348 @Test 349 public void removeAccount_notifiesListenersIfSuccessful() { 350 Account account = new Account("name", "type"); 351 am.addAccountExplicitly(account, "passwd", null); 352 353 TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener(); 354 am.addOnAccountsUpdatedListener(listener, null, false); 355 assertThat(listener.getInvocationCount()).isEqualTo(0); 356 357 am.removeAccount(account, null, null); 358 359 assertThat(listener.getInvocationCount()).isEqualTo(1); 360 } 361 362 @Test 363 public void removeAccount_doesNotNotifyIfUnuccessful() { 364 Account account = new Account("name", "type"); 365 366 TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener(); 367 am.addOnAccountsUpdatedListener(listener, null, false); 368 assertThat(listener.getInvocationCount()).isEqualTo(0); 369 370 // The account has not been added 371 am.removeAccount(account, null, null); 372 373 assertThat(listener.getInvocationCount()).isEqualTo(0); 374 } 375 376 private static class TestOnAccountsUpdateListener implements OnAccountsUpdateListener { 377 private int invocationCount = 0; 378 379 @Override 380 public void onAccountsUpdated(Account[] accounts) { 381 invocationCount++; 382 } 383 384 public int getInvocationCount() { 385 return invocationCount; 386 } 387 } 388 389 @Test 390 public void testAccountsUpdateListener() { 391 TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener(); 392 am.addOnAccountsUpdatedListener(listener, null, false); 393 assertThat(listener.getInvocationCount()).isEqualTo(0); 394 395 Account account = new Account("name", "type"); 396 shadowOf(am).addAccount(account); 397 assertThat(listener.getInvocationCount()).isEqualTo(1); 398 } 399 400 @Test 401 public void testAccountsUpdateListener_duplicate() { 402 TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener(); 403 am.addOnAccountsUpdatedListener(listener, null, false); 404 am.addOnAccountsUpdatedListener(listener, null, false); 405 assertThat(listener.getInvocationCount()).isEqualTo(0); 406 407 Account account = new Account("name", "type"); 408 shadowOf(am).addAccount(account); 409 assertThat(listener.getInvocationCount()).isEqualTo(1); 410 } 411 412 @Test 413 public void testAccountsUpdateListener_updateImmediately() { 414 TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener(); 415 am.addOnAccountsUpdatedListener(listener, null, true); 416 assertThat(listener.getInvocationCount()).isEqualTo(1); 417 } 418 419 @Test 420 public void testAccountsUpdateListener_listenerNotInvokedAfterRemoval() { 421 TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener(); 422 am.addOnAccountsUpdatedListener(listener, null, false); 423 assertThat(listener.getInvocationCount()).isEqualTo(0); 424 425 Account account = new Account("name", "type"); 426 shadowOf(am).addAccount(account); 427 428 assertThat(listener.getInvocationCount()).isEqualTo(1); 429 430 am.removeOnAccountsUpdatedListener(listener); 431 432 shadowOf(am).addAccount(account); 433 434 assertThat(listener.getInvocationCount()).isEqualTo(1); 435 } 436 437 @Test 438 public void testAddAuthenticator() { 439 shadowOf(am).addAuthenticator("type"); 440 AuthenticatorDescription[] result = am.getAuthenticatorTypes(); 441 assertThat(result.length).isEqualTo(1); 442 assertThat(result[0].type).isEqualTo("type"); 443 } 444 445 @Test 446 public void invalidateAuthToken_noAccount() { 447 am.invalidateAuthToken("type1", "token1"); 448 } 449 450 @Test 451 public void invalidateAuthToken_noToken() { 452 Account account1 = new Account("name", "type1"); 453 shadowOf(am).addAccount(account1); 454 am.invalidateAuthToken("type1", "token1"); 455 } 456 457 @Test 458 public void invalidateAuthToken_multipleAccounts() { 459 Account account1 = new Account("name", "type1"); 460 shadowOf(am).addAccount(account1); 461 462 Account account2 = new Account("name", "type2"); 463 shadowOf(am).addAccount(account2); 464 465 am.setAuthToken(account1, "token_type_1", "token1"); 466 am.setAuthToken(account2, "token_type_1", "token1"); 467 468 assertThat(am.peekAuthToken(account1, "token_type_1")).isEqualTo("token1"); 469 assertThat(am.peekAuthToken(account2, "token_type_1")).isEqualTo("token1"); 470 471 // invalidate token for type1 account 472 am.invalidateAuthToken("type1", "token1"); 473 assertThat(am.peekAuthToken(account1, "token_type_1")).isNull(); 474 assertThat(am.peekAuthToken(account2, "token_type_1")).isEqualTo("token1"); 475 476 // invalidate token for type2 account 477 am.invalidateAuthToken("type2", "token1"); 478 assertThat(am.peekAuthToken(account1, "token_type_1")).isNull(); 479 assertThat(am.peekAuthToken(account2, "token_type_1")).isNull(); 480 } 481 482 @Test 483 public void invalidateAuthToken_multipleTokens() { 484 Account account = new Account("name", "type1"); 485 shadowOf(am).addAccount(account); 486 487 am.setAuthToken(account, "token_type_1", "token1"); 488 am.setAuthToken(account, "token_type_2", "token2"); 489 490 assertThat(am.peekAuthToken(account, "token_type_1")).isEqualTo("token1"); 491 assertThat(am.peekAuthToken(account, "token_type_2")).isEqualTo("token2"); 492 493 // invalidate token1 494 am.invalidateAuthToken("type1", "token1"); 495 assertThat(am.peekAuthToken(account, "token_type_1")).isNull(); 496 assertThat(am.peekAuthToken(account, "token_type_2")).isEqualTo("token2"); 497 498 // invalidate token2 499 am.invalidateAuthToken("type1", "token2"); 500 assertThat(am.peekAuthToken(account, "token_type_1")).isNull(); 501 assertThat(am.peekAuthToken(account, "token_type_2")).isNull(); 502 } 503 504 @Test 505 public void invalidateAuthToken_multipleTokenTypesSameToken() { 506 Account account = new Account("name", "type1"); 507 shadowOf(am).addAccount(account); 508 509 am.setAuthToken(account, "token_type_1", "token1"); 510 am.setAuthToken(account, "token_type_2", "token1"); 511 512 assertThat(am.peekAuthToken(account, "token_type_1")).isEqualTo("token1"); 513 assertThat(am.peekAuthToken(account, "token_type_2")).isEqualTo("token1"); 514 515 // invalidate token1 516 am.invalidateAuthToken("type1", "token1"); 517 assertThat(am.peekAuthToken(account, "token_type_1")).isNull(); 518 assertThat(am.peekAuthToken(account, "token_type_2")).isNull(); 519 } 520 521 @Test 522 public void addAccount_noActivitySpecified() throws Exception { 523 shadowOf(am).addAuthenticator("google.com"); 524 525 AccountManagerFuture<Bundle> result = am.addAccount("google.com", "auth_token_type", null, null, null, null, null); 526 527 Bundle resultBundle = result.getResult(); 528 529 assertThat((Intent) resultBundle.getParcelable(AccountManager.KEY_INTENT)).isNotNull(); 530 } 531 532 @Test 533 public void addAccount_activitySpecified() throws Exception { 534 shadowOf(am).addAuthenticator("google.com"); 535 536 AccountManagerFuture<Bundle> result = am.addAccount("google.com", "auth_token_type", null, null, activity, null, null); 537 Bundle resultBundle = result.getResult(); 538 539 assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_TYPE)).isEqualTo("google.com"); 540 assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_NAME)).isEqualTo("some_user (at) gmail.com"); 541 } 542 543 @Test 544 public void addAccount_shouldCallCallback() throws Exception { 545 shadowOf(am).addAuthenticator("google.com"); 546 547 TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>(); 548 AccountManagerFuture<Bundle> result = am.addAccount("google.com", "auth_token_type", null, null, activity, callback, new Handler()); 549 550 assertThat(callback.hasBeenCalled()).isFalse(); 551 assertThat(result.isDone()).isFalse(); 552 553 shadowOf(am).addAccount(new Account("thebomb (at) google.com", "google.com")); 554 assertThat(result.isDone()).isTrue(); 555 assertThat(callback.accountManagerFuture).isNotNull(); 556 557 Bundle resultBundle = callback.getResult(); 558 assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_TYPE)).isEqualTo("google.com"); 559 assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_NAME)).isEqualTo("thebomb (at) google.com"); 560 } 561 562 @Test 563 public void addAccount_whenSchedulerPaused_shouldCallCallbackAfterSchedulerUnpaused() throws Exception { 564 scheduler.pause(); 565 shadowOf(am).addAuthenticator("google.com"); 566 567 TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>(); 568 am.addAccount("google.com", "auth_token_type", null, null, activity, callback, new Handler()); 569 assertThat(callback.hasBeenCalled()).isFalse(); 570 571 shadowOf(am).addAccount(new Account("thebomb (at) google.com", "google.com")); 572 573 scheduler.unPause(); 574 assertThat(callback.hasBeenCalled()).isTrue(); 575 576 Bundle resultBundle = callback.getResult(); 577 assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_TYPE)).isEqualTo("google.com"); 578 assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_NAME)).isEqualTo("thebomb (at) google.com"); 579 } 580 581 @Test 582 public void addAccount_noAuthenticatorDefined() throws Exception { 583 AccountManagerFuture<Bundle> future = am.addAccount("unknown_account_type", "auth_token_type", null, null, activity, null, null); 584 try { 585 future.getResult(); 586 fail("addAccount() should throw an authenticator exception if no authenticator was registered for this account type"); 587 } catch(AuthenticatorException e) { 588 // Expected 589 } 590 assertThat(future.isDone()).isTrue(); 591 } 592 593 @Test 594 public void addAccount_withOptionsShouldSupportGetNextAddAccountOptions() throws Exception { 595 assertThat(shadowOf(am).getNextAddAccountOptions()).isNull(); 596 597 shadowOf(am).addAuthenticator("google.com"); 598 599 Bundle expectedAddAccountOptions = new Bundle(); 600 expectedAddAccountOptions.putString("option", "value"); 601 602 am.addAccount("google.com", "auth_token_type", null, expectedAddAccountOptions, activity, null, null); 603 604 Bundle actualAddAccountOptions = shadowOf(am).getNextAddAccountOptions(); 605 assertThat(shadowOf(am).getNextAddAccountOptions()).isNull(); 606 assertThat(actualAddAccountOptions).isEqualTo(expectedAddAccountOptions); 607 } 608 609 @Test 610 public void addAccount_withOptionsShouldSupportPeekNextAddAccountOptions() throws Exception { 611 assertThat(shadowOf(am).peekNextAddAccountOptions()).isNull(); 612 613 shadowOf(am).addAuthenticator("google.com"); 614 615 Bundle expectedAddAccountOptions = new Bundle(); 616 expectedAddAccountOptions.putString("option", "value"); 617 am.addAccount("google.com", "auth_token_type", null, expectedAddAccountOptions, activity, null, null); 618 619 Bundle actualAddAccountOptions = shadowOf(am).peekNextAddAccountOptions(); 620 assertThat(shadowOf(am).peekNextAddAccountOptions()).isNotNull(); 621 assertThat(actualAddAccountOptions).isEqualTo(expectedAddAccountOptions); 622 } 623 624 @Test 625 public void addAccount_withNoAuthenticatorForType_throwsExceptionInGetResult() throws Exception { 626 assertThat(shadowOf(am).peekNextAddAccountOptions()).isNull(); 627 628 AccountManagerFuture<Bundle> futureResult = am.addAccount("google.com", "auth_token_type", null, null, activity, null, null); 629 try { 630 futureResult.getResult(); 631 fail("should have thrown"); 632 } catch (AuthenticatorException expected) { } 633 } 634 635 @Test 636 @Config(minSdk = LOLLIPOP) 637 public void addPreviousAccount() { 638 Account account = new Account("name_a", "type_a"); 639 shadowOf(am).setPreviousAccountName(account, "old_name"); 640 assertThat(am.getPreviousName(account)).isEqualTo("old_name"); 641 } 642 643 @Test 644 public void testGetAsSystemService() throws Exception { 645 AccountManager systemService = 646 (AccountManager) 647 ApplicationProvider.getApplicationContext().getSystemService(Context.ACCOUNT_SERVICE); 648 assertThat(systemService).isNotNull(); 649 assertThat(am).isEqualTo(systemService); 650 } 651 652 @Test 653 public void getAuthToken_withActivity_returnsCorrectToken() throws Exception { 654 Account account = new Account("name", "google.com"); 655 shadowOf(am).addAccount(account); 656 shadowOf(am).addAuthenticator("google.com"); 657 658 am.setAuthToken(account, "auth_token_type", "token1"); 659 660 TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>(); 661 AccountManagerFuture<Bundle> future = am.getAuthToken(account, 662 "auth_token_type", 663 new Bundle(), 664 activity, 665 callback, 666 new Handler()); 667 668 assertThat(future.isDone()).isTrue(); 669 assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_NAME)).isEqualTo(account.name); 670 assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_TYPE)).isEqualTo(account.type); 671 assertThat(future.getResult().getString(AccountManager.KEY_AUTHTOKEN)).isEqualTo("token1"); 672 673 assertThat(callback.hasBeenCalled()).isTrue(); 674 } 675 676 @Test 677 public void getAuthToken_withActivity_returnsAuthIntent() throws Exception { 678 Account account = new Account("name", "google.com"); 679 shadowOf(am).addAccount(account); 680 shadowOf(am).addAuthenticator("google.com"); 681 682 TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>(); 683 AccountManagerFuture<Bundle> future = am.getAuthToken(account, 684 "auth_token_type", 685 new Bundle(), 686 activity, 687 callback, 688 new Handler()); 689 690 assertThat(future.isDone()).isTrue(); 691 assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_NAME)) 692 .isEqualTo(account.name); 693 assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_TYPE)) 694 .isEqualTo(account.type); 695 assertThat(future.getResult().getString(AccountManager.KEY_AUTHTOKEN)).isNull(); 696 assertThat((Intent) future.getResult().getParcelable(AccountManager.KEY_INTENT)).isNotNull(); 697 698 assertThat(callback.hasBeenCalled()).isTrue(); 699 } 700 701 @Test 702 public void getAuthToken_withNotifyAuthFailureSetToFalse_returnsCorrectToken() throws Exception { 703 Account account = new Account("name", "google.com"); 704 shadowOf(am).addAccount(account); 705 shadowOf(am).addAuthenticator("google.com"); 706 707 am.setAuthToken(account, "auth_token_type", "token1"); 708 709 TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>(); 710 AccountManagerFuture<Bundle> future = 711 am.getAuthToken( 712 account, 713 "auth_token_type", 714 new Bundle(), 715 /* notifyAuthFailure= */ false, 716 callback, 717 new Handler()); 718 719 assertThat(future.isDone()).isTrue(); 720 assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_NAME)) 721 .isEqualTo(account.name); 722 assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_TYPE)) 723 .isEqualTo(account.type); 724 assertThat(future.getResult().getString(AccountManager.KEY_AUTHTOKEN)).isEqualTo("token1"); 725 726 assertThat(callback.hasBeenCalled()).isTrue(); 727 } 728 729 @Test 730 public void getAuthToken_withNotifyAuthFailureSetToFalse_returnsAuthIntent() throws Exception { 731 Account account = new Account("name", "google.com"); 732 shadowOf(am).addAccount(account); 733 shadowOf(am).addAuthenticator("google.com"); 734 735 TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>(); 736 AccountManagerFuture<Bundle> future = 737 am.getAuthToken( 738 account, 739 "auth_token_type", 740 new Bundle(), 741 /* notifyAuthFailure= */ false, 742 callback, 743 new Handler()); 744 745 assertThat(future.isDone()).isTrue(); 746 assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_NAME)) 747 .isEqualTo(account.name); 748 assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_TYPE)) 749 .isEqualTo(account.type); 750 assertThat(future.getResult().getString(AccountManager.KEY_AUTHTOKEN)).isNull(); 751 assertThat((Intent) future.getResult().getParcelable(AccountManager.KEY_INTENT)).isNotNull(); 752 753 assertThat(callback.hasBeenCalled()).isTrue(); 754 } 755 756 @Test 757 public void getHasFeatures_returnsTrueWhenAllFeaturesSatisfied() throws Exception { 758 Account account = new Account("name", "google.com"); 759 shadowOf(am).addAccount(account); 760 shadowOf(am).setFeatures(account, new String[] { "FEATURE_1", "FEATURE_2" }); 761 762 TestAccountManagerCallback<Boolean> callback = new TestAccountManagerCallback<>(); 763 AccountManagerFuture<Boolean> future = am.hasFeatures(account, new String[] { "FEATURE_1", "FEATURE_2" }, callback, new Handler()); 764 765 assertThat(future.isDone()).isTrue(); 766 assertThat(future.getResult().booleanValue()).isEqualTo(true); 767 768 assertThat(callback.hasBeenCalled()).isTrue(); 769 } 770 771 @Test 772 public void getHasFeatures_returnsFalseWhenAllFeaturesNotSatisfied() throws Exception { 773 Account account = new Account("name", "google.com"); 774 shadowOf(am).addAccount(account); 775 shadowOf(am).setFeatures(account, new String[] { "FEATURE_1" }); 776 777 TestAccountManagerCallback<Boolean> callback = new TestAccountManagerCallback<>(); 778 AccountManagerFuture<Boolean> future = am.hasFeatures(account, new String[] { "FEATURE_1", "FEATURE_2" }, callback, new Handler()); 779 780 assertThat(future.isDone()).isTrue(); 781 assertThat(future.getResult().booleanValue()).isEqualTo(false); 782 assertThat(callback.hasBeenCalled()).isTrue(); 783 } 784 785 @Test 786 public void getAccountsByTypeAndFeatures() throws Exception { 787 788 Account accountWithCorrectTypeAndFeatures = new Account("account_1", "google.com"); 789 shadowOf(am).addAccount(accountWithCorrectTypeAndFeatures); 790 shadowOf(am).setFeatures(accountWithCorrectTypeAndFeatures, new String[] { "FEATURE_1", "FEATURE_2" }); 791 792 Account accountWithCorrectTypeButNotFeatures = new Account("account_2", "google.com"); 793 shadowOf(am).addAccount(accountWithCorrectTypeButNotFeatures); 794 shadowOf(am).setFeatures(accountWithCorrectTypeButNotFeatures, new String[] { "FEATURE_1" }); 795 796 Account accountWithCorrectFeaturesButNotType = new Account("account_3", "facebook.com"); 797 shadowOf(am).addAccount(accountWithCorrectFeaturesButNotType); 798 shadowOf(am).setFeatures(accountWithCorrectFeaturesButNotType, new String[] { "FEATURE_1", "FEATURE_2" }); 799 800 801 TestAccountManagerCallback<Account[]> callback = new TestAccountManagerCallback<>(); 802 803 AccountManagerFuture<Account[]> future = am.getAccountsByTypeAndFeatures("google.com", new String[] { "FEATURE_1", "FEATURE_2" }, callback, new Handler()); 804 805 assertThat(future.isDone()).isTrue(); 806 assertThat(future.getResult()).asList().containsExactly(accountWithCorrectTypeAndFeatures); 807 808 assertThat(callback.hasBeenCalled()).isTrue(); 809 } 810 811 @Test 812 public void getAccountsByTypeAndFeatures_returnsAllAccountsForNullFeature() throws Exception { 813 814 Account accountWithCorrectTypeAndFeatures = new Account("account_1", "google.com"); 815 shadowOf(am).addAccount(accountWithCorrectTypeAndFeatures); 816 shadowOf(am).setFeatures( 817 accountWithCorrectTypeAndFeatures, new String[] { "FEATURE_1", "FEATURE_2" }); 818 819 Account accountWithCorrectTypeButNotFeatures = new Account("account_2", "google.com"); 820 shadowOf(am).addAccount(accountWithCorrectTypeButNotFeatures); 821 shadowOf(am).setFeatures(accountWithCorrectTypeButNotFeatures, new String[] { "FEATURE_1" }); 822 823 Account accountWithCorrectFeaturesButNotType = new Account("account_3", "facebook.com"); 824 shadowOf(am).addAccount(accountWithCorrectFeaturesButNotType); 825 shadowOf(am).setFeatures( 826 accountWithCorrectFeaturesButNotType, new String[] { "FEATURE_1", "FEATURE_2" }); 827 828 829 TestAccountManagerCallback<Account[]> callback = new TestAccountManagerCallback<>(); 830 831 AccountManagerFuture<Account[]> future = 832 am.getAccountsByTypeAndFeatures("google.com", null, callback, new Handler()); 833 834 assertThat(future.isDone()).isTrue(); 835 assertThat(future.getResult()).asList() 836 .containsExactly(accountWithCorrectTypeAndFeatures, accountWithCorrectTypeButNotFeatures); 837 838 assertThat(callback.hasBeenCalled()).isTrue(); 839 } 840 841 @Test 842 @Config(minSdk = JELLY_BEAN_MR2) 843 public void getAccountsByTypeForPackage() { 844 Account[] accountsByTypeForPackage = am.getAccountsByTypeForPackage(null, "org.somepackage"); 845 846 assertThat(accountsByTypeForPackage).isEmpty(); 847 848 Account accountVisibleToPackage = new Account("user (at) gmail.com", "gmail.com"); 849 shadowOf(am).addAccount(accountVisibleToPackage, "org.somepackage"); 850 851 accountsByTypeForPackage = am.getAccountsByTypeForPackage("other_type", "org.somepackage"); 852 assertThat(accountsByTypeForPackage).isEmpty(); 853 854 accountsByTypeForPackage = am.getAccountsByTypeForPackage("gmail.com", "org.somepackage"); 855 assertThat(accountsByTypeForPackage).asList().containsExactly(accountVisibleToPackage); 856 857 accountsByTypeForPackage = am.getAccountsByTypeForPackage(null, "org.somepackage"); 858 assertThat(accountsByTypeForPackage).asList().containsExactly(accountVisibleToPackage); 859 } 860 861 @Test 862 @Config(minSdk = LOLLIPOP_MR1) 863 public void removeAccountExplicitly() { 864 assertThat(am.removeAccountExplicitly(new Account("non_existant_account (at) gmail.com", "gmail.com"))).isFalse(); 865 assertThat(am.removeAccountExplicitly(null)).isFalse(); 866 867 Account account = new Account("name (at) gmail.com", "gmail.com"); 868 shadowOf(am).addAccount(account); 869 870 assertThat(am.removeAccountExplicitly(account)).isTrue(); 871 } 872 873 @Test 874 public void removeAllAccounts() throws Exception { 875 876 Account account = new Account("name (at) gmail.com", "gmail.com"); 877 shadowOf(am).addAccount(account); 878 879 assertThat(am.getAccounts()).isNotEmpty(); 880 881 shadowOf(am).removeAllAccounts(); 882 883 assertThat(am.getAccounts()).isEmpty(); 884 } 885 886 @Test 887 public void testSetAuthenticationErrorOnNextResponse() 888 throws AuthenticatorException, IOException, OperationCanceledException { 889 890 shadowOf(am).setAuthenticationErrorOnNextResponse(true); 891 892 try { 893 am.getAccountsByTypeAndFeatures(null, null, null, null).getResult(); 894 fail("should have thrown"); 895 } catch (AuthenticatorException expected) { 896 // Expected 897 } 898 899 am.getAccountsByTypeAndFeatures(null, null, null, null).getResult(); 900 } 901 902 private static class TestAccountManagerCallback<T> implements AccountManagerCallback<T> { 903 private AccountManagerFuture<T> accountManagerFuture; 904 905 @Override 906 public void run(AccountManagerFuture<T> accountManagerFuture) { 907 this.accountManagerFuture = accountManagerFuture; 908 } 909 910 boolean hasBeenCalled() { 911 return accountManagerFuture != null; 912 } 913 914 T getResult() throws Exception { 915 return accountManagerFuture.getResult(); 916 } 917 } 918 } 919