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

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: review2 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::_;
25 using testing::CallbackToFunctor;
26 using testing::InvokeWithoutArgs;
27 using testing::StrictMock;
28
29 #if defined(OS_CHROMEOS)
30 // ChromeOS doesn't have SigninManager.
31 using SigninManagerForTest = FakeSigninManagerBase;
32 #else
33 using SigninManagerForTest = FakeSigninManager;
34 #endif // OS_CHROMEOS
35
36 class AccessTokenFetcherTest : public testing::Test {
37 public:
38 using TestTokenCallback =
39 StrictMock<MockCallback<AccessTokenFetcher::TokenCallback>>;
40
41 AccessTokenFetcherTest()
42 : signin_client_(&pref_service_) {
43 AccountTrackerService::RegisterPrefs(pref_service_.registry());
44 #if defined(OS_CHROMEOS)
45 SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
46 SigninManagerBase::RegisterPrefs(pref_service_.registry());
47 #else
48 SigninManager::RegisterProfilePrefs(pref_service_.registry());
49 SigninManager::RegisterPrefs(pref_service_.registry());
50 #endif // OS_CHROMEOS
51
52 account_tracker_ = base::MakeUnique<AccountTrackerService>();
53 account_tracker_->Initialize(&signin_client_);
54
55 #if defined(OS_CHROMEOS)
56 signin_manager_ = base::MakeUnique<FakeSigninManagerBase>(
57 &signin_client_, account_tracker_.get());
58 #else
59 signin_manager_ = base::MakeUnique<FakeSigninManager>(
60 &signin_client_, &token_service_, account_tracker_.get(),
61 /*cookie_manager_service=*/nullptr);
62 #endif // OS_CHROMEOS
63 }
64
65 ~AccessTokenFetcherTest() override {}
66
67 std::unique_ptr<AccessTokenFetcher> CreateFetcher(
68 AccessTokenFetcher::TokenCallback callback) {
69 std::set<std::string> scopes{"scope"};
70 return base::MakeUnique<AccessTokenFetcher>(
71 "test_consumer", signin_manager_.get(), &token_service_, scopes,
72 std::move(callback));
73 }
74
75 FakeProfileOAuth2TokenService* token_service() { return &token_service_; }
76 SigninManagerForTest* signin_manager() { return signin_manager_.get(); }
77
78 void SignIn(const std::string& account) {
79 #if defined(OS_CHROMEOS)
80 signin_manager_->SignIn(account);
81 #else
82 signin_manager_->SignIn(account, "user", "pass");
83 #endif // OS_CHROMEOS
84 }
85
86 private:
87 TestingPrefServiceSyncable pref_service_;
88 TestSigninClient signin_client_;
89 FakeProfileOAuth2TokenService token_service_;
90
91 std::unique_ptr<AccountTrackerService> account_tracker_;
92 std::unique_ptr<SigninManagerForTest> signin_manager_;
93 };
94
95 TEST_F(AccessTokenFetcherTest, ShouldReturnAccessToken) {
96 TestTokenCallback callback;
97
98 SignIn("account");
99 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
100
101 // Signed in and refresh token already exists, so this should result in a
102 // request for an access token.
103 auto fetcher = CreateFetcher(callback.Get());
104
105 // Once the access token request is fulfilled, we should get called back with
106 // the access token.
107 EXPECT_CALL(callback, Run("access token"));
108 token_service()->IssueAllTokensForAccount(
109 "account", "access token",
110 base::Time::Now() + base::TimeDelta::FromHours(1));
111 }
112
113 TEST_F(AccessTokenFetcherTest, ShouldNotReplyIfDestroyed) {
114 TestTokenCallback callback;
115
116 SignIn("account");
117 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
118
119 // Signed in and refresh token already exists, so this should result in a
120 // request for an access token.
121 auto fetcher = CreateFetcher(callback.Get());
122
123 // Destroy the fetcher before the access token request is fulfilled.
124 fetcher.reset();
125
126 // Now fulfilling the access token request should have no effect.
127 token_service()->IssueAllTokensForAccount(
128 "account", "access token",
129 base::Time::Now() + base::TimeDelta::FromHours(1));
130 }
131
132 TEST_F(AccessTokenFetcherTest, ShouldNotReturnWhenSignedOut) {
133 TestTokenCallback callback;
134
135 // Signed out -> the fetcher should wait for a sign-in which never happens
136 // in this test, so we shouldn't get called back.
137 auto fetcher = CreateFetcher(callback.Get());
138 }
139
140 TEST_F(AccessTokenFetcherTest, ShouldWaitForSignIn) {
141 TestTokenCallback callback;
142
143 // Not signed in, so this should wait for a sign-in to complete.
144 auto fetcher = CreateFetcher(callback.Get());
145
146 SignIn("account");
147 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
148
149 // Once the access token request is fulfilled, we should get called back with
150 // the access token.
151 EXPECT_CALL(callback, Run("access token"));
152 token_service()->IssueAllTokensForAccount(
153 "account", "access token",
154 base::Time::Now() + base::TimeDelta::FromHours(1));
155 }
156
157 // Tests related to auth-in-progress don't apply on ChromeOS (it doesn't have
158 // that concept).
159 #if !defined(OS_CHROMEOS)
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, Run("access token"));
176 token_service()->IssueAllTokensForAccount(
177 "account", "access token",
178 base::Time::Now() + base::TimeDelta::FromHours(1));
179 }
180
181 TEST_F(AccessTokenFetcherTest, ShouldWaitForFailedSignIn) {
182 TestTokenCallback callback;
183
184 signin_manager()->set_auth_in_progress("account");
185
186 // A sign-in is currently in progress, so this should wait for the sign-in to
187 // complete.
188 auto fetcher = CreateFetcher(callback.Get());
189
190 // The fetcher should detect the failed sign-in and call us with an empty
191 // access token.
192 EXPECT_CALL(callback, Run(std::string()));
193
194 signin_manager()->FailSignin(GoogleServiceAuthError(
195 GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
196 }
197
198 #endif // !OS_CHROMEOS
199
200 TEST_F(AccessTokenFetcherTest, ShouldWaitForRefreshToken) {
201 TestTokenCallback callback;
202
203 SignIn("account");
204
205 // Signed in, but there is no refresh token -> we should not get called back
206 // (yet).
207 auto fetcher = CreateFetcher(callback.Get());
208
209 // Getting a refresh token should result in a request for an access token.
210 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
211
212 // Once the access token request is fulfilled, we should get called back with
213 // the access token.
214 EXPECT_CALL(callback, Run("access token"));
215 token_service()->IssueAllTokensForAccount(
216 "account", "access token",
217 base::Time::Now() + base::TimeDelta::FromHours(1));
218 }
219
220 TEST_F(AccessTokenFetcherTest, ShouldIgnoreRefreshTokensForOtherAccounts) {
221 TestTokenCallback callback;
222
223 // Signed-in to "account", but there's only a refresh token for a different
224 // account.
225 SignIn("account");
226 token_service()->GetDelegate()->UpdateCredentials("account 2", "refresh");
227
228 // The fetcher should wait for the correct refresh token.
229 auto fetcher = CreateFetcher(callback.Get());
230
231 // A refresh token for yet another account shouldn't matter either.
232 token_service()->GetDelegate()->UpdateCredentials("account 3", "refresh");
233 }
234
235 TEST_F(AccessTokenFetcherTest, ShouldReturnWhenNoRefreshTokenAvailable) {
236 TestTokenCallback callback;
237
238 SignIn("account");
239
240 // Signed in, but there is no refresh token -> we should not get called back
241 // (yet).
242 auto fetcher = CreateFetcher(callback.Get());
243
244 // Getting a refresh token for some other account should have no effect.
245 token_service()->GetDelegate()->UpdateCredentials("different account",
246 "refresh token");
247
248 // When all refresh tokens have been loaded by the token service, but the one
249 // for our account wasn't among them, we should get called back with an empty
250 // access token
251 EXPECT_CALL(callback, Run(std::string()));
252 token_service()->GetDelegate()->LoadCredentials("account doesn't matter");
253 }
254
255 TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequest) {
256 TestTokenCallback callback;
257
258 SignIn("account");
259 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
260
261 // Signed in and refresh token already exists, so this should result in a
262 // request for an access token.
263 auto fetcher = CreateFetcher(callback.Get());
264
265 // A canceled access token request should get retried once.
266 token_service()->IssueErrorForAllPendingRequestsForAccount(
267 "account",
268 GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
269
270 // Once the access token request is fulfilled, we should get called back with
271 // the access token.
272 EXPECT_CALL(callback, Run("access token"));
273 token_service()->IssueAllTokensForAccount(
274 "account", "access token",
275 base::Time::Now() + base::TimeDelta::FromHours(1));
276 }
277
278 TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequestOnlyOnce) {
279 TestTokenCallback callback;
280
281 SignIn("account");
282 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
283
284 // Signed in and refresh token already exists, so this should result in a
285 // request for an access token.
286 auto fetcher = CreateFetcher(callback.Get());
287
288 // A canceled access token request should get retried once.
289 token_service()->IssueErrorForAllPendingRequestsForAccount(
290 "account",
291 GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
292
293 // On the second failure, we should get called back with an empty access
294 // token.
295 EXPECT_CALL(callback, Run(std::string()));
296 token_service()->IssueErrorForAllPendingRequestsForAccount(
297 "account",
298 GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
299 }
300
301 TEST_F(AccessTokenFetcherTest, ShouldNotRetryFailedAccessTokenRequest) {
302 TestTokenCallback callback;
303
304 SignIn("account");
305 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
306
307 // Signed in and refresh token already exists, so this should result in a
308 // request for an access token.
309 auto fetcher = CreateFetcher(callback.Get());
310
311 // An access token failure other than "canceled" should not be retried; we
312 // should immediately get called back with an empty access token.
313 EXPECT_CALL(callback, Run(std::string()));
314 token_service()->IssueErrorForAllPendingRequestsForAccount(
315 "account", GoogleServiceAuthError(
316 GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
317 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698