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

Unified Diff: components/signin/core/browser/access_token_fetcher_unittest.cc

Issue 2582573002: Signin/OAuth: Create an AccessTokenFetcher helper class (Closed)
Patch Set: AuthInProgress test 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 side-by-side diff with in-line comments
Download patch
Index: components/signin/core/browser/access_token_fetcher_unittest.cc
diff --git a/components/signin/core/browser/access_token_fetcher_unittest.cc b/components/signin/core/browser/access_token_fetcher_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..89bb1c7d15b62453df54e8313d84ddba0fbd24af
--- /dev/null
+++ b/components/signin/core/browser/access_token_fetcher_unittest.cc
@@ -0,0 +1,258 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/access_token_fetcher.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/test/mock_callback.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/fake_signin_manager.h"
+#include "components/signin/core/browser/test_signin_client.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "google_apis/gaia/fake_oauth2_token_service.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gmock_mutant.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::MockCallback;
+using sync_preferences::TestingPrefServiceSyncable;
+using testing::_;
+using testing::CallbackToFunctor;
+using testing::InvokeWithoutArgs;
+using testing::StrictMock;
+
+class AccessTokenFetcherTest : public testing::Test {
+ public:
+ using TestTokenCallback =
+ StrictMock<MockCallback<AccessTokenFetcher::TokenCallback>>;
+
+ AccessTokenFetcherTest()
+ : signin_client_(&pref_service_),
+ signin_manager_(&signin_client_, &account_tracker_) {
+ SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
+ SigninManagerBase::RegisterPrefs(pref_service_.registry());
+ }
+
+ ~AccessTokenFetcherTest() override {}
+
+ std::unique_ptr<AccessTokenFetcher> CreateFetcher(
+ AccessTokenFetcher::TokenCallback callback) {
+ std::set<std::string> scopes{"scope"};
+ return base::MakeUnique<AccessTokenFetcher>(
+ "test_consumer", &signin_manager_, &token_service_, scopes,
+ std::move(callback));
+ }
+
+ FakeOAuth2TokenService* token_service() { return &token_service_; }
+ FakeSigninManagerBase* signin_manager() { return &signin_manager_; }
+
+ private:
+ // AccessTokenFetcher may post a task to the current task runner, which
+ // requires an active message loop.
+ base::MessageLoop message_loop_;
+
+ FakeOAuth2TokenService token_service_;
+ TestingPrefServiceSyncable pref_service_;
+ AccountTrackerService account_tracker_;
+ TestSigninClient signin_client_;
+ FakeSigninManagerBase signin_manager_;
+};
+
+TEST_F(AccessTokenFetcherTest, ShouldReturnAccessToken) {
+ TestTokenCallback callback;
+
+ signin_manager()->SignIn("account");
+ token_service()->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
+ "account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run("access token"));
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldNotReplyIfDestroyed) {
+ TestTokenCallback callback;
+
+ signin_manager()->SignIn("account");
+ token_service()->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
+ "account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Destroy the fetcher before the access token request is fulfilled.
+ fetcher.reset();
+
+ // Now fulfilling the access token request should have no effect.
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldReturnEmptyTokenWhenSignedOut) {
+ TestTokenCallback callback;
+
+ // Signed out -> we should get called back with an empty access token.
+ base::RunLoop run_loop;
+ EXPECT_CALL(callback, Run(std::string()))
+ .WillOnce(InvokeWithoutArgs(CallbackToFunctor(run_loop.QuitClosure())));
+ auto fetcher = CreateFetcher(callback.Get());
+ run_loop.Run();
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldNotReplyIfDestroyedWhenSignedOut) {
+ TestTokenCallback callback;
+
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Destroy the fetcher before it gets a chance to run the callback.
+ fetcher.reset();
+
+ // Make sure the fetcher didn't post a callback to the message loop.
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldWaitForSignIn) {
+ TestTokenCallback callback;
+
+ signin_manager()->SetAuthInProgress(true);
+
+ // A sign-in is currently in progress, so this should wait for the sign-in to
+ // complete.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ signin_manager()->SignIn("account");
+ token_service()->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
+ "account", "refresh token");
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run("access token"));
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldWaitForRefreshToken) {
+ TestTokenCallback callback;
+
+ signin_manager()->SignIn("account");
+
+ // Signed in, but there is no refresh token -> we should not get called back
+ // (yet).
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Getting a refresh token should result in a request for an access token.
+ token_service()->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
+ "account", "refresh token");
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run("access token"));
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldReturnWhenNoRefreshTokenAvailable) {
+ TestTokenCallback callback;
+
+ signin_manager()->SignIn("account");
+
+ // Signed in, but there is no refresh token -> we should not get called back
+ // (yet).
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Getting a refresh token for some other account should have no effect.
+ token_service()->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
+ "different account", "refresh token");
+
+ // When all refresh tokens have been loaded by the token service, but the one
+ // for our account wasn't among them, we should get called back with an empty
+ // access token
+ EXPECT_CALL(callback, Run(std::string()));
+ token_service()->GetFakeOAuth2TokenServiceDelegate()->LoadCredentials(
+ "account doesn't matter");
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequest) {
+ TestTokenCallback callback;
+
+ signin_manager()->SignIn("account");
+ token_service()->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
+ "account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // A canceled access token request should get retried once.
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account",
+ GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback, Run("access token"));
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequestOnlyOnce) {
+ TestTokenCallback callback;
+
+ signin_manager()->SignIn("account");
+ token_service()->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
+ "account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // A canceled access token request should get retried once.
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account",
+ GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
+
+ // On the second failure, we should get called back with an empty access
+ // token.
+ EXPECT_CALL(callback, Run(std::string()));
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account",
+ GoogleServiceAuthError(GoogleServiceAuthError::State::REQUEST_CANCELED));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldNotRetryFailedAccessTokenRequest) {
+ TestTokenCallback callback;
+
+ signin_manager()->SignIn("account");
+ token_service()->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
+ "account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // An access token failure other than "canceled" should not be retried; we
+ // should immediately get called back with an empty access token.
+ EXPECT_CALL(callback, Run(std::string()));
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account", GoogleServiceAuthError(
+ GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS));
+}

Powered by Google App Engine
This is Rietveld 408576698