Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(899)

Side by Side Diff: components/signin/core/browser/access_token_fetcher_unittest.cc

Issue 2582573002: Signin/OAuth: Create an AccessTokenFetcher helper class (Closed)
Patch Set: return AuthErrors Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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
5 #include "components/signin/core/browser/access_token_fetcher.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/memory/ptr_util.h"
11 #include "base/test/mock_callback.h"
12 #include "components/prefs/testing_pref_service.h"
13 #include "components/signin/core/browser/account_tracker_service.h"
14 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
15 #include "components/signin/core/browser/fake_signin_manager.h"
16 #include "components/signin/core/browser/test_signin_client.h"
17 #include "components/sync_preferences/testing_pref_service_syncable.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gmock_mutant.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using base::MockCallback;
23 using sync_preferences::TestingPrefServiceSyncable;
24 using testing::CallbackToFunctor;
25 using testing::InvokeWithoutArgs;
26 using testing::StrictMock;
27
28 #if defined(OS_CHROMEOS)
29 // ChromeOS doesn't have SigninManager.
30 using SigninManagerForTest = FakeSigninManagerBase;
31 #else
32 using SigninManagerForTest = FakeSigninManager;
33 #endif // OS_CHROMEOS
34
35 class AccessTokenFetcherTest : public testing::Test {
36 public:
37 using TestTokenCallback =
38 StrictMock<MockCallback<AccessTokenFetcher::TokenCallback>>;
39
40 AccessTokenFetcherTest() : signin_client_(&pref_service_) {
41 AccountTrackerService::RegisterPrefs(pref_service_.registry());
42 #if defined(OS_CHROMEOS)
43 SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
44 SigninManagerBase::RegisterPrefs(pref_service_.registry());
45 #else
46 SigninManager::RegisterProfilePrefs(pref_service_.registry());
47 SigninManager::RegisterPrefs(pref_service_.registry());
48 #endif // OS_CHROMEOS
49
50 account_tracker_ = base::MakeUnique<AccountTrackerService>();
51 account_tracker_->Initialize(&signin_client_);
52
53 #if defined(OS_CHROMEOS)
54 signin_manager_ = base::MakeUnique<FakeSigninManagerBase>(
55 &signin_client_, account_tracker_.get());
56 #else
57 signin_manager_ = base::MakeUnique<FakeSigninManager>(
58 &signin_client_, &token_service_, account_tracker_.get(),
59 /*cookie_manager_service=*/nullptr);
60 #endif // OS_CHROMEOS
61 }
62
63 ~AccessTokenFetcherTest() override {}
64
65 std::unique_ptr<AccessTokenFetcher> CreateFetcher(
66 AccessTokenFetcher::TokenCallback callback) {
67 std::set<std::string> scopes{"scope"};
68 return base::MakeUnique<AccessTokenFetcher>(
69 "test_consumer", signin_manager_.get(), &token_service_, scopes,
70 std::move(callback));
71 }
72
73 FakeProfileOAuth2TokenService* token_service() { return &token_service_; }
74 SigninManagerForTest* signin_manager() { return signin_manager_.get(); }
75
76 void SignIn(const std::string& account) {
77 #if defined(OS_CHROMEOS)
78 signin_manager_->SignIn(account);
79 #else
80 signin_manager_->SignIn(account, "user", "pass");
81 #endif // OS_CHROMEOS
82 }
83
84 private:
85 TestingPrefServiceSyncable pref_service_;
86 TestSigninClient signin_client_;
87 FakeProfileOAuth2TokenService token_service_;
88
89 std::unique_ptr<AccountTrackerService> account_tracker_;
90 std::unique_ptr<SigninManagerForTest> signin_manager_;
91 };
92
93 TEST_F(AccessTokenFetcherTest, ShouldReturnAccessToken) {
94 TestTokenCallback callback;
95
96 SignIn("account");
97 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
98
99 // Signed in and refresh token already exists, so this should result in a
100 // request for an access token.
101 auto fetcher = CreateFetcher(callback.Get());
102
103 // Once the access token request is fulfilled, we should get called back with
104 // the access token.
105 EXPECT_CALL(callback,
106 Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
107 token_service()->IssueAllTokensForAccount(
108 "account", "access token",
109 base::Time::Now() + base::TimeDelta::FromHours(1));
110 }
111
112 TEST_F(AccessTokenFetcherTest, ShouldNotReplyIfDestroyed) {
113 TestTokenCallback callback;
114
115 SignIn("account");
116 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
117
118 // Signed in and refresh token already exists, so this should result in a
119 // request for an access token.
120 auto fetcher = CreateFetcher(callback.Get());
121
122 // Destroy the fetcher before the access token request is fulfilled.
123 fetcher.reset();
124
125 // Now fulfilling the access token request should have no effect.
126 token_service()->IssueAllTokensForAccount(
127 "account", "access token",
128 base::Time::Now() + base::TimeDelta::FromHours(1));
129 }
130
131 TEST_F(AccessTokenFetcherTest, ShouldNotReturnWhenSignedOut) {
132 TestTokenCallback callback;
133
134 // Signed out -> the fetcher should wait for a sign-in which never happens
135 // in this test, so we shouldn't get called back.
136 auto fetcher = CreateFetcher(callback.Get());
137 }
138
139 // Tests related to waiting for sign-in don't apply on ChromeOS (it doesn't have
140 // that concept).
141 #if !defined(OS_CHROMEOS)
142
143 TEST_F(AccessTokenFetcherTest, ShouldWaitForSignIn) {
144 TestTokenCallback callback;
145
146 // Not signed in, so this should wait for a sign-in to complete.
147 auto fetcher = CreateFetcher(callback.Get());
148
149 SignIn("account");
150 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
151
152 // Once the access token request is fulfilled, we should get called back with
153 // the access token.
154 EXPECT_CALL(callback,
155 Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
156 token_service()->IssueAllTokensForAccount(
157 "account", "access token",
158 base::Time::Now() + base::TimeDelta::FromHours(1));
159 }
160
161 TEST_F(AccessTokenFetcherTest, ShouldWaitForSignInInProgress) {
162 TestTokenCallback callback;
163
164 signin_manager()->set_auth_in_progress("account");
165
166 // A sign-in is currently in progress, so this should wait for the sign-in to
167 // complete.
168 auto fetcher = CreateFetcher(callback.Get());
169
170 SignIn("account");
171 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
172
173 // Once the access token request is fulfilled, we should get called back with
174 // the access token.
175 EXPECT_CALL(callback,
176 Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
177 token_service()->IssueAllTokensForAccount(
178 "account", "access token",
179 base::Time::Now() + base::TimeDelta::FromHours(1));
180 }
181
182 TEST_F(AccessTokenFetcherTest, ShouldWaitForFailedSignIn) {
183 TestTokenCallback callback;
184
185 signin_manager()->set_auth_in_progress("account");
186
187 // A sign-in is currently in progress, so this should wait for the sign-in to
188 // complete.
189 auto fetcher = CreateFetcher(callback.Get());
190
191 // The fetcher should detect the failed sign-in and call us with an empty
192 // access token.
193 EXPECT_CALL(callback,
194 Run(GoogleServiceAuthError(
195 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS),
196 std::string()));
197
198 signin_manager()->FailSignin(
199 GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
msarda 2017/01/27 10:38:58 This test will fail, if you pass a different error
Marc Treib 2017/01/27 11:16:55 Good catch! Per your other comment, I fixed the ac
200 }
201
202 #endif // !OS_CHROMEOS
203
204 TEST_F(AccessTokenFetcherTest, ShouldWaitForRefreshToken) {
205 TestTokenCallback callback;
206
207 SignIn("account");
208
209 // Signed in, but there is no refresh token -> we should not get called back
210 // (yet).
211 auto fetcher = CreateFetcher(callback.Get());
212
213 // Getting a refresh token should result in a request for an access token.
214 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
215
216 // Once the access token request is fulfilled, we should get called back with
217 // the access token.
218 EXPECT_CALL(callback,
219 Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
220 token_service()->IssueAllTokensForAccount(
221 "account", "access token",
222 base::Time::Now() + base::TimeDelta::FromHours(1));
223 }
224
225 TEST_F(AccessTokenFetcherTest, ShouldIgnoreRefreshTokensForOtherAccounts) {
226 TestTokenCallback callback;
227
228 // Signed-in to "account", but there's only a refresh token for a different
229 // account.
230 SignIn("account");
231 token_service()->GetDelegate()->UpdateCredentials("account 2", "refresh");
232
233 // The fetcher should wait for the correct refresh token.
234 auto fetcher = CreateFetcher(callback.Get());
235
236 // A refresh token for yet another account shouldn't matter either.
237 token_service()->GetDelegate()->UpdateCredentials("account 3", "refresh");
238 }
239
240 TEST_F(AccessTokenFetcherTest, ShouldReturnWhenNoRefreshTokenAvailable) {
241 TestTokenCallback callback;
242
243 SignIn("account");
244
245 // Signed in, but there is no refresh token -> we should not get called back
246 // (yet).
247 auto fetcher = CreateFetcher(callback.Get());
248
249 // Getting a refresh token for some other account should have no effect.
250 token_service()->GetDelegate()->UpdateCredentials("different account",
251 "refresh token");
252
253 // When all refresh tokens have been loaded by the token service, but the one
254 // for our account wasn't among them, we should get called back with an empty
255 // access token.
256 EXPECT_CALL(callback,
257 Run(GoogleServiceAuthError(
258 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS),
259 std::string()));
260 token_service()->GetDelegate()->LoadCredentials("account doesn't matter");
261 }
262
263 TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequest) {
264 TestTokenCallback callback;
265
266 SignIn("account");
267 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
268
269 // Signed in and refresh token already exists, so this should result in a
270 // request for an access token.
271 auto fetcher = CreateFetcher(callback.Get());
272
273 // A canceled access token request should get retried once.
274 token_service()->IssueErrorForAllPendingRequestsForAccount(
275 "account",
276 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
277
278 // Once the access token request is fulfilled, we should get called back with
279 // the access token.
280 EXPECT_CALL(callback,
281 Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
282 token_service()->IssueAllTokensForAccount(
283 "account", "access token",
284 base::Time::Now() + base::TimeDelta::FromHours(1));
285 }
286
287 TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequestOnlyOnce) {
288 TestTokenCallback callback;
289
290 SignIn("account");
291 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
292
293 // Signed in and refresh token already exists, so this should result in a
294 // request for an access token.
295 auto fetcher = CreateFetcher(callback.Get());
296
297 // A canceled access token request should get retried once.
298 token_service()->IssueErrorForAllPendingRequestsForAccount(
299 "account",
300 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
301
302 // On the second failure, we should get called back with an empty access
303 // token.
304 EXPECT_CALL(
305 callback,
306 Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
307 std::string()));
308 token_service()->IssueErrorForAllPendingRequestsForAccount(
309 "account",
310 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
311 }
312
313 #if !defined(OS_CHROMEOS)
314
315 TEST_F(AccessTokenFetcherTest,
316 ShouldNotRetryCanceledAccessTokenRequestIfSignedOut) {
317 TestTokenCallback callback;
318
319 SignIn("account");
320 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
321
322 // Signed in and refresh token already exists, so this should result in a
323 // request for an access token.
324 auto fetcher = CreateFetcher(callback.Get());
325
326 // Simulate the user signing out while the access token request is pending.
327 // In this case, the pending request gets canceled, and the fetcher should
328 // *not* retry.
329 signin_manager()->ForceSignOut();
330 EXPECT_CALL(
331 callback,
332 Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
333 std::string()));
334 token_service()->IssueErrorForAllPendingRequestsForAccount(
335 "account",
336 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
337 }
338
339 #endif // !OS_CHROMEOS
340
341 TEST_F(AccessTokenFetcherTest,
342 ShouldNotRetryCanceledAccessTokenRequestIfRefreshTokenRevoked) {
343 TestTokenCallback callback;
344
345 SignIn("account");
346 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
347
348 // Signed in and refresh token already exists, so this should result in a
349 // request for an access token.
350 auto fetcher = CreateFetcher(callback.Get());
351
352 // Simulate the refresh token getting invalidated. In this case, pending
353 // access token requests get canceled, and the fetcher should *not* retry.
354 token_service()->GetDelegate()->RevokeCredentials("account");
355 EXPECT_CALL(
356 callback,
357 Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
358 std::string()));
359 token_service()->IssueErrorForAllPendingRequestsForAccount(
360 "account",
361 GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
362 }
363
364 TEST_F(AccessTokenFetcherTest, ShouldNotRetryFailedAccessTokenRequest) {
365 TestTokenCallback callback;
366
367 SignIn("account");
368 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
369
370 // Signed in and refresh token already exists, so this should result in a
371 // request for an access token.
372 auto fetcher = CreateFetcher(callback.Get());
373
374 // An access token failure other than "canceled" should not be retried; we
375 // should immediately get called back with an empty access token.
376 EXPECT_CALL(
377 callback,
378 Run(GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE),
379 std::string()));
380 token_service()->IssueErrorForAllPendingRequestsForAccount(
381 "account",
382 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
383 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698