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

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: ChromeOS, for realz now 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/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/test/mock_callback.h"
14 #include "components/prefs/testing_pref_service.h"
15 #include "components/signin/core/browser/account_tracker_service.h"
16 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
17 #include "components/signin/core/browser/fake_signin_manager.h"
18 #include "components/signin/core/browser/test_signin_client.h"
19 #include "components/sync_preferences/testing_pref_service_syncable.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gmock_mutant.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 using base::MockCallback;
25 using sync_preferences::TestingPrefServiceSyncable;
26 using testing::_;
27 using testing::CallbackToFunctor;
28 using testing::InvokeWithoutArgs;
29 using testing::StrictMock;
30
31 #if defined(OS_CHROMEOS)
32 // ChromeOS doesn't have SigninManager.
33 using SigninManagerForTest = FakeSigninManagerBase;
34 #else
35 using SigninManagerForTest = FakeSigninManager;
36 #endif // OS_CHROMEOS
37
38 class AccessTokenFetcherTest : public testing::Test {
39 public:
40 using TestTokenCallback =
41 StrictMock<MockCallback<AccessTokenFetcher::TokenCallback>>;
42
43 AccessTokenFetcherTest()
44 : signin_client_(&pref_service_) {
45 AccountTrackerService::RegisterPrefs(pref_service_.registry());
46 #if defined(OS_CHROMEOS)
47 SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
48 SigninManagerBase::RegisterPrefs(pref_service_.registry());
49 #else
50 SigninManager::RegisterProfilePrefs(pref_service_.registry());
51 SigninManager::RegisterPrefs(pref_service_.registry());
52 #endif // OS_CHROMEOS
53
54 account_tracker_ = base::MakeUnique<AccountTrackerService>();
55 account_tracker_->Initialize(&signin_client_);
56
57 #if defined(OS_CHROMEOS)
58 signin_manager_ = base::MakeUnique<FakeSigninManagerBase>(
59 &signin_client_, account_tracker_.get());
60 #else
61 signin_manager_ = base::MakeUnique<FakeSigninManager>(
62 &signin_client_, &token_service_, account_tracker_.get(),
63 /*cookie_manager_service=*/nullptr);
64 #endif // OS_CHROMEOS
65 }
66
67 ~AccessTokenFetcherTest() override {}
68
69 std::unique_ptr<AccessTokenFetcher> CreateFetcher(
70 AccessTokenFetcher::TokenCallback callback) {
71 std::set<std::string> scopes{"scope"};
72 return base::MakeUnique<AccessTokenFetcher>(
73 "test_consumer", signin_manager_.get(), &token_service_, scopes,
74 std::move(callback));
75 }
76
77 FakeProfileOAuth2TokenService* token_service() { return &token_service_; }
78 SigninManagerForTest* signin_manager() { return signin_manager_.get(); }
79
80 void SignIn(const std::string& account) {
81 #if defined(OS_CHROMEOS)
82 signin_manager_->SignIn(account);
83 #else
84 signin_manager_->SignIn(account, "user", "pass");
85 #endif // OS_CHROMEOS
86 }
87
88 private:
89 // AccessTokenFetcher may post a task to the current task runner, which
90 // requires an active message loop.
91 base::MessageLoop message_loop_;
92
93 TestingPrefServiceSyncable pref_service_;
94 TestSigninClient signin_client_;
95 FakeProfileOAuth2TokenService token_service_;
96
97 std::unique_ptr<AccountTrackerService> account_tracker_;
98 std::unique_ptr<SigninManagerForTest> signin_manager_;
99 };
100
101 TEST_F(AccessTokenFetcherTest, ShouldReturnAccessToken) {
102 TestTokenCallback callback;
103
104 SignIn("account");
105 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
106
107 // Signed in and refresh token already exists, so this should result in a
108 // request for an access token.
109 auto fetcher = CreateFetcher(callback.Get());
110
111 // Once the access token request is fulfilled, we should get called back with
112 // the access token.
113 EXPECT_CALL(callback, Run("access token"));
114 token_service()->IssueAllTokensForAccount(
115 "account", "access token",
116 base::Time::Now() + base::TimeDelta::FromHours(1));
117 }
118
119 TEST_F(AccessTokenFetcherTest, ShouldNotReplyIfDestroyed) {
120 TestTokenCallback callback;
121
122 SignIn("account");
123 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
124
125 // Signed in and refresh token already exists, so this should result in a
126 // request for an access token.
127 auto fetcher = CreateFetcher(callback.Get());
128
129 // Destroy the fetcher before the access token request is fulfilled.
130 fetcher.reset();
131
132 // Now fulfilling the access token request should have no effect.
133 token_service()->IssueAllTokensForAccount(
134 "account", "access token",
135 base::Time::Now() + base::TimeDelta::FromHours(1));
136 }
137
138 TEST_F(AccessTokenFetcherTest, ShouldReturnEmptyTokenWhenSignedOut) {
139 TestTokenCallback callback;
140
141 // Signed out -> we should get called back with an empty access token.
142 base::RunLoop run_loop;
143 EXPECT_CALL(callback, Run(std::string()))
144 .WillOnce(InvokeWithoutArgs(CallbackToFunctor(run_loop.QuitClosure())));
145 auto fetcher = CreateFetcher(callback.Get());
146 run_loop.Run();
147 }
148
149 TEST_F(AccessTokenFetcherTest, ShouldNotReplyIfDestroyedWhenSignedOut) {
150 TestTokenCallback callback;
151
152 auto fetcher = CreateFetcher(callback.Get());
153
154 // Destroy the fetcher before it gets a chance to run the callback.
155 fetcher.reset();
156
157 // Make sure the fetcher didn't post a callback to the message loop.
158 base::RunLoop().RunUntilIdle();
159 }
160
161 // Tests related to auth-in-progress don't apply on ChromeOS (it doesn't have
162 // that concept).
163 #if !defined(OS_CHROMEOS)
164
165 TEST_F(AccessTokenFetcherTest, ShouldWaitForSignIn) {
166 TestTokenCallback callback;
167
168 signin_manager()->set_auth_in_progress("account");
169
170 // A sign-in is currently in progress, so this should wait for the sign-in to
171 // complete.
172 auto fetcher = CreateFetcher(callback.Get());
173
174 SignIn("account");
175 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
176
177 // Once the access token request is fulfilled, we should get called back with
178 // the access token.
179 EXPECT_CALL(callback, Run("access token"));
180 token_service()->IssueAllTokensForAccount(
181 "account", "access token",
182 base::Time::Now() + base::TimeDelta::FromHours(1));
183 }
184
185 TEST_F(AccessTokenFetcherTest, ShouldWaitForFailedSignIn) {
186 TestTokenCallback callback;
187
188 signin_manager()->set_auth_in_progress("account");
189
190 // A sign-in is currently in progress, so this should wait for the sign-in to
191 // complete.
192 auto fetcher = CreateFetcher(callback.Get());
193
194 // The fetcher should detect the failed sign-in and call us with an empty
195 // access token.
196 EXPECT_CALL(callback, Run(std::string()));
197
198 signin_manager()->FailSignin(GoogleServiceAuthError(
199 GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
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, Run("access token"));
219 token_service()->IssueAllTokensForAccount(
220 "account", "access token",
221 base::Time::Now() + base::TimeDelta::FromHours(1));
222 }
223
224 TEST_F(AccessTokenFetcherTest, ShouldReturnWhenNoRefreshTokenAvailable) {
225 TestTokenCallback callback;
226
227 SignIn("account");
228
229 // Signed in, but there is no refresh token -> we should not get called back
230 // (yet).
231 auto fetcher = CreateFetcher(callback.Get());
232
233 // Getting a refresh token for some other account should have no effect.
234 token_service()->GetDelegate()->UpdateCredentials("different account",
235 "refresh token");
236
237 // When all refresh tokens have been loaded by the token service, but the one
238 // for our account wasn't among them, we should get called back with an empty
239 // access token
240 EXPECT_CALL(callback, Run(std::string()));
241 token_service()->GetDelegate()->LoadCredentials("account doesn't matter");
242 }
243
244 TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequest) {
245 TestTokenCallback callback;
246
247 SignIn("account");
248 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
249
250 // Signed in and refresh token already exists, so this should result in a
251 // request for an access token.
252 auto fetcher = CreateFetcher(callback.Get());
253
254 // A canceled access token request should get retried once.
255 token_service()->IssueErrorForAllPendingRequestsForAccount(
256 "account",
257 GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
258
259 // Once the access token request is fulfilled, we should get called back with
260 // the access token.
261 EXPECT_CALL(callback, Run("access token"));
262 token_service()->IssueAllTokensForAccount(
263 "account", "access token",
264 base::Time::Now() + base::TimeDelta::FromHours(1));
265 }
266
267 TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequestOnlyOnce) {
268 TestTokenCallback callback;
269
270 SignIn("account");
271 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
272
273 // Signed in and refresh token already exists, so this should result in a
274 // request for an access token.
275 auto fetcher = CreateFetcher(callback.Get());
276
277 // A canceled access token request should get retried once.
278 token_service()->IssueErrorForAllPendingRequestsForAccount(
279 "account",
280 GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
281
282 // On the second failure, we should get called back with an empty access
283 // token.
284 EXPECT_CALL(callback, Run(std::string()));
285 token_service()->IssueErrorForAllPendingRequestsForAccount(
286 "account",
287 GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
288 }
289
290 TEST_F(AccessTokenFetcherTest, ShouldNotRetryFailedAccessTokenRequest) {
291 TestTokenCallback callback;
292
293 SignIn("account");
294 token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
295
296 // Signed in and refresh token already exists, so this should result in a
297 // request for an access token.
298 auto fetcher = CreateFetcher(callback.Get());
299
300 // An access token failure other than "canceled" should not be retried; we
301 // should immediately get called back with an empty access token.
302 EXPECT_CALL(callback, Run(std::string()));
303 token_service()->IssueErrorForAllPendingRequestsForAccount(
304 "account", GoogleServiceAuthError(
305 GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
306 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698