1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settings.accounts; 17 18 import android.accounts.Account; 19 import android.accounts.AccountManager; 20 import android.accounts.AuthenticatorDescription; 21 import android.content.Context; 22 import android.content.pm.UserInfo; 23 import android.os.UserHandle; 24 import android.os.UserManager; 25 import android.support.v7.preference.Preference; 26 import android.support.v7.preference.PreferenceGroup; 27 import android.support.v7.preference.PreferenceManager; 28 import android.support.v7.preference.PreferenceScreen; 29 import android.text.TextUtils; 30 31 import com.android.settings.AccessiblePreferenceCategory; 32 import com.android.settings.R; 33 import com.android.settings.SettingsPreferenceFragment; 34 import com.android.settings.SettingsRobolectricTestRunner; 35 import com.android.settings.TestConfig; 36 import com.android.settings.search.SearchIndexableRaw; 37 import com.android.settings.testutils.shadow.ShadowAccountManager; 38 import com.android.settings.testutils.shadow.ShadowContentResolver; 39 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.mockito.ArgumentMatcher; 44 import org.mockito.Mock; 45 import org.mockito.MockitoAnnotations; 46 import org.robolectric.annotation.Config; 47 import org.robolectric.shadows.ShadowApplication; 48 49 import java.util.ArrayList; 50 import java.util.List; 51 52 import static com.google.common.truth.Truth.assertThat; 53 import static org.mockito.Answers.RETURNS_DEEP_STUBS; 54 import static org.mockito.Matchers.any; 55 import static org.mockito.Matchers.anyInt; 56 import static org.mockito.Matchers.argThat; 57 import static org.mockito.Matchers.eq; 58 import static org.mockito.Mockito.mock; 59 import static org.mockito.Mockito.never; 60 import static org.mockito.Mockito.reset; 61 import static org.mockito.Mockito.times; 62 import static org.mockito.Mockito.verify; 63 import static org.mockito.Mockito.when; 64 65 @RunWith(SettingsRobolectricTestRunner.class) 66 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, 67 shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) 68 public class AccountPreferenceControllerTest { 69 70 @Mock(answer = RETURNS_DEEP_STUBS) 71 private PreferenceScreen mScreen; 72 @Mock(answer = RETURNS_DEEP_STUBS) 73 private UserManager mUserManager; 74 @Mock(answer = RETURNS_DEEP_STUBS) 75 private SettingsPreferenceFragment mFragment; 76 @Mock(answer = RETURNS_DEEP_STUBS) 77 private AccountManager mAccountManager; 78 @Mock(answer = RETURNS_DEEP_STUBS) 79 private AccountRestrictionHelper mAccountHelper; 80 81 private Context mContext; 82 private AccountPreferenceController mController; 83 84 @Before setUp()85 public void setUp() { 86 MockitoAnnotations.initMocks(this); 87 ShadowApplication shadowContext = ShadowApplication.getInstance(); 88 shadowContext.setSystemService(Context.USER_SERVICE, mUserManager); 89 shadowContext.setSystemService(Context.ACCOUNT_SERVICE, mAccountManager); 90 mContext = shadowContext.getApplicationContext(); 91 92 when(mFragment.getPreferenceScreen()).thenReturn(mScreen); 93 when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); 94 when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn( 95 new AuthenticatorDescription[0]); 96 when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]); 97 mController = new AccountPreferenceController(mContext, mFragment, null, mAccountHelper); 98 } 99 100 @Test onResume_managedProfile_shouldNotAddAccountCategory()101 public void onResume_managedProfile_shouldNotAddAccountCategory() { 102 when(mUserManager.isManagedProfile()).thenReturn(true); 103 mController.onResume(); 104 105 verify(mScreen, never()).addPreference(any(Preference.class)); 106 } 107 108 @Test 109 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_linkedUser_shouldAddOneAccountCategory()110 public void onResume_linkedUser_shouldAddOneAccountCategory() { 111 final UserInfo info = new UserInfo(1, "user 1", 0); 112 when(mUserManager.isManagedProfile()).thenReturn(false); 113 when(mUserManager.isLinkedUser()).thenReturn(true); 114 when(mUserManager.getUserInfo(anyInt())).thenReturn(info); 115 116 mController.onResume(); 117 118 verify(mScreen, times(1)).addPreference(any(PreferenceGroup.class)); 119 } 120 121 @Test 122 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_oneProfile_shouldAddOneAccountCategory()123 public void onResume_oneProfile_shouldAddOneAccountCategory() { 124 final List<UserInfo> infos = new ArrayList<>(); 125 infos.add(new UserInfo(1, "user 1", 0)); 126 when(mUserManager.isManagedProfile()).thenReturn(false); 127 when(mUserManager.isLinkedUser()).thenReturn(false); 128 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 129 130 mController.onResume(); 131 132 verify(mScreen, times(1)).addPreference(any(PreferenceGroup.class)); 133 } 134 135 @Test 136 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_twoProfiles_shouldAddTwoAccountCategory()137 public void onResume_twoProfiles_shouldAddTwoAccountCategory() { 138 final List<UserInfo> infos = new ArrayList<>(); 139 infos.add(new UserInfo(1, "user 1", 0)); 140 infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); 141 when(mUserManager.isManagedProfile()).thenReturn(false); 142 when(mUserManager.isLinkedUser()).thenReturn(false); 143 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 144 145 mController.onResume(); 146 147 verify(mScreen, times(2)).addPreference(any(PreferenceGroup.class)); 148 } 149 150 @Test 151 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_noProfileChange_shouldNotAddOrRemoveAccountCategory()152 public void onResume_noProfileChange_shouldNotAddOrRemoveAccountCategory() { 153 final List<UserInfo> infos = new ArrayList<>(); 154 infos.add(new UserInfo(1, "user 1", 0)); 155 infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); 156 when(mUserManager.isManagedProfile()).thenReturn(false); 157 when(mUserManager.isLinkedUser()).thenReturn(false); 158 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 159 // First time resume will build the UI 160 mController.onResume(); 161 reset(mScreen); 162 163 mController.onResume(); 164 verify(mScreen, never()).addPreference(any(PreferenceGroup.class)); 165 verify(mScreen, never()).removePreference(any(PreferenceGroup.class)); 166 } 167 168 @Test 169 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_oneNewProfile_shouldAddOneAccountCategory()170 public void onResume_oneNewProfile_shouldAddOneAccountCategory() { 171 final List<UserInfo> infos = new ArrayList<>(); 172 infos.add(new UserInfo(1, "user 1", 0)); 173 when(mUserManager.isManagedProfile()).thenReturn(false); 174 when(mUserManager.isLinkedUser()).thenReturn(false); 175 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 176 // First time resume will build the UI 177 mController.onResume(); 178 // add a new profile 179 infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); 180 reset(mScreen); 181 182 mController.onResume(); 183 verify(mScreen, times(1)).addPreference(any(PreferenceGroup.class)); 184 } 185 186 @Test 187 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_oneProfileRemoved_shouldRemoveOneAccountCategory()188 public void onResume_oneProfileRemoved_shouldRemoveOneAccountCategory() { 189 final List<UserInfo> infos = new ArrayList<>(); 190 infos.add(new UserInfo(1, "user 1", 0)); 191 infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); 192 when(mUserManager.isManagedProfile()).thenReturn(false); 193 when(mUserManager.isLinkedUser()).thenReturn(false); 194 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 195 // First time resume will build the UI 196 mController.onResume(); 197 // remove a profile 198 infos.remove(1); 199 200 mController.onResume(); 201 verify(mScreen, times(1)).removePreference(any(PreferenceGroup.class)); 202 } 203 204 @Test 205 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_oneProfile_shouldSetAccountTitleWithUserName()206 public void onResume_oneProfile_shouldSetAccountTitleWithUserName() { 207 final List<UserInfo> infos = new ArrayList<>(); 208 infos.add(new UserInfo(1, "user 1", UserInfo.FLAG_MANAGED_PROFILE)); 209 when(mUserManager.isManagedProfile()).thenReturn(false); 210 when(mUserManager.isLinkedUser()).thenReturn(false); 211 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 212 AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); 213 when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( 214 preferenceGroup); 215 216 mController.onResume(); 217 218 verify(preferenceGroup).setTitle( 219 mContext.getString(R.string.account_for_section_header, "user 1")); 220 221 } 222 223 @Test 224 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_noPreferenceScreen_shouldNotCrash()225 public void onResume_noPreferenceScreen_shouldNotCrash() { 226 final List<UserInfo> infos = new ArrayList<>(); 227 infos.add(new UserInfo(1, "user 1", 0)); 228 when(mUserManager.isManagedProfile()).thenReturn(false); 229 when(mUserManager.isLinkedUser()).thenReturn(false); 230 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 231 232 AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); 233 when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( 234 preferenceGroup); 235 236 mController.onResume(); 237 238 // Should not crash 239 } 240 241 @Test 242 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_noPreferenceManager_shouldNotCrash()243 public void onResume_noPreferenceManager_shouldNotCrash() { 244 when(mFragment.getPreferenceManager()).thenReturn(null); 245 final List<UserInfo> infos = new ArrayList<>(); 246 infos.add(new UserInfo(1, "user 1", 0)); 247 when(mUserManager.isManagedProfile()).thenReturn(false); 248 when(mUserManager.isLinkedUser()).thenReturn(false); 249 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 250 mController.onResume(); 251 252 // Should not crash 253 } 254 255 @Test updateRawDataToIndex_ManagedProfile_shouldNotUpdate()256 public void updateRawDataToIndex_ManagedProfile_shouldNotUpdate() { 257 final List<SearchIndexableRaw> data = new ArrayList<>(); 258 when(mUserManager.isManagedProfile()).thenReturn(true); 259 260 mController.updateRawDataToIndex(data); 261 262 assertThat(data).isEmpty(); 263 } 264 265 @Test updateRawDataToIndex_DisabledUser_shouldNotUpdate()266 public void updateRawDataToIndex_DisabledUser_shouldNotUpdate() { 267 final List<SearchIndexableRaw> data = new ArrayList<>(); 268 final List<UserInfo> infos = new ArrayList<>(); 269 infos.add(new UserInfo(1, "user 1", UserInfo.FLAG_DISABLED)); 270 when(mUserManager.isManagedProfile()).thenReturn(false); 271 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 272 mController.updateRawDataToIndex(data); 273 274 assertThat(data).isEmpty(); 275 } 276 277 @Test updateRawDataToIndex_EnabledUser_shouldAddOne()278 public void updateRawDataToIndex_EnabledUser_shouldAddOne() { 279 final List<SearchIndexableRaw> data = new ArrayList<>(); 280 final List<UserInfo> infos = new ArrayList<>(); 281 infos.add(new UserInfo(1, "user 1", 0)); 282 when(mUserManager.isManagedProfile()).thenReturn(false); 283 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 284 285 mController.updateRawDataToIndex(data); 286 287 assertThat(data.size()).isEqualTo(1); 288 } 289 290 @Test updateRawDataToIndex_ManagedUser_shouldAddThree()291 public void updateRawDataToIndex_ManagedUser_shouldAddThree() { 292 final List<SearchIndexableRaw> data = new ArrayList<>(); 293 final List<UserInfo> infos = new ArrayList<>(); 294 infos.add(new UserInfo(1, "user 1", UserInfo.FLAG_MANAGED_PROFILE)); 295 when(mUserManager.isManagedProfile()).thenReturn(false); 296 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 297 298 mController.updateRawDataToIndex(data); 299 300 assertThat(data.size()).isEqualTo(3); 301 } 302 303 @Test updateRawDataToIndex_DisallowRemove_shouldAddTwo()304 public void updateRawDataToIndex_DisallowRemove_shouldAddTwo() { 305 final List<SearchIndexableRaw> data = new ArrayList<>(); 306 final List<UserInfo> infos = new ArrayList<>(); 307 infos.add(new UserInfo(1, "user 1", UserInfo.FLAG_MANAGED_PROFILE)); 308 when(mUserManager.isManagedProfile()).thenReturn(false); 309 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 310 when(mAccountHelper.hasBaseUserRestriction( 311 eq(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE), anyInt())) 312 .thenReturn(true); 313 314 mController.updateRawDataToIndex(data); 315 316 assertThat(data.size()).isEqualTo(2); 317 } 318 319 @Test updateRawDataToIndex_DisallowModify_shouldAddTwo()320 public void updateRawDataToIndex_DisallowModify_shouldAddTwo() { 321 final List<SearchIndexableRaw> data = new ArrayList<>(); 322 final List<UserInfo> infos = new ArrayList<>(); 323 infos.add(new UserInfo(1, "user 1", UserInfo.FLAG_MANAGED_PROFILE)); 324 when(mUserManager.isManagedProfile()).thenReturn(false); 325 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 326 when(mAccountHelper.hasBaseUserRestriction( 327 eq(UserManager.DISALLOW_MODIFY_ACCOUNTS), anyInt())).thenReturn(true); 328 329 mController.updateRawDataToIndex(data); 330 331 assertThat(data.size()).isEqualTo(2); 332 } 333 334 @Test 335 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_twoAccountsOfSameType_shouldAddThreePreferences()336 public void onResume_twoAccountsOfSameType_shouldAddThreePreferences() { 337 final List<UserInfo> infos = new ArrayList<>(); 338 infos.add(new UserInfo(1, "user 1", 0)); 339 when(mUserManager.isManagedProfile()).thenReturn(false); 340 when(mUserManager.isLinkedUser()).thenReturn(false); 341 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 342 Account[] accounts = {new Account("Account1", "com.acct1")}; 343 when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); 344 345 Account[] accountType1 = new Account[2]; 346 accountType1[0] = new Account("Account11", "com.acct1"); 347 accountType1[1] = new Account("Account12", "com.acct1"); 348 when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) 349 .thenReturn(accountType1); 350 351 AuthenticatorDescription[] authDescs = { 352 new AuthenticatorDescription("com.acct1", "com.android.settings", 353 R.string.account_settings_title, 0, 0, 0, false) 354 }; 355 when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); 356 357 AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); 358 when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 359 when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( 360 preferenceGroup); 361 362 mController.onResume(); 363 364 // should add 2 individual account and the Add account preference 365 verify(preferenceGroup, times(3)).addPreference(any(Preference.class)); 366 } 367 368 @Test 369 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_twoAccountsOfSameName_shouldAddFivePreferences()370 public void onResume_twoAccountsOfSameName_shouldAddFivePreferences() { 371 final List<UserInfo> infos = new ArrayList<>(); 372 infos.add(new UserInfo(1, "user 1", 0)); 373 when(mUserManager.isManagedProfile()).thenReturn(false); 374 when(mUserManager.isLinkedUser()).thenReturn(false); 375 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 376 377 final Account[] accountType1 = new Account[2]; 378 accountType1[0] = new Account("Account1", "com.acct1"); 379 accountType1[1] = new Account("Account2", "com.acct1"); 380 final Account[] accountType2 = new Account[2]; 381 accountType2[0] = new Account("Account1", "com.acct2"); 382 accountType2[1] = new Account("Account2", "com.acct2"); 383 final Account[] allAccounts = new Account[4]; 384 allAccounts[0] = accountType1[0]; 385 allAccounts[1] = accountType1[1]; 386 allAccounts[2] = accountType2[0]; 387 allAccounts[3] = accountType2[1]; 388 final AuthenticatorDescription[] authDescs = { 389 new AuthenticatorDescription("com.acct1", "com.android.settings", 390 R.string.account_settings_title, 0, 0, 0, false), 391 new AuthenticatorDescription("com.acct2", "com.android.settings", 392 R.string.account_settings_title, 0, 0, 0, false) 393 }; 394 395 when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(allAccounts); 396 when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) 397 .thenReturn(accountType1); 398 when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct2"), any(UserHandle.class))) 399 .thenReturn(accountType2); 400 when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); 401 402 AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); 403 when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 404 when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( 405 preferenceGroup); 406 407 mController.onResume(); 408 409 // should add 4 individual account and the Add account preference 410 verify(preferenceGroup, times(5)).addPreference(any(Preference.class)); 411 } 412 413 @Test 414 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_noAccountChange_shouldNotAddAccountPreference()415 public void onResume_noAccountChange_shouldNotAddAccountPreference() { 416 final List<UserInfo> infos = new ArrayList<>(); 417 infos.add(new UserInfo(1, "user 1", 0)); 418 when(mUserManager.isManagedProfile()).thenReturn(false); 419 when(mUserManager.isLinkedUser()).thenReturn(false); 420 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 421 Account[] accounts = {new Account("Acct1", "com.acct1")}; 422 when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); 423 424 Account[] accountType1 = new Account[2]; 425 accountType1[0] = new Account("Acct11", "com.acct1"); 426 accountType1[1] = new Account("Acct12", "com.acct1"); 427 when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) 428 .thenReturn(accountType1); 429 430 AuthenticatorDescription[] authDescs = { 431 new AuthenticatorDescription("com.acct1", "com.android.settings", 432 R.string.account_settings_title, 0, 0, 0, false) 433 }; 434 when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); 435 436 AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); 437 when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 438 when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( 439 preferenceGroup); 440 mController.onResume(); 441 442 mController.onResume(); 443 444 // each account should be added only once 445 verify(preferenceGroup).addPreference(argThat(new PreferenceMatcher("Acct11"))); 446 verify(preferenceGroup).addPreference(argThat(new PreferenceMatcher("Acct12"))); 447 } 448 449 @Test onResume_oneNewAccount_shouldAddOneAccountPreference()450 public void onResume_oneNewAccount_shouldAddOneAccountPreference() { 451 final List<UserInfo> infos = new ArrayList<>(); 452 infos.add(new UserInfo(1, "user 1", 0)); 453 when(mUserManager.isManagedProfile()).thenReturn(false); 454 when(mUserManager.isLinkedUser()).thenReturn(false); 455 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 456 Account[] accounts = {new Account("Acct1", "com.acct1")}; 457 when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); 458 459 Account[] accountType1 = new Account[2]; 460 accountType1[0] = new Account("Acct11", "com.acct1"); 461 accountType1[1] = new Account("Acct12", "com.acct1"); 462 when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) 463 .thenReturn(accountType1); 464 465 AuthenticatorDescription[] authDescs = { 466 new AuthenticatorDescription("com.acct1", "com.android.settings", 467 R.string.account_settings_title, 0, 0, 0, false) 468 }; 469 when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); 470 471 AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); 472 when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 473 when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( 474 preferenceGroup); 475 476 mController.onResume(); 477 478 // add a new account 479 accountType1 = new Account[3]; 480 accountType1[0] = new Account("Acct11", "com.acct1"); 481 accountType1[1] = new Account("Acct12", "com.acct1"); 482 accountType1[2] = new Account("Acct13", "com.acct1"); 483 when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) 484 .thenReturn(accountType1); 485 486 mController.onResume(); 487 488 // each account should be added only once 489 verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct11"))); 490 verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct12"))); 491 verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct13"))); 492 } 493 494 @Test 495 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_oneNewAccountType_shouldAddOneAccountPreference()496 public void onResume_oneNewAccountType_shouldAddOneAccountPreference() { 497 final List<UserInfo> infos = new ArrayList<>(); 498 infos.add(new UserInfo(1, "user 1", 0)); 499 infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE)); 500 when(mUserManager.isManagedProfile()).thenReturn(false); 501 when(mUserManager.isLinkedUser()).thenReturn(false); 502 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 503 504 AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); 505 when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 506 when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( 507 preferenceGroup); 508 509 // First time resume will build the UI with no account 510 mController.onResume(); 511 512 // Add new account 513 Account[] accounts = {new Account("Acct1", "com.acct1")}; 514 when(mAccountManager.getAccountsAsUser(2)).thenReturn(accounts); 515 when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) 516 .thenReturn(accounts); 517 518 AuthenticatorDescription[] authDescs = { 519 new AuthenticatorDescription("com.acct1", "com.android.settings", 520 R.string.account_settings_title, 0, 0, 0, false) 521 }; 522 when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); 523 524 // Resume should show the newly added account 525 mController.onResume(); 526 527 verify(preferenceGroup).addPreference(argThat(new PreferenceMatcher("Acct1"))); 528 } 529 530 @Test 531 @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) onResume_oneAccountRemoved_shouldRemoveOneAccountPreference()532 public void onResume_oneAccountRemoved_shouldRemoveOneAccountPreference() { 533 final List<UserInfo> infos = new ArrayList<>(); 534 infos.add(new UserInfo(1, "user 1", 0)); 535 when(mUserManager.isManagedProfile()).thenReturn(false); 536 when(mUserManager.isLinkedUser()).thenReturn(false); 537 when(mUserManager.getProfiles(anyInt())).thenReturn(infos); 538 Account[] accounts = {new Account("Acct1", "com.acct1")}; 539 when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(accounts); 540 541 Account[] accountType1 = new Account[2]; 542 accountType1[0] = new Account("Acct11", "com.acct1"); 543 accountType1[1] = new Account("Acct12", "com.acct1"); 544 when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) 545 .thenReturn(accountType1); 546 547 AuthenticatorDescription[] authDescs = { 548 new AuthenticatorDescription("com.acct1", "com.android.settings", 549 R.string.account_settings_title, 0, 0, 0, false) 550 }; 551 when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs); 552 553 AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class); 554 when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); 555 when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn( 556 preferenceGroup); 557 558 mController.onResume(); 559 560 // remove an account 561 accountType1 = new Account[1]; 562 accountType1[0] = new Account("Acct11", "com.acct1"); 563 when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class))) 564 .thenReturn(accountType1); 565 566 mController.onResume(); 567 568 verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct11"))); 569 verify(preferenceGroup, times(1)).addPreference(argThat(new PreferenceMatcher("Acct12"))); 570 verify(preferenceGroup, times(1)).removePreference( 571 argThat(new PreferenceMatcher("Acct12"))); 572 } 573 574 private static class PreferenceMatcher extends ArgumentMatcher<Preference> { 575 576 private final String mExpectedTitle; 577 PreferenceMatcher(String title)578 public PreferenceMatcher(String title) { 579 mExpectedTitle = title; 580 } 581 582 @Override matches(Object arg)583 public boolean matches(Object arg) { 584 final Preference preference = (Preference) arg; 585 return TextUtils.equals(mExpectedTitle, preference.getTitle()); 586 } 587 } 588 589 } 590