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