• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
4 import static android.os.Build.VERSION_CODES.O;
5 import static com.google.common.truth.Truth.assertThat;
6 import static org.junit.Assert.fail;
7 import static org.robolectric.Shadows.shadowOf;
8 import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
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 java.util.Arrays;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 import org.robolectric.Robolectric;
31 import org.robolectric.android.controller.ActivityController;
32 import org.robolectric.annotation.Config;
33 
34 @RunWith(AndroidJUnit4.class)
35 public class ShadowAccountManagerTest {
36   private AccountManager am;
37   private Activity activity;
38   private Context appContext;
39 
40   @Before
setUp()41   public void setUp() throws Exception {
42     am = AccountManager.get(ApplicationProvider.getApplicationContext());
43     activity = new Activity();
44     appContext = ApplicationProvider.getApplicationContext();
45   }
46 
47   @Test
testGet()48   public void testGet() {
49     assertThat(am).isNotNull();
50     assertThat(am)
51         .isSameInstanceAs(AccountManager.get(ApplicationProvider.getApplicationContext()));
52 
53     AccountManager activityAM = AccountManager.get(ApplicationProvider.getApplicationContext());
54     assertThat(activityAM).isNotNull();
55     assertThat(activityAM).isSameInstanceAs(am);
56   }
57 
58   @Test
testGetAccounts()59   public void testGetAccounts() {
60     assertThat(am.getAccounts()).isNotNull();
61     assertThat(am.getAccounts().length).isEqualTo(0);
62 
63     Account a1 = new Account("name_a", "type_a");
64     shadowOf(am).addAccount(a1);
65     assertThat(am.getAccounts()).isNotNull();
66     assertThat(am.getAccounts().length).isEqualTo(1);
67     assertThat(am.getAccounts()[0]).isSameInstanceAs(a1);
68 
69     Account a2 = new Account("name_b", "type_b");
70     shadowOf(am).addAccount(a2);
71     assertThat(am.getAccounts()).isNotNull();
72     assertThat(am.getAccounts().length).isEqualTo(2);
73     assertThat(am.getAccounts()[1]).isSameInstanceAs(a2);
74   }
75 
76   @Test
getAccountsByType_nullTypeReturnsAllAccounts()77   public void getAccountsByType_nullTypeReturnsAllAccounts() {
78     shadowOf(am).addAccount(new Account("name_1", "type_1"));
79     shadowOf(am).addAccount(new Account("name_2", "type_2"));
80     shadowOf(am).addAccount(new Account("name_3", "type_3"));
81 
82     assertThat(am.getAccountsByType(null)).asList().containsAtLeastElementsIn(am.getAccounts());
83   }
84 
85   @Test
testGetAccountsByType()86   public void testGetAccountsByType() {
87     assertThat(am.getAccountsByType("name_a")).isNotNull();
88     assertThat(am.getAccounts().length).isEqualTo(0);
89 
90     Account a1 = new Account("name_a", "type_a");
91     shadowOf(am).addAccount(a1);
92     Account[] accounts = am.getAccountsByType("type_a");
93     assertThat(accounts).isNotNull();
94     assertThat(accounts.length).isEqualTo(1);
95     assertThat(accounts[0]).isSameInstanceAs(a1);
96 
97     Account a2 = new Account("name_b", "type_b");
98     shadowOf(am).addAccount(a2);
99     accounts = am.getAccountsByType("type_a");
100     assertThat(accounts).isNotNull();
101     assertThat(accounts.length).isEqualTo(1);
102     assertThat(accounts[0]).isSameInstanceAs(a1);
103 
104     Account a3 = new Account("name_c", "type_a");
105     shadowOf(am).addAccount(a3);
106     accounts = am.getAccountsByType("type_a");
107     assertThat(accounts).isNotNull();
108     assertThat(accounts.length).isEqualTo(2);
109     assertThat(accounts[0]).isSameInstanceAs(a1);
110     assertThat(accounts[1]).isSameInstanceAs(a3);
111   }
112 
113   @Test
addAuthToken()114   public void addAuthToken() {
115     Account account = new Account("name", "type");
116     shadowOf(am).addAccount(account);
117 
118     am.setAuthToken(account, "token_type_1", "token1");
119     am.setAuthToken(account, "token_type_2", "token2");
120 
121     assertThat(am.peekAuthToken(account, "token_type_1")).isEqualTo("token1");
122     assertThat(am.peekAuthToken(account, "token_type_2")).isEqualTo("token2");
123   }
124 
125   @Test
setAuthToken_shouldNotAddTokenIfAccountNotPresent()126   public void setAuthToken_shouldNotAddTokenIfAccountNotPresent() {
127     Account account = new Account("name", "type");
128     am.setAuthToken(account, "token_type_1", "token1");
129     assertThat(am.peekAuthToken(account, "token_type_1")).isNull();
130   }
131 
132   @Test
testAddAccountExplicitly_noPasswordNoExtras()133   public void testAddAccountExplicitly_noPasswordNoExtras() {
134     Account account = new Account("name", "type");
135     boolean accountAdded = am.addAccountExplicitly(account, null, null);
136 
137     assertThat(accountAdded).isTrue();
138     assertThat(am.getAccountsByType("type").length).isEqualTo(1);
139     assertThat(am.getAccountsByType("type")[0].name).isEqualTo("name");
140 
141     boolean accountAddedTwice = am.addAccountExplicitly(account, null, null);
142     assertThat(accountAddedTwice).isFalse();
143 
144     account = new Account("another_name", "type");
145     accountAdded = am.addAccountExplicitly(account, null, null);
146     assertThat(accountAdded).isTrue();
147     assertThat(am.getAccountsByType("type").length).isEqualTo(2);
148     assertThat(am.getAccountsByType("type")[0].name).isEqualTo("name");
149     assertThat(am.getAccountsByType("type")[1].name).isEqualTo("another_name");
150     assertThat(am.getPassword(account)).isNull();
151 
152     try {
153       am.addAccountExplicitly(null, null, null);
154       fail(
155           "An illegal argument exception should have been thrown when trying to add a null"
156               + " account");
157     } catch (IllegalArgumentException iae) {
158       // NOP
159     }
160   }
161 
162   @Test
testAddAccountExplicitly_withPassword()163   public void testAddAccountExplicitly_withPassword() {
164     Account account = new Account("name", "type");
165     boolean accountAdded = am.addAccountExplicitly(account, "passwd", null);
166 
167     assertThat(accountAdded).isTrue();
168     assertThat(am.getPassword(account)).isEqualTo("passwd");
169   }
170 
171   @Test
testAddAccountExplicitly_withExtras()172   public void testAddAccountExplicitly_withExtras() {
173     Account account = new Account("name", "type");
174     Bundle extras = new Bundle();
175     extras.putString("key123", "value123");
176     boolean accountAdded = am.addAccountExplicitly(account, null, extras);
177 
178     assertThat(accountAdded).isTrue();
179     assertThat(am.getUserData(account, "key123")).isEqualTo("value123");
180     assertThat(am.getUserData(account, "key456")).isNull();
181   }
182 
183   @Test
testAddAccountExplicitly_notifiesListenersIfSuccessful()184   public void testAddAccountExplicitly_notifiesListenersIfSuccessful() {
185     TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener();
186     am.addOnAccountsUpdatedListener(listener, null, false);
187     assertThat(listener.getInvocationCount()).isEqualTo(0);
188 
189     Account account = new Account("name", "type");
190     boolean accountAdded = am.addAccountExplicitly(account, "passwd", null);
191 
192     assertThat(accountAdded).isTrue();
193     assertThat(listener.getInvocationCount()).isEqualTo(1);
194   }
195 
196   @Test
testAddAccountExplicitly_doesNotNotifyListenersIfUnsuccessful()197   public void testAddAccountExplicitly_doesNotNotifyListenersIfUnsuccessful() {
198     Account account = new Account("name", "type");
199     boolean accountAdded = am.addAccountExplicitly(account, "passwd", null);
200     assertThat(accountAdded).isTrue();
201 
202     TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener();
203     am.addOnAccountsUpdatedListener(listener, null, false);
204     assertThat(listener.getInvocationCount()).isEqualTo(0);
205 
206     // This account is added already, so it'll fail
207     boolean accountAdded2 = am.addAccountExplicitly(account, "passwd", null);
208     assertThat(accountAdded2).isFalse();
209     assertThat(listener.getInvocationCount()).isEqualTo(0);
210   }
211 
212   @Test
testGetSetUserData_addToInitiallyEmptyExtras()213   public void testGetSetUserData_addToInitiallyEmptyExtras() {
214     Account account = new Account("name", "type");
215     boolean accountAdded = am.addAccountExplicitly(account, null, null);
216 
217     assertThat(accountAdded).isTrue();
218 
219     am.setUserData(account, "key123", "value123");
220     assertThat(am.getUserData(account, "key123")).isEqualTo("value123");
221   }
222 
223   @Test
testGetSetUserData_overwrite()224   public void testGetSetUserData_overwrite() {
225     Account account = new Account("name", "type");
226     boolean accountAdded = am.addAccountExplicitly(account, null, null);
227 
228     assertThat(accountAdded).isTrue();
229 
230     am.setUserData(account, "key123", "value123");
231     assertThat(am.getUserData(account, "key123")).isEqualTo("value123");
232 
233     am.setUserData(account, "key123", "value456");
234     assertThat(am.getUserData(account, "key123")).isEqualTo("value456");
235   }
236 
237   @Test
testGetSetUserData_remove()238   public void testGetSetUserData_remove() {
239     Account account = new Account("name", "type");
240     boolean accountAdded = am.addAccountExplicitly(account, null, null);
241 
242     assertThat(accountAdded).isTrue();
243 
244     am.setUserData(account, "key123", "value123");
245     assertThat(am.getUserData(account, "key123")).isEqualTo("value123");
246 
247     am.setUserData(account, "key123", null);
248     assertThat(am.getUserData(account, "key123")).isNull();
249   }
250 
251   @Test
testGetSetPassword_setInAccountInitiallyWithNoPassword()252   public void testGetSetPassword_setInAccountInitiallyWithNoPassword() {
253     Account account = new Account("name", "type");
254     boolean accountAdded = am.addAccountExplicitly(account, null, null);
255 
256     assertThat(accountAdded).isTrue();
257     assertThat(am.getPassword(account)).isNull();
258 
259     am.setPassword(account, "passwd");
260     assertThat(am.getPassword(account)).isEqualTo("passwd");
261   }
262 
263   @Test
testGetSetPassword_overwrite()264   public void testGetSetPassword_overwrite() {
265     Account account = new Account("name", "type");
266     boolean accountAdded = am.addAccountExplicitly(account, "passwd1", null);
267 
268     assertThat(accountAdded).isTrue();
269     assertThat(am.getPassword(account)).isEqualTo("passwd1");
270 
271     am.setPassword(account, "passwd2");
272     assertThat(am.getPassword(account)).isEqualTo("passwd2");
273   }
274 
275   @Test
testGetSetPassword_remove()276   public void testGetSetPassword_remove() {
277     Account account = new Account("name", "type");
278     boolean accountAdded = am.addAccountExplicitly(account, "passwd1", null);
279 
280     assertThat(accountAdded).isTrue();
281     assertThat(am.getPassword(account)).isEqualTo("passwd1");
282 
283     am.setPassword(account, null);
284     assertThat(am.getPassword(account)).isNull();
285   }
286 
287   @Test
testBlockingGetAuthToken()288   public void testBlockingGetAuthToken()
289       throws AuthenticatorException, OperationCanceledException, IOException {
290     Account account = new Account("name", "type");
291     shadowOf(am).addAccount(account);
292 
293     am.setAuthToken(account, "token_type_1", "token1");
294     am.setAuthToken(account, "token_type_2", "token2");
295 
296     assertThat(am.blockingGetAuthToken(account, "token_type_1", false)).isEqualTo("token1");
297     assertThat(am.blockingGetAuthToken(account, "token_type_2", false)).isEqualTo("token2");
298 
299     try {
300       am.blockingGetAuthToken(null, "token_type_1", false);
301       fail(
302           "blockingGetAuthToken() should throw an illegal argument exception if the account is"
303               + " null");
304     } catch (IllegalArgumentException iae) {
305       // Expected
306     }
307     try {
308       am.blockingGetAuthToken(account, null, false);
309       fail(
310           "blockingGetAuthToken() should throw an illegal argument exception if the auth token"
311               + " type is null");
312     } catch (IllegalArgumentException iae) {
313       // Expected
314     }
315 
316     Account account1 = new Account("unknown", "type");
317     assertThat(am.blockingGetAuthToken(account1, "token_type_1", false)).isNull();
318   }
319 
320   @Test
removeAccount_throwsIllegalArgumentException_whenPassedNullAccount()321   public void removeAccount_throwsIllegalArgumentException_whenPassedNullAccount() {
322     Account account = new Account("name", "type");
323     shadowOf(am).addAccount(account);
324 
325     try {
326       am.removeAccount(null, null, null);
327       fail("removeAccount() should throw an illegal argument exception if the account is null");
328     } catch (IllegalArgumentException iae) {
329       // Expected
330     }
331   }
332 
333   @Test
removeAccount_doesNotRemoveAccountOfDifferentName()334   public void removeAccount_doesNotRemoveAccountOfDifferentName() throws Exception {
335     Account account = new Account("name", "type");
336     shadowOf(am).addAccount(account);
337 
338     Account wrongAccount = new Account("wrong_name", "type");
339     AccountManagerFuture<Boolean> future = am.removeAccount(wrongAccount, null, null);
340     assertThat(future.getResult()).isFalse();
341     assertThat(am.getAccountsByType("type")).isNotEmpty();
342   }
343 
344   @Test
removeAccount_does()345   public void removeAccount_does() throws Exception {
346     Account account = new Account("name", "type");
347     shadowOf(am).addAccount(account);
348 
349     TestAccountManagerCallback<Boolean> testAccountManagerCallback =
350         new TestAccountManagerCallback<>();
351     AccountManagerFuture<Boolean> future =
352         am.removeAccount(account, testAccountManagerCallback, null);
353     assertThat(future.getResult()).isTrue();
354     assertThat(am.getAccountsByType("type")).isEmpty();
355 
356     shadowMainLooper().idle();
357     assertThat(testAccountManagerCallback.accountManagerFuture).isNotNull();
358   }
359 
360   @Test
361   @Config(minSdk = LOLLIPOP_MR1)
removeAccount_withActivity()362   public void removeAccount_withActivity() throws Exception {
363     Account account = new Account("name", "type");
364     shadowOf(am).addAccount(account);
365 
366     TestAccountManagerCallback<Bundle> testAccountManagerCallback =
367         new TestAccountManagerCallback<>();
368     AccountManagerFuture<Bundle> future =
369         am.removeAccount(account, activity, testAccountManagerCallback, null);
370     Bundle result = future.getResult();
371 
372     assertThat(result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)).isTrue();
373     Intent removeAccountIntent = result.getParcelable(AccountManager.KEY_INTENT);
374     assertThat(removeAccountIntent).isNull();
375   }
376 
377   @Test
378   @Config(minSdk = LOLLIPOP_MR1)
removeAccount_withActivity_doesNotRemoveButReturnsIntent()379   public void removeAccount_withActivity_doesNotRemoveButReturnsIntent() throws Exception {
380     Account account = new Account("name", "type");
381     shadowOf(am).addAccount(account);
382     Intent intent = new Intent().setAction("remove-account-action");
383     shadowOf(am).setRemoveAccountIntent(intent);
384 
385     TestAccountManagerCallback<Bundle> testAccountManagerCallback =
386         new TestAccountManagerCallback<>();
387     AccountManagerFuture<Bundle> future =
388         am.removeAccount(account, activity, testAccountManagerCallback, null);
389     Bundle result = future.getResult();
390 
391     assertThat(result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)).isFalse();
392     Intent removeAccountIntent = result.getParcelable(AccountManager.KEY_INTENT);
393     assertThat(removeAccountIntent.getAction()).isEqualTo(intent.getAction());
394   }
395 
396   @Test
removeAccount_notifiesListenersIfSuccessful()397   public void removeAccount_notifiesListenersIfSuccessful() {
398     Account account = new Account("name", "type");
399     am.addAccountExplicitly(account, "passwd", null);
400 
401     TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener();
402     am.addOnAccountsUpdatedListener(listener, null, false);
403     assertThat(listener.getInvocationCount()).isEqualTo(0);
404 
405     am.removeAccount(account, null, null);
406 
407     assertThat(listener.getInvocationCount()).isEqualTo(1);
408   }
409 
410   @Test
removeAccount_doesNotNotifyIfUnuccessful()411   public void removeAccount_doesNotNotifyIfUnuccessful() {
412     Account account = new Account("name", "type");
413 
414     TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener();
415     am.addOnAccountsUpdatedListener(listener, null, false);
416     assertThat(listener.getInvocationCount()).isEqualTo(0);
417 
418     // The account has not been added
419     am.removeAccount(account, null, null);
420 
421     assertThat(listener.getInvocationCount()).isEqualTo(0);
422   }
423 
424   private static class TestOnAccountsUpdateListener implements OnAccountsUpdateListener {
425     private int invocationCount = 0;
426     private Account[] updatedAccounts;
427 
428     @Override
onAccountsUpdated(Account[] accounts)429     public void onAccountsUpdated(Account[] accounts) {
430       invocationCount++;
431       updatedAccounts = accounts;
432     }
433 
getInvocationCount()434     public int getInvocationCount() {
435       return invocationCount;
436     }
437 
getUpdatedAccounts()438     public Account[] getUpdatedAccounts() {
439       return updatedAccounts;
440     }
441   }
442 
443   @Test
testAccountsUpdateListener()444   public void testAccountsUpdateListener() {
445     TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener();
446     am.addOnAccountsUpdatedListener(listener, null, false);
447     assertThat(listener.getInvocationCount()).isEqualTo(0);
448 
449     Account account = new Account("name", "type");
450     shadowOf(am).addAccount(account);
451     assertThat(listener.getInvocationCount()).isEqualTo(1);
452   }
453 
454   @Test
testAccountsUpdateListener_duplicate()455   public void testAccountsUpdateListener_duplicate() {
456     TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener();
457     am.addOnAccountsUpdatedListener(listener, null, false);
458     am.addOnAccountsUpdatedListener(listener, null, false);
459     assertThat(listener.getInvocationCount()).isEqualTo(0);
460 
461     Account account = new Account("name", "type");
462     shadowOf(am).addAccount(account);
463     assertThat(listener.getInvocationCount()).isEqualTo(1);
464   }
465 
466   @Test
testAccountsUpdateListener_updateImmediately()467   public void testAccountsUpdateListener_updateImmediately() {
468     TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener();
469     am.addOnAccountsUpdatedListener(listener, null, true);
470     assertThat(listener.getInvocationCount()).isEqualTo(1);
471   }
472 
473   @Test
474   @Config(minSdk = O)
addOnAccountsUpdatedListener_notifiesListenersForAccountType()475   public void addOnAccountsUpdatedListener_notifiesListenersForAccountType() {
476     Account accountOne = new Account("name", "typeOne");
477     Account accountTwo = new Account("name", "typeTwo");
478     TestOnAccountsUpdateListener typeOneListener = new TestOnAccountsUpdateListener();
479     am.addOnAccountsUpdatedListener(
480         typeOneListener,
481         /* handler= */ null,
482         /* updateImmediately= */ false,
483         new String[] {"typeOne"});
484     TestOnAccountsUpdateListener typeTwoListener = new TestOnAccountsUpdateListener();
485     am.addOnAccountsUpdatedListener(
486         typeTwoListener, /* handler= */ null, /* updateImmediately= */ false);
487 
488     shadowOf(am).addAccount(accountOne);
489     shadowOf(am).addAccount(accountTwo);
490 
491     assertThat(typeOneListener.getInvocationCount()).isEqualTo(1);
492     assertThat(typeTwoListener.getInvocationCount()).isEqualTo(2);
493   }
494 
495   @Test
496   @Config(minSdk = O)
addOnAccountsUpdatedListener_updateImmediately_notifiesListenerSelectively()497   public void addOnAccountsUpdatedListener_updateImmediately_notifiesListenerSelectively() {
498     Account accountOne = new Account("name", "typeOne");
499     Account accountTwo = new Account("name", "typeTwo");
500     shadowOf(am).addAccount(accountOne);
501     shadowOf(am).addAccount(accountTwo);
502     TestOnAccountsUpdateListener typeOneListener = new TestOnAccountsUpdateListener();
503 
504     am.addOnAccountsUpdatedListener(
505         typeOneListener,
506         /* handler= */ null,
507         /* updateImmediately= */ true,
508         new String[] {"typeOne"});
509 
510     assertThat(Arrays.asList(typeOneListener.getUpdatedAccounts())).containsExactly(accountOne);
511   }
512 
513   @Test
testAccountsUpdateListener_listenerNotInvokedAfterRemoval()514   public void testAccountsUpdateListener_listenerNotInvokedAfterRemoval() {
515     TestOnAccountsUpdateListener listener = new TestOnAccountsUpdateListener();
516     am.addOnAccountsUpdatedListener(listener, null, false);
517     assertThat(listener.getInvocationCount()).isEqualTo(0);
518 
519     Account account = new Account("name", "type");
520     shadowOf(am).addAccount(account);
521 
522     assertThat(listener.getInvocationCount()).isEqualTo(1);
523 
524     am.removeOnAccountsUpdatedListener(listener);
525 
526     shadowOf(am).addAccount(account);
527 
528     assertThat(listener.getInvocationCount()).isEqualTo(1);
529   }
530 
531   @Test
testAddAuthenticator()532   public void testAddAuthenticator() {
533     shadowOf(am).addAuthenticator("type");
534     AuthenticatorDescription[] result = am.getAuthenticatorTypes();
535     assertThat(result.length).isEqualTo(1);
536     assertThat(result[0].type).isEqualTo("type");
537   }
538 
539   @Test
invalidateAuthToken_noAccount()540   public void invalidateAuthToken_noAccount() {
541     am.invalidateAuthToken("type1", "token1");
542   }
543 
544   @Test
invalidateAuthToken_noToken()545   public void invalidateAuthToken_noToken() {
546     Account account1 = new Account("name", "type1");
547     shadowOf(am).addAccount(account1);
548     am.invalidateAuthToken("type1", "token1");
549   }
550 
551   @Test
invalidateAuthToken_multipleAccounts()552   public void invalidateAuthToken_multipleAccounts() {
553     Account account1 = new Account("name", "type1");
554     shadowOf(am).addAccount(account1);
555 
556     Account account2 = new Account("name", "type2");
557     shadowOf(am).addAccount(account2);
558 
559     am.setAuthToken(account1, "token_type_1", "token1");
560     am.setAuthToken(account2, "token_type_1", "token1");
561 
562     assertThat(am.peekAuthToken(account1, "token_type_1")).isEqualTo("token1");
563     assertThat(am.peekAuthToken(account2, "token_type_1")).isEqualTo("token1");
564 
565     // invalidate token for type1 account
566     am.invalidateAuthToken("type1", "token1");
567     assertThat(am.peekAuthToken(account1, "token_type_1")).isNull();
568     assertThat(am.peekAuthToken(account2, "token_type_1")).isEqualTo("token1");
569 
570     // invalidate token for type2 account
571     am.invalidateAuthToken("type2", "token1");
572     assertThat(am.peekAuthToken(account1, "token_type_1")).isNull();
573     assertThat(am.peekAuthToken(account2, "token_type_1")).isNull();
574   }
575 
576   @Test
invalidateAuthToken_multipleTokens()577   public void invalidateAuthToken_multipleTokens() {
578     Account account = new Account("name", "type1");
579     shadowOf(am).addAccount(account);
580 
581     am.setAuthToken(account, "token_type_1", "token1");
582     am.setAuthToken(account, "token_type_2", "token2");
583 
584     assertThat(am.peekAuthToken(account, "token_type_1")).isEqualTo("token1");
585     assertThat(am.peekAuthToken(account, "token_type_2")).isEqualTo("token2");
586 
587     // invalidate token1
588     am.invalidateAuthToken("type1", "token1");
589     assertThat(am.peekAuthToken(account, "token_type_1")).isNull();
590     assertThat(am.peekAuthToken(account, "token_type_2")).isEqualTo("token2");
591 
592     // invalidate token2
593     am.invalidateAuthToken("type1", "token2");
594     assertThat(am.peekAuthToken(account, "token_type_1")).isNull();
595     assertThat(am.peekAuthToken(account, "token_type_2")).isNull();
596   }
597 
598   @Test
invalidateAuthToken_multipleTokenTypesSameToken()599   public void invalidateAuthToken_multipleTokenTypesSameToken() {
600     Account account = new Account("name", "type1");
601     shadowOf(am).addAccount(account);
602 
603     am.setAuthToken(account, "token_type_1", "token1");
604     am.setAuthToken(account, "token_type_2", "token1");
605 
606     assertThat(am.peekAuthToken(account, "token_type_1")).isEqualTo("token1");
607     assertThat(am.peekAuthToken(account, "token_type_2")).isEqualTo("token1");
608 
609     // invalidate token1
610     am.invalidateAuthToken("type1", "token1");
611     assertThat(am.peekAuthToken(account, "token_type_1")).isNull();
612     assertThat(am.peekAuthToken(account, "token_type_2")).isNull();
613   }
614 
615   @Test
616   @Config(minSdk = O)
startAddAccountSession_withNonNullActivity()617   public void startAddAccountSession_withNonNullActivity() throws Exception {
618     shadowOf(am).addAuthenticator("google.com");
619 
620     TestAccountManagerCallback<Bundle> testAccountManagerCallback =
621         new TestAccountManagerCallback<>();
622     AccountManagerFuture<Bundle> future =
623         am.startAddAccountSession(
624             "google.com",
625             /* authTokenType= */ null,
626             /* requiredFeatures= */ null,
627             /* options= */ null,
628             activity,
629             testAccountManagerCallback,
630             /* handler= */ null);
631 
632     shadowMainLooper().idle();
633     assertThat(testAccountManagerCallback.hasBeenCalled()).isTrue();
634 
635     Bundle result = future.getResult();
636     assertThat(result.getBundle(AccountManager.KEY_ACCOUNT_SESSION_BUNDLE)).isNotNull();
637   }
638 
639   @Test
640   @Config(minSdk = O)
startAddAccountSession_withNullActivity()641   public void startAddAccountSession_withNullActivity() throws Exception {
642     shadowOf(am).addAuthenticator("google.com");
643 
644     TestAccountManagerCallback<Bundle> testAccountManagerCallback =
645         new TestAccountManagerCallback<>();
646     AccountManagerFuture<Bundle> future =
647         am.startAddAccountSession(
648             "google.com",
649             /* authTokenType= */ null,
650             /* requiredFeatures= */ null,
651             /* options= */ null,
652             /* activity= */ null,
653             testAccountManagerCallback,
654             /* handler= */ null);
655 
656     shadowMainLooper().idle();
657     assertThat(testAccountManagerCallback.hasBeenCalled()).isTrue();
658 
659     Bundle result = future.getResult();
660     assertThat((Intent) result.getParcelable(AccountManager.KEY_INTENT)).isNotNull();
661   }
662 
663   @Test
664   @Config(minSdk = O)
startAddAccountSession_missingAuthenticator()665   public void startAddAccountSession_missingAuthenticator() throws Exception {
666     TestAccountManagerCallback<Bundle> testAccountManagerCallback =
667         new TestAccountManagerCallback<>();
668     AccountManagerFuture<Bundle> future =
669         am.startAddAccountSession(
670             "google.com",
671             /* authTokenType= */ null,
672             /* requiredFeatures= */ null,
673             /* options= */ null,
674             activity,
675             testAccountManagerCallback,
676             /* handler= */ null);
677 
678     shadowMainLooper().idle();
679     assertThat(testAccountManagerCallback.hasBeenCalled()).isTrue();
680 
681     try {
682       future.getResult();
683       fail(
684           "startAddAccountSession() should throw an authenticator exception if no authenticator "
685               + " was registered for this account type");
686     } catch (AuthenticatorException e) {
687       // Expected
688     }
689     assertThat(future.isDone()).isTrue();
690   }
691 
692   @Test
693   @Config(minSdk = O)
finishSession()694   public void finishSession() throws Exception {
695     Bundle sessionBundle = new Bundle();
696     sessionBundle.putString(AccountManager.KEY_ACCOUNT_NAME, "name");
697     sessionBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, "google.com");
698 
699     TestAccountManagerCallback<Bundle> testAccountManagerCallback =
700         new TestAccountManagerCallback<>();
701     AccountManagerFuture<Bundle> future =
702         am.finishSession(sessionBundle, activity, testAccountManagerCallback, null);
703 
704     shadowMainLooper().idle();
705     assertThat(testAccountManagerCallback.hasBeenCalled()).isTrue();
706 
707     Bundle result = future.getResult();
708     assertThat(result.getString(AccountManager.KEY_ACCOUNT_NAME)).isEqualTo("name");
709     assertThat(result.getString(AccountManager.KEY_ACCOUNT_TYPE)).isEqualTo("google.com");
710   }
711 
712   @Test
addAccount_noActivitySpecified()713   public void addAccount_noActivitySpecified() throws Exception {
714     shadowOf(am).addAuthenticator("google.com");
715 
716     AccountManagerFuture<Bundle> result =
717         am.addAccount("google.com", "auth_token_type", null, null, null, null, null);
718 
719     Bundle resultBundle = result.getResult();
720 
721     assertThat((Intent) resultBundle.getParcelable(AccountManager.KEY_INTENT)).isNotNull();
722   }
723 
724   @Test
addAccount_activitySpecified()725   public void addAccount_activitySpecified() throws Exception {
726     shadowOf(am).addAuthenticator("google.com");
727 
728     AccountManagerFuture<Bundle> result =
729         am.addAccount("google.com", "auth_token_type", null, null, activity, null, null);
730     Bundle resultBundle = result.getResult();
731 
732     assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_TYPE)).isEqualTo("google.com");
733     assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_NAME))
734         .isEqualTo("some_user@gmail.com");
735   }
736 
737   @Test
addAccount_shouldCallCallback()738   public void addAccount_shouldCallCallback() throws Exception {
739     shadowOf(am).addAuthenticator("google.com");
740 
741     TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>();
742     AccountManagerFuture<Bundle> result =
743         am.addAccount(
744             "google.com", "auth_token_type", null, null, activity, callback, new Handler());
745 
746     assertThat(callback.hasBeenCalled()).isFalse();
747     assertThat(result.isDone()).isFalse();
748 
749     shadowOf(am).addAccount(new Account("thebomb@google.com", "google.com"));
750     shadowMainLooper().idle();
751     assertThat(result.isDone()).isTrue();
752     assertThat(callback.accountManagerFuture).isNotNull();
753 
754     Bundle resultBundle = callback.getResult();
755     assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_TYPE)).isEqualTo("google.com");
756     assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_NAME))
757         .isEqualTo("thebomb@google.com");
758   }
759 
760   @Test
addAccount_whenSchedulerPaused_shouldCallCallbackAfterSchedulerUnpaused()761   public void addAccount_whenSchedulerPaused_shouldCallCallbackAfterSchedulerUnpaused()
762       throws Exception {
763     shadowMainLooper().pause();
764     shadowOf(am).addAuthenticator("google.com");
765 
766     TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>();
767     am.addAccount("google.com", "auth_token_type", null, null, activity, callback, new Handler());
768     assertThat(callback.hasBeenCalled()).isFalse();
769 
770     shadowOf(am).addAccount(new Account("thebomb@google.com", "google.com"));
771 
772     shadowMainLooper().idle();
773     assertThat(callback.hasBeenCalled()).isTrue();
774 
775     Bundle resultBundle = callback.getResult();
776     assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_TYPE)).isEqualTo("google.com");
777     assertThat(resultBundle.getString(AccountManager.KEY_ACCOUNT_NAME))
778         .isEqualTo("thebomb@google.com");
779   }
780 
781   @Test
addAccount_noAuthenticatorDefined()782   public void addAccount_noAuthenticatorDefined() throws Exception {
783     AccountManagerFuture<Bundle> future =
784         am.addAccount("unknown_account_type", "auth_token_type", null, null, activity, null, null);
785     try {
786       future.getResult();
787       fail(
788           "addAccount() should throw an authenticator exception if no authenticator was"
789               + " registered for this account type");
790     } catch (AuthenticatorException e) {
791       // Expected
792     }
793     assertThat(future.isDone()).isTrue();
794   }
795 
796   @Test
addAccount_withOptionsShouldSupportGetNextAddAccountOptions()797   public void addAccount_withOptionsShouldSupportGetNextAddAccountOptions() throws Exception {
798     assertThat(shadowOf(am).getNextAddAccountOptions()).isNull();
799 
800     shadowOf(am).addAuthenticator("google.com");
801 
802     Bundle expectedAddAccountOptions = new Bundle();
803     expectedAddAccountOptions.putString("option", "value");
804 
805     am.addAccount(
806         "google.com", "auth_token_type", null, expectedAddAccountOptions, activity, null, null);
807 
808     Bundle actualAddAccountOptions = shadowOf(am).getNextAddAccountOptions();
809     assertThat(shadowOf(am).getNextAddAccountOptions()).isNull();
810     assertThat(actualAddAccountOptions).isEqualTo(expectedAddAccountOptions);
811   }
812 
813   @Test
addAccount_withOptionsShouldSupportPeekNextAddAccountOptions()814   public void addAccount_withOptionsShouldSupportPeekNextAddAccountOptions() throws Exception {
815     assertThat(shadowOf(am).peekNextAddAccountOptions()).isNull();
816 
817     shadowOf(am).addAuthenticator("google.com");
818 
819     Bundle expectedAddAccountOptions = new Bundle();
820     expectedAddAccountOptions.putString("option", "value");
821     am.addAccount(
822         "google.com", "auth_token_type", null, expectedAddAccountOptions, activity, null, null);
823 
824     Bundle actualAddAccountOptions = shadowOf(am).peekNextAddAccountOptions();
825     assertThat(shadowOf(am).peekNextAddAccountOptions()).isNotNull();
826     assertThat(actualAddAccountOptions).isEqualTo(expectedAddAccountOptions);
827   }
828 
829   @Test
addAccount_withNoAuthenticatorForType_throwsExceptionInGetResult()830   public void addAccount_withNoAuthenticatorForType_throwsExceptionInGetResult() throws Exception {
831     assertThat(shadowOf(am).peekNextAddAccountOptions()).isNull();
832 
833     AccountManagerFuture<Bundle> futureResult =
834         am.addAccount("google.com", "auth_token_type", null, null, activity, null, null);
835     try {
836       futureResult.getResult();
837       fail("should have thrown");
838     } catch (AuthenticatorException expected) {
839     }
840   }
841 
842   @Test
addPreviousAccount()843   public void addPreviousAccount() {
844     Account account = new Account("name_a", "type_a");
845     shadowOf(am).setPreviousAccountName(account, "old_name");
846     assertThat(am.getPreviousName(account)).isEqualTo("old_name");
847   }
848 
849   @Test
testGetAsSystemService()850   public void testGetAsSystemService() throws Exception {
851     AccountManager systemService =
852         (AccountManager)
853             ApplicationProvider.getApplicationContext().getSystemService(Context.ACCOUNT_SERVICE);
854     assertThat(systemService).isNotNull();
855     assertThat(am).isEqualTo(systemService);
856   }
857 
858   @Test
getAuthToken_withActivity_returnsCorrectToken()859   public void getAuthToken_withActivity_returnsCorrectToken() throws Exception {
860     Account account = new Account("name", "google.com");
861     shadowOf(am).addAccount(account);
862     shadowOf(am).addAuthenticator("google.com");
863 
864     am.setAuthToken(account, "auth_token_type", "token1");
865 
866     TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>();
867     AccountManagerFuture<Bundle> future =
868         am.getAuthToken(
869             account, "auth_token_type", new Bundle(), activity, callback, new Handler());
870 
871     assertThat(future.isDone()).isTrue();
872     assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_NAME))
873         .isEqualTo(account.name);
874     assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_TYPE))
875         .isEqualTo(account.type);
876     assertThat(future.getResult().getString(AccountManager.KEY_AUTHTOKEN)).isEqualTo("token1");
877 
878     shadowMainLooper().idle();
879     assertThat(callback.hasBeenCalled()).isTrue();
880   }
881 
882   @Test
getAuthToken_withActivity_returnsAuthIntent()883   public void getAuthToken_withActivity_returnsAuthIntent() throws Exception {
884     Account account = new Account("name", "google.com");
885     shadowOf(am).addAccount(account);
886     shadowOf(am).addAuthenticator("google.com");
887 
888     TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>();
889     AccountManagerFuture<Bundle> future =
890         am.getAuthToken(
891             account, "auth_token_type", new Bundle(), activity, callback, new Handler());
892 
893     assertThat(future.isDone()).isTrue();
894     assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_NAME))
895         .isEqualTo(account.name);
896     assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_TYPE))
897         .isEqualTo(account.type);
898     assertThat(future.getResult().getString(AccountManager.KEY_AUTHTOKEN)).isNull();
899     assertThat((Intent) future.getResult().getParcelable(AccountManager.KEY_INTENT)).isNotNull();
900 
901     shadowMainLooper().idle();
902     assertThat(callback.hasBeenCalled()).isTrue();
903   }
904 
905   @Test
getAuthToken_withNotifyAuthFailureSetToFalse_returnsCorrectToken()906   public void getAuthToken_withNotifyAuthFailureSetToFalse_returnsCorrectToken() throws Exception {
907     Account account = new Account("name", "google.com");
908     shadowOf(am).addAccount(account);
909     shadowOf(am).addAuthenticator("google.com");
910 
911     am.setAuthToken(account, "auth_token_type", "token1");
912 
913     TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>();
914     AccountManagerFuture<Bundle> future =
915         am.getAuthToken(
916             account,
917             "auth_token_type",
918             new Bundle(),
919             /* notifyAuthFailure= */ false,
920             callback,
921             new Handler());
922 
923     assertThat(future.isDone()).isTrue();
924     assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_NAME))
925         .isEqualTo(account.name);
926     assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_TYPE))
927         .isEqualTo(account.type);
928     assertThat(future.getResult().getString(AccountManager.KEY_AUTHTOKEN)).isEqualTo("token1");
929 
930     shadowMainLooper().idle();
931     assertThat(callback.hasBeenCalled()).isTrue();
932   }
933 
934   @Test
getAuthToken_withNotifyAuthFailureSetToFalse_returnsAuthIntent()935   public void getAuthToken_withNotifyAuthFailureSetToFalse_returnsAuthIntent() throws Exception {
936     Account account = new Account("name", "google.com");
937     shadowOf(am).addAccount(account);
938     shadowOf(am).addAuthenticator("google.com");
939 
940     TestAccountManagerCallback<Bundle> callback = new TestAccountManagerCallback<>();
941     AccountManagerFuture<Bundle> future =
942         am.getAuthToken(
943             account,
944             "auth_token_type",
945             new Bundle(),
946             /* notifyAuthFailure= */ false,
947             callback,
948             new Handler());
949 
950     assertThat(future.isDone()).isTrue();
951     assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_NAME))
952         .isEqualTo(account.name);
953     assertThat(future.getResult().getString(AccountManager.KEY_ACCOUNT_TYPE))
954         .isEqualTo(account.type);
955     assertThat(future.getResult().getString(AccountManager.KEY_AUTHTOKEN)).isNull();
956     assertThat((Intent) future.getResult().getParcelable(AccountManager.KEY_INTENT)).isNotNull();
957 
958     shadowMainLooper().idle();
959     assertThat(callback.hasBeenCalled()).isTrue();
960   }
961 
962   @Test
getHasFeatures_returnsTrueWhenAllFeaturesSatisfied()963   public void getHasFeatures_returnsTrueWhenAllFeaturesSatisfied() throws Exception {
964     Account account = new Account("name", "google.com");
965     shadowOf(am).addAccount(account);
966     shadowOf(am).setFeatures(account, new String[] {"FEATURE_1", "FEATURE_2"});
967 
968     TestAccountManagerCallback<Boolean> callback = new TestAccountManagerCallback<>();
969     AccountManagerFuture<Boolean> future =
970         am.hasFeatures(account, new String[] {"FEATURE_1", "FEATURE_2"}, callback, new Handler());
971 
972     assertThat(future.isDone()).isTrue();
973     assertThat(future.getResult().booleanValue()).isEqualTo(true);
974 
975     shadowMainLooper().idle();
976     assertThat(callback.hasBeenCalled()).isTrue();
977   }
978 
979   @Test
getHasFeatures_returnsFalseWhenAllFeaturesNotSatisfied()980   public void getHasFeatures_returnsFalseWhenAllFeaturesNotSatisfied() throws Exception {
981     Account account = new Account("name", "google.com");
982     shadowOf(am).addAccount(account);
983     shadowOf(am).setFeatures(account, new String[] {"FEATURE_1"});
984 
985     TestAccountManagerCallback<Boolean> callback = new TestAccountManagerCallback<>();
986     AccountManagerFuture<Boolean> future =
987         am.hasFeatures(account, new String[] {"FEATURE_1", "FEATURE_2"}, callback, new Handler());
988 
989     assertThat(future.isDone()).isTrue();
990     assertThat(future.getResult().booleanValue()).isEqualTo(false);
991     shadowMainLooper().idle();
992     assertThat(callback.hasBeenCalled()).isTrue();
993   }
994 
995   @Test
getAccountsByTypeAndFeatures()996   public void getAccountsByTypeAndFeatures() throws Exception {
997 
998     Account accountWithCorrectTypeAndFeatures = new Account("account_1", "google.com");
999     shadowOf(am).addAccount(accountWithCorrectTypeAndFeatures);
1000     shadowOf(am)
1001         .setFeatures(accountWithCorrectTypeAndFeatures, new String[] {"FEATURE_1", "FEATURE_2"});
1002 
1003     Account accountWithCorrectTypeButNotFeatures = new Account("account_2", "google.com");
1004     shadowOf(am).addAccount(accountWithCorrectTypeButNotFeatures);
1005     shadowOf(am).setFeatures(accountWithCorrectTypeButNotFeatures, new String[] {"FEATURE_1"});
1006 
1007     Account accountWithCorrectTypeButEmptyFeatures = new Account("account_3", "google.com");
1008     shadowOf(am).addAccount(accountWithCorrectTypeButEmptyFeatures);
1009 
1010     Account accountWithCorrectFeaturesButNotType = new Account("account_4", "facebook.com");
1011     shadowOf(am).addAccount(accountWithCorrectFeaturesButNotType);
1012     shadowOf(am)
1013         .setFeatures(accountWithCorrectFeaturesButNotType, new String[] {"FEATURE_1", "FEATURE_2"});
1014 
1015     TestAccountManagerCallback<Account[]> callback = new TestAccountManagerCallback<>();
1016 
1017     AccountManagerFuture<Account[]> future =
1018         am.getAccountsByTypeAndFeatures(
1019             "google.com", new String[] {"FEATURE_1", "FEATURE_2"}, callback, new Handler());
1020 
1021     assertThat(future.isDone()).isTrue();
1022     assertThat(future.getResult()).asList().containsExactly(accountWithCorrectTypeAndFeatures);
1023 
1024     shadowMainLooper().idle();
1025     assertThat(callback.hasBeenCalled()).isTrue();
1026   }
1027 
1028   @Test
getAccountsByTypeAndFeatures_returnsAllAccountsForNullFeature()1029   public void getAccountsByTypeAndFeatures_returnsAllAccountsForNullFeature() throws Exception {
1030 
1031     Account accountWithCorrectTypeAndFeatures = new Account("account_1", "google.com");
1032     shadowOf(am).addAccount(accountWithCorrectTypeAndFeatures);
1033     shadowOf(am)
1034         .setFeatures(accountWithCorrectTypeAndFeatures, new String[] {"FEATURE_1", "FEATURE_2"});
1035 
1036     Account accountWithCorrectTypeButNotFeatures = new Account("account_2", "google.com");
1037     shadowOf(am).addAccount(accountWithCorrectTypeButNotFeatures);
1038     shadowOf(am).setFeatures(accountWithCorrectTypeButNotFeatures, new String[] {"FEATURE_1"});
1039 
1040     Account accountWithCorrectFeaturesButNotType = new Account("account_3", "facebook.com");
1041     shadowOf(am).addAccount(accountWithCorrectFeaturesButNotType);
1042     shadowOf(am)
1043         .setFeatures(accountWithCorrectFeaturesButNotType, new String[] {"FEATURE_1", "FEATURE_2"});
1044 
1045     TestAccountManagerCallback<Account[]> callback = new TestAccountManagerCallback<>();
1046 
1047     AccountManagerFuture<Account[]> future =
1048         am.getAccountsByTypeAndFeatures("google.com", null, callback, new Handler());
1049 
1050     assertThat(future.isDone()).isTrue();
1051     assertThat(future.getResult())
1052         .asList()
1053         .containsExactly(accountWithCorrectTypeAndFeatures, accountWithCorrectTypeButNotFeatures);
1054 
1055     shadowMainLooper().idle();
1056     assertThat(callback.hasBeenCalled()).isTrue();
1057   }
1058 
1059   @Test
getAccountsByTypeForPackage()1060   public void getAccountsByTypeForPackage() {
1061     Account[] accountsByTypeForPackage = am.getAccountsByTypeForPackage(null, "org.somepackage");
1062 
1063     assertThat(accountsByTypeForPackage).isEmpty();
1064 
1065     Account accountVisibleToPackage = new Account("user@gmail.com", "gmail.com");
1066     shadowOf(am).addAccount(accountVisibleToPackage, "org.somepackage");
1067 
1068     accountsByTypeForPackage = am.getAccountsByTypeForPackage("other_type", "org.somepackage");
1069     assertThat(accountsByTypeForPackage).isEmpty();
1070 
1071     accountsByTypeForPackage = am.getAccountsByTypeForPackage("gmail.com", "org.somepackage");
1072     assertThat(accountsByTypeForPackage).asList().containsExactly(accountVisibleToPackage);
1073 
1074     accountsByTypeForPackage = am.getAccountsByTypeForPackage(null, "org.somepackage");
1075     assertThat(accountsByTypeForPackage).asList().containsExactly(accountVisibleToPackage);
1076   }
1077 
1078   @Test
1079   @Config(minSdk = LOLLIPOP_MR1)
removeAccountExplicitly()1080   public void removeAccountExplicitly() {
1081     assertThat(
1082             am.removeAccountExplicitly(new Account("non_existent_account@gmail.com", "gmail.com")))
1083         .isFalse();
1084     assertThat(am.removeAccountExplicitly(null)).isFalse();
1085 
1086     Account account = new Account("name@gmail.com", "gmail.com");
1087     shadowOf(am).addAccount(account);
1088 
1089     assertThat(am.removeAccountExplicitly(account)).isTrue();
1090   }
1091 
1092   @Test
removeAllAccounts()1093   public void removeAllAccounts() throws Exception {
1094 
1095     Account account = new Account("name@gmail.com", "gmail.com");
1096     shadowOf(am).addAccount(account);
1097 
1098     assertThat(am.getAccounts()).isNotEmpty();
1099 
1100     shadowOf(am).removeAllAccounts();
1101 
1102     assertThat(am.getAccounts()).isEmpty();
1103   }
1104 
1105   @Test
testSetAuthenticationErrorOnNextResponse()1106   public void testSetAuthenticationErrorOnNextResponse()
1107       throws AuthenticatorException, IOException, OperationCanceledException {
1108 
1109     shadowOf(am).setAuthenticationErrorOnNextResponse(true);
1110 
1111     try {
1112       am.getAccountsByTypeAndFeatures(null, null, null, null).getResult();
1113       fail("should have thrown");
1114     } catch (AuthenticatorException expected) {
1115       // Expected
1116     }
1117 
1118     am.getAccountsByTypeAndFeatures(null, null, null, null).getResult();
1119   }
1120 
1121   private static class TestAccountManagerCallback<T> implements AccountManagerCallback<T> {
1122     private AccountManagerFuture<T> accountManagerFuture;
1123 
1124     @Override
run(AccountManagerFuture<T> accountManagerFuture)1125     public void run(AccountManagerFuture<T> accountManagerFuture) {
1126       this.accountManagerFuture = accountManagerFuture;
1127     }
1128 
hasBeenCalled()1129     boolean hasBeenCalled() {
1130       return accountManagerFuture != null;
1131     }
1132 
getResult()1133     T getResult() throws Exception {
1134       return accountManagerFuture.getResult();
1135     }
1136   }
1137 
1138   @Test
1139   @Config(minSdk = O)
accountManager_activityContextEnabled_differentInstancesRetrieveAccounts()1140   public void accountManager_activityContextEnabled_differentInstancesRetrieveAccounts() {
1141     String originalProperty = System.getProperty("robolectric.createActivityContexts", "");
1142     System.setProperty("robolectric.createActivityContexts", "true");
1143     try (ActivityController<Activity> controller =
1144         Robolectric.buildActivity(Activity.class).setup()) {
1145       AccountManager applicationAccountManager = appContext.getSystemService(AccountManager.class);
1146       Activity activity = controller.get();
1147       AccountManager activityAccountManager = activity.getSystemService(AccountManager.class);
1148 
1149       assertThat(applicationAccountManager).isNotSameInstanceAs(activityAccountManager);
1150 
1151       Account[] applicationAccounts =
1152           applicationAccountManager.getAccountsByType("com.example.account_type");
1153       Account[] activityAccounts =
1154           activityAccountManager.getAccountsByType("com.example.account_type");
1155 
1156       assertThat(activityAccounts).isEqualTo(applicationAccounts);
1157     } finally {
1158       System.setProperty("robolectric.createActivityContexts", originalProperty);
1159     }
1160   }
1161 }
1162