OAuth2TokenServiceIntegrationTest.java revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.chrome.browser.signin;
6
7import android.accounts.Account;
8import android.test.UiThreadTest;
9import android.test.suitebuilder.annotation.MediumTest;
10
11import org.chromium.base.ThreadUtils;
12import org.chromium.base.test.util.AdvancedMockContext;
13import org.chromium.base.test.util.Feature;
14import org.chromium.chrome.browser.profiles.Profile;
15import org.chromium.chrome.shell.ChromeShellTestBase;
16import org.chromium.sync.signin.AccountManagerHelper;
17import org.chromium.sync.signin.ChromeSigninController;
18import org.chromium.sync.test.util.AccountHolder;
19import org.chromium.sync.test.util.MockAccountManager;
20
21import java.util.concurrent.atomic.AtomicReference;
22
23/**
24 * Integration test for the OAuth2TokenService.
25 *
26 * These tests initialize the native part of the service.
27 */
28public class OAuth2TokenServiceIntegrationTest extends ChromeShellTestBase {
29
30    private static final Account TEST_ACCOUNT1 =
31            AccountManagerHelper.createAccountFromName("foo@gmail.com");
32    private static final Account TEST_ACCOUNT2 =
33            AccountManagerHelper.createAccountFromName("bar@gmail.com");
34    private static final AccountHolder TEST_ACCOUNT_HOLDER_1 =
35            AccountHolder.create().account(TEST_ACCOUNT1).build();
36    private static final AccountHolder TEST_ACCOUNT_HOLDER_2 =
37            AccountHolder.create().account(TEST_ACCOUNT2).build();
38
39    private AdvancedMockContext mContext;
40    private OAuth2TokenService mOAuth2TokenService;
41    private MockAccountManager mAccountManager;
42    private TestObserver mObserver;
43    private ChromeSigninController mChromeSigninController;
44
45    @Override
46    protected void setUp() throws Exception {
47        super.setUp();
48        clearAppData();
49        startChromeBrowserProcessSync(getInstrumentation().getTargetContext());
50
51        // Set up AccountManager.
52        mContext = new AdvancedMockContext(getInstrumentation().getTargetContext());
53        mAccountManager = new MockAccountManager(mContext, getInstrumentation().getContext());
54        AccountManagerHelper.overrideAccountManagerHelperForTests(mContext, mAccountManager);
55        mChromeSigninController = ChromeSigninController.get(mContext);
56
57        // Get a reference to the service.
58        mOAuth2TokenService = getOAuth2TokenServiceOnUiThread();
59
60        // Set up observer.
61        mObserver = new TestObserver();
62        addObserver(mObserver);
63    }
64
65    /**
66     * The {@link OAuth2TokenService} and the {@link Profile} can only be accessed from the UI
67     * thread, so this helper method is a convenience method to retrieve it.
68     *
69     * @return the OAuth2TokenService.
70     */
71    private static OAuth2TokenService getOAuth2TokenServiceOnUiThread() {
72        final AtomicReference<OAuth2TokenService> service =
73                new AtomicReference<OAuth2TokenService>();
74        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
75            @Override
76            public void run() {
77                service.set(OAuth2TokenService.getForProfile(Profile.getLastUsedProfile()));
78            }
79        });
80        return service.get();
81    }
82
83    private void addObserver(final TestObserver observer) {
84        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
85            @Override
86            public void run() {
87                mOAuth2TokenService.addObserver(observer);
88            }
89        });
90    }
91
92    @MediumTest
93    @UiThreadTest
94    @Feature({"Sync"})
95    public void testFireRefreshTokenAvailableNotifiesJavaObservers() {
96        // Adding an observer should not lead to a callback.
97        assertEquals(0, mObserver.getAvailableCallCount());
98
99        // An observer should be called with the correct account.
100        mOAuth2TokenService.fireRefreshTokenAvailable(TEST_ACCOUNT1);
101        assertEquals(1, mObserver.getAvailableCallCount());
102        assertEquals(TEST_ACCOUNT1, mObserver.getLastAccount());
103
104        // When mOAuth2TokenService, an observer should not be called.
105        mOAuth2TokenService.removeObserver(mObserver);
106        mOAuth2TokenService.fireRefreshTokenAvailable(TEST_ACCOUNT1);
107        assertEquals(1, mObserver.getAvailableCallCount());
108
109        // No other observer interface method should ever have been called.
110        assertEquals(0, mObserver.getRevokedCallCount());
111        assertEquals(0, mObserver.getLoadedCallCount());
112    }
113
114    @MediumTest
115    @UiThreadTest
116    @Feature({"Sync"})
117    public void testFireRefreshTokenRevokedNotifiesJavaObservers() {
118        // Adding an observer should not lead to a callback.
119        assertEquals(0, mObserver.getRevokedCallCount());
120
121        // An observer should be called with the correct account.
122        mOAuth2TokenService.fireRefreshTokenRevoked(TEST_ACCOUNT1);
123        assertEquals(1, mObserver.getRevokedCallCount());
124        assertEquals(TEST_ACCOUNT1, mObserver.getLastAccount());
125
126        // When removed, an observer should not be called.
127        mOAuth2TokenService.removeObserver(mObserver);
128        mOAuth2TokenService.fireRefreshTokenRevoked(TEST_ACCOUNT1);
129        assertEquals(1, mObserver.getRevokedCallCount());
130
131        // No other observer interface method should ever have been called.
132        assertEquals(0, mObserver.getAvailableCallCount());
133        assertEquals(0, mObserver.getLoadedCallCount());
134    }
135
136    @MediumTest
137    @UiThreadTest
138    @Feature({"Sync"})
139    public void testFireRefreshTokensLoadedNotifiesJavaObservers() {
140        // Adding an observer should not lead to a callback.
141        assertEquals(0, mObserver.getLoadedCallCount());
142
143        // An observer should be called with the correct account.
144        mOAuth2TokenService.fireRefreshTokensLoaded();
145        assertEquals(1, mObserver.getLoadedCallCount());
146
147        // When removed, an observer should not be called.
148        mOAuth2TokenService.removeObserver(mObserver);
149        mOAuth2TokenService.fireRefreshTokensLoaded();
150        assertEquals(1, mObserver.getLoadedCallCount());
151
152        // No other observer interface method should ever have been called.
153        assertEquals(0, mObserver.getAvailableCallCount());
154        assertEquals(0, mObserver.getRevokedCallCount());
155    }
156
157    @MediumTest
158    @UiThreadTest
159    public void testValidateAccountsNoAccountsRegisteredAndNoSignedInUser() {
160        // Run test.
161        mOAuth2TokenService.validateAccounts(mContext);
162
163        // Ensure no calls have been made to the observer.
164        assertEquals(0, mObserver.getAvailableCallCount());
165        assertEquals(0, mObserver.getRevokedCallCount());
166        assertEquals(0, mObserver.getLoadedCallCount());
167    }
168
169    @MediumTest
170    @UiThreadTest
171    public void testValidateAccountsOneAccountsRegisteredAndNoSignedInUser() {
172        // Add account.
173        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
174
175        // Run test.
176        mOAuth2TokenService.validateAccounts(mContext);
177
178        // Ensure no calls have been made to the observer.
179        assertEquals(0, mObserver.getAvailableCallCount());
180        assertEquals(0, mObserver.getRevokedCallCount());
181        assertEquals(0, mObserver.getLoadedCallCount());
182    }
183
184    @MediumTest
185    @UiThreadTest
186    public void testValidateAccountsOneAccountsRegisteredSignedIn() {
187        // Add account.
188        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
189
190        // Mark user as signed in.
191        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
192
193        // Run test.
194        mOAuth2TokenService.validateAccounts(mContext);
195
196        // Ensure no calls have been made to the observer.
197        assertEquals(1, mObserver.getAvailableCallCount());
198        assertEquals(0, mObserver.getRevokedCallCount());
199        assertEquals(0, mObserver.getLoadedCallCount());
200    }
201
202    @MediumTest
203    @UiThreadTest
204    public void testValidateAccountsSingleAccountWithoutChanges() {
205        // Add account.
206        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
207
208        // Mark user as signed in.
209        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
210
211        // Run one validation.
212        mOAuth2TokenService.validateAccounts(mContext);
213        assertEquals(1, mObserver.getAvailableCallCount());
214        assertEquals(0, mObserver.getRevokedCallCount());
215        assertEquals(0, mObserver.getLoadedCallCount());
216
217        // Re-run validation.
218        mOAuth2TokenService.validateAccounts(mContext);
219        assertEquals(2, mObserver.getAvailableCallCount());
220        assertEquals(0, mObserver.getRevokedCallCount());
221        assertEquals(0, mObserver.getLoadedCallCount());
222    }
223
224    @MediumTest
225    @UiThreadTest
226    public void testValidateAccountsSingleAccountThenAddOne() {
227        // Add account.
228        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
229
230        // Mark user as signed in.
231        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
232
233        // Run one validation.
234        mOAuth2TokenService.validateAccounts(mContext);
235        assertEquals(1, mObserver.getAvailableCallCount());
236        assertEquals(0, mObserver.getRevokedCallCount());
237        assertEquals(0, mObserver.getLoadedCallCount());
238
239        // Add another account.
240        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
241
242        // Re-run validation.
243        mOAuth2TokenService.validateAccounts(mContext);
244        assertEquals(3, mObserver.getAvailableCallCount());
245        assertEquals(0, mObserver.getRevokedCallCount());
246        assertEquals(0, mObserver.getLoadedCallCount());
247    }
248
249    @MediumTest
250    @UiThreadTest
251    public void testValidateAccountsTwoAccountsThenRemoveOne() {
252        // Add accounts.
253        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
254        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
255
256        // Mark user as signed in.
257        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
258
259        // Run one validation.
260        mOAuth2TokenService.validateAccounts(mContext);
261        assertEquals(2, mObserver.getAvailableCallCount());
262
263        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
264        mOAuth2TokenService.validateAccounts(mContext);
265
266        assertEquals(3, mObserver.getAvailableCallCount());
267        assertEquals(1, mObserver.getRevokedCallCount());
268        assertEquals(0, mObserver.getLoadedCallCount());
269    }
270
271    @MediumTest
272    @UiThreadTest
273    public void testValidateAccountsTwoAccountsThenRemoveAll() {
274        // Add accounts.
275        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
276        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
277
278        // Mark user as signed in.
279        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
280
281        mOAuth2TokenService.validateAccounts(mContext);
282        assertEquals(2, mObserver.getAvailableCallCount());
283
284        // Remove all.
285        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
286        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
287
288        // Re-validate and run checks.
289        mOAuth2TokenService.validateAccounts(mContext);
290        assertEquals(2, mObserver.getRevokedCallCount());
291        assertEquals(0, mObserver.getLoadedCallCount());
292    }
293
294    @MediumTest
295    @UiThreadTest
296    public void testValidateAccountsTwoAccountsThenRemoveAllSignOut() {
297        // Add accounts.
298        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
299        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
300
301        // Mark user as signed in.
302        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
303
304        mOAuth2TokenService.validateAccounts(mContext);
305        assertEquals(2, mObserver.getAvailableCallCount());
306
307        // Remove all.
308        mChromeSigninController.clearSignedInUser();
309        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
310        mAccountManager.removeAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
311
312        // Re-validate and run checks.
313        mOAuth2TokenService.validateAccounts(mContext);
314        assertEquals(2, mObserver.getRevokedCallCount());
315        assertEquals(0, mObserver.getLoadedCallCount());
316    }
317
318    @MediumTest
319    @UiThreadTest
320    public void testValidateAccountsTwoAccountsRegisteredAndOneSignedIn() {
321        // Add accounts.
322        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_1);
323        mAccountManager.addAccountHolderExplicitly(TEST_ACCOUNT_HOLDER_2);
324
325        // Mark user as signed in.
326        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
327
328        // Run test.
329        mOAuth2TokenService.validateAccounts(mContext);
330
331        // All accounts will be notified. It is up to the observer
332        // to design if any action is needed.
333        assertEquals(2, mObserver.getAvailableCallCount());
334        assertEquals(0, mObserver.getRevokedCallCount());
335        assertEquals(0, mObserver.getLoadedCallCount());
336    }
337
338    @MediumTest
339    @UiThreadTest
340    public void testValidateAccountsNoAccountsRegisteredButSignedIn() {
341        // Mark user as signed in without setting up the account.
342        mChromeSigninController.setSignedInAccountName(TEST_ACCOUNT1.name);
343
344        // Run test.
345        mOAuth2TokenService.validateAccounts(mContext);
346
347        // Ensure no calls have been made to the observer.
348        assertEquals(0, mObserver.getAvailableCallCount());
349        assertEquals(1, mObserver.getRevokedCallCount());
350        assertEquals(0, mObserver.getLoadedCallCount());
351    }
352
353    private static class TestObserver implements OAuth2TokenService.OAuth2TokenServiceObserver {
354        private int mAvailableCallCount;
355        private int mRevokedCallCount;
356        private int mLoadedCallCount;
357        private Account mLastAccount;
358
359        @Override
360        public void onRefreshTokenAvailable(Account account) {
361            mAvailableCallCount++;
362            mLastAccount = account;
363        }
364
365        @Override
366        public void onRefreshTokenRevoked(Account account) {
367            mRevokedCallCount++;
368            mLastAccount = account;
369        }
370
371        @Override
372        public void onRefreshTokensLoaded() {
373            mLoadedCallCount++;
374        }
375
376        public int getAvailableCallCount() {
377            return mAvailableCallCount;
378        }
379
380        public int getRevokedCallCount() {
381            return mRevokedCallCount;
382        }
383
384        public int getLoadedCallCount() {
385            return mLoadedCallCount;
386        }
387
388        public Account getLastAccount() {
389            return mLastAccount;
390        }
391    }
392}
393