summaryrefslogtreecommitdiffstats
path: root/components/signin
diff options
context:
space:
mode:
authorblundell@chromium.org <blundell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-31 11:41:20 +0000
committerblundell@chromium.org <blundell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-31 11:41:20 +0000
commit7fa4af9b89a7d7357db7b1ad12fba8a24f4ad12f (patch)
tree2a9458179a9e4d93b505294b70609240db75043f /components/signin
parente20bc8f3849b2738d158ceb3f56c135128248ab7 (diff)
downloadchromium_src-7fa4af9b89a7d7357db7b1ad12fba8a24f4ad12f.zip
chromium_src-7fa4af9b89a7d7357db7b1ad12fba8a24f4ad12f.tar.gz
chromium_src-7fa4af9b89a7d7357db7b1ad12fba8a24f4ad12f.tar.bz2
Componentize MutableProfileOAuth2TokenService unittest.
This entails: - Creating TestSigninClient for the test to use instead of ChromeSigninClient - Eliminating dependencies on TestingProfile BUG=358001,358000 Review URL: https://codereview.chromium.org/217423003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260525 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/signin')
-rw-r--r--components/signin/core/browser/mutable_profile_oauth2_token_service.h1
-rw-r--r--components/signin/core/browser/mutable_profile_oauth2_token_service_unittest.cc336
-rw-r--r--components/signin/core/browser/test_signin_client.cc46
-rw-r--r--components/signin/core/browser/test_signin_client.h50
4 files changed, 433 insertions, 0 deletions
diff --git a/components/signin/core/browser/mutable_profile_oauth2_token_service.h b/components/signin/core/browser/mutable_profile_oauth2_token_service.h
index 4f10555..a5a100d 100644
--- a/components/signin/core/browser/mutable_profile_oauth2_token_service.h
+++ b/components/signin/core/browser/mutable_profile_oauth2_token_service.h
@@ -68,6 +68,7 @@ class MutableProfileOAuth2TokenService : public ProfileOAuth2TokenService,
typedef std::map<std::string, linked_ptr<AccountInfo> > AccountInfoMap;
friend class ProfileOAuth2TokenServiceFactory;
+ friend class MutableProfileOAuth2TokenServiceTest;
MutableProfileOAuth2TokenService();
virtual ~MutableProfileOAuth2TokenService();
diff --git a/components/signin/core/browser/mutable_profile_oauth2_token_service_unittest.cc b/components/signin/core/browser/mutable_profile_oauth2_token_service_unittest.cc
new file mode 100644
index 0000000..153e0b4
--- /dev/null
+++ b/components/signin/core/browser/mutable_profile_oauth2_token_service_unittest.cc
@@ -0,0 +1,336 @@
+// Copyright 2014 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/mutable_profile_oauth2_token_service.h"
+
+#include "base/run_loop.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
+#include "components/signin/core/browser/test_signin_client.h"
+#include "components/signin/core/browser/webdata/token_web_data.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/oauth2_token_service_test_util.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_MACOSX)
+#include "components/os_crypt/os_crypt.h"
+#endif
+
+// Defining constant here to handle backward compatiblity tests, but this
+// constant is no longer used in current versions of chrome.
+static const char kLSOService[] = "lso";
+static const char kEmail[] = "user@gmail.com";
+
+class MutableProfileOAuth2TokenServiceTest
+ : public testing::Test,
+ public OAuth2TokenService::Observer {
+ public:
+ MutableProfileOAuth2TokenServiceTest()
+ : factory_(NULL),
+ token_available_count_(0),
+ token_revoked_count_(0),
+ tokens_loaded_count_(0) {}
+
+ virtual void SetUp() OVERRIDE {
+#if defined(OS_MACOSX)
+ OSCrypt::UseMockKeychain(true);
+#endif
+
+ factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_revoke_url(),
+ "",
+ net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+ oauth2_service_.Initialize(&client_);
+ // Make sure PO2TS has a chance to load itself before continuing.
+ base::RunLoop().RunUntilIdle();
+ oauth2_service_.AddObserver(this);
+ }
+
+ virtual void TearDown() OVERRIDE {
+ oauth2_service_.RemoveObserver(this);
+ oauth2_service_.Shutdown();
+ }
+
+ void AddAuthTokenManually(const std::string& service,
+ const std::string& value) {
+ scoped_refptr<TokenWebData> token_web_data = client_.GetDatabase();
+ if (token_web_data.get())
+ token_web_data->SetTokenForService(service, value);
+ }
+
+ // OAuth2TokenService::Observer implementation.
+ virtual void OnRefreshTokenAvailable(const std::string& account_id) OVERRIDE {
+ ++token_available_count_;
+ }
+ virtual void OnRefreshTokenRevoked(const std::string& account_id) OVERRIDE {
+ ++token_revoked_count_;
+ }
+ virtual void OnRefreshTokensLoaded() OVERRIDE { ++tokens_loaded_count_; }
+
+ void ResetObserverCounts() {
+ token_available_count_ = 0;
+ token_revoked_count_ = 0;
+ tokens_loaded_count_ = 0;
+ }
+
+ void ExpectNoNotifications() {
+ EXPECT_EQ(0, token_available_count_);
+ EXPECT_EQ(0, token_revoked_count_);
+ EXPECT_EQ(0, tokens_loaded_count_);
+ ResetObserverCounts();
+ }
+
+ void ExpectOneTokenAvailableNotification() {
+ EXPECT_EQ(1, token_available_count_);
+ EXPECT_EQ(0, token_revoked_count_);
+ EXPECT_EQ(0, tokens_loaded_count_);
+ ResetObserverCounts();
+ }
+
+ void ExpectOneTokenRevokedNotification() {
+ EXPECT_EQ(0, token_available_count_);
+ EXPECT_EQ(1, token_revoked_count_);
+ EXPECT_EQ(0, tokens_loaded_count_);
+ ResetObserverCounts();
+ }
+
+ void ExpectOneTokensLoadedNotification() {
+ EXPECT_EQ(0, token_available_count_);
+ EXPECT_EQ(0, token_revoked_count_);
+ EXPECT_EQ(1, tokens_loaded_count_);
+ ResetObserverCounts();
+ }
+
+ protected:
+ base::MessageLoop message_loop_;
+ net::FakeURLFetcherFactory factory_;
+ TestSigninClient client_;
+ MutableProfileOAuth2TokenService oauth2_service_;
+ TestingOAuth2TokenServiceConsumer consumer_;
+ int token_available_count_;
+ int token_revoked_count_;
+ int tokens_loaded_count_;
+};
+
+TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceDBUpgrade) {
+ std::string main_account_id(kEmail);
+ std::string main_refresh_token("old_refresh_token");
+
+ // Populate DB with legacy tokens.
+ AddAuthTokenManually(GaiaConstants::kSyncService, "syncServiceToken");
+ AddAuthTokenManually(kLSOService, "lsoToken");
+ AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+ main_refresh_token);
+
+ // Force LoadCredentials.
+ oauth2_service_.LoadCredentials(main_account_id);
+ base::RunLoop().RunUntilIdle();
+
+ // Legacy tokens get discarded, but the old refresh token is kept.
+ EXPECT_EQ(1, tokens_loaded_count_);
+ EXPECT_EQ(1, token_available_count_);
+ EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(main_account_id));
+ EXPECT_EQ(1U, oauth2_service_.refresh_tokens().size());
+ EXPECT_EQ(main_refresh_token,
+ oauth2_service_.refresh_tokens()[main_account_id]->refresh_token());
+
+ // Add an old legacy token to the DB, to ensure it will not overwrite existing
+ // credentials for main account.
+ AddAuthTokenManually(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
+ "secondOldRefreshToken");
+ // Add some other legacy token. (Expected to get discarded).
+ AddAuthTokenManually(kLSOService, "lsoToken");
+ // Also add a token using PO2TS.UpdateCredentials and make sure upgrade does
+ // not wipe it.
+ std::string other_account_id("other_account_id");
+ std::string other_refresh_token("other_refresh_token");
+ oauth2_service_.UpdateCredentials(other_account_id, other_refresh_token);
+ ResetObserverCounts();
+
+ // Force LoadCredentials.
+ oauth2_service_.LoadCredentials(main_account_id);
+ base::RunLoop().RunUntilIdle();
+
+ // Again legacy tokens get discarded, but since the main porfile account
+ // token is present it is not overwritten.
+ EXPECT_EQ(2, token_available_count_);
+ EXPECT_EQ(1, tokens_loaded_count_);
+ EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(main_account_id));
+ // TODO(fgorski): cover both using RefreshTokenIsAvailable() and then get the
+ // tokens using GetRefreshToken()
+ EXPECT_EQ(2U, oauth2_service_.refresh_tokens().size());
+ EXPECT_EQ(main_refresh_token,
+ oauth2_service_.refresh_tokens()[main_account_id]->refresh_token());
+ EXPECT_EQ(
+ other_refresh_token,
+ oauth2_service_.refresh_tokens()[other_account_id]->refresh_token());
+
+ oauth2_service_.RevokeAllCredentials();
+}
+
+TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceRevokeCredentials) {
+ std::string account_id_1 = "account_id_1";
+ std::string refresh_token_1 = "refresh_token_1";
+ std::string account_id_2 = "account_id_2";
+ std::string refresh_token_2 = "refresh_token_2";
+
+ // TODO(fgorski): Enable below when implemented:
+ // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1));
+ // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_2));
+
+ oauth2_service_.UpdateCredentials(account_id_1, refresh_token_1);
+ oauth2_service_.UpdateCredentials(account_id_2, refresh_token_2);
+
+ // TODO(fgorski): Enable below when implemented:
+ // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1));
+ // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(account_id_2));
+
+ ResetObserverCounts();
+ oauth2_service_.RevokeCredentials(account_id_1);
+ ExpectOneTokenRevokedNotification();
+
+ // TODO(fgorski): Enable below when implemented:
+ // EXPECT_FALSE(oauth2_servive_->RefreshTokenIsAvailable(account_id_1));
+ // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable(account_id_2));
+
+ oauth2_service_.RevokeAllCredentials();
+ EXPECT_EQ(0, token_available_count_);
+ EXPECT_EQ(1, token_revoked_count_);
+ EXPECT_EQ(0, tokens_loaded_count_);
+ ResetObserverCounts();
+}
+
+TEST_F(MutableProfileOAuth2TokenServiceTest, PersistenceLoadCredentials) {
+ // Ensure DB is clean.
+ oauth2_service_.RevokeAllCredentials();
+ ResetObserverCounts();
+ // Perform a load from an empty DB.
+ oauth2_service_.LoadCredentials("account_id");
+ base::RunLoop().RunUntilIdle();
+ ExpectOneTokensLoadedNotification();
+ // LoadCredentials() guarantees that the account given to it as argument
+ // is in the refresh_token map.
+ EXPECT_EQ(1U, oauth2_service_.refresh_tokens().size());
+ EXPECT_TRUE(
+ oauth2_service_.refresh_tokens()["account_id"]->refresh_token().empty());
+ // Setup a DB with tokens that don't require upgrade and clear memory.
+ oauth2_service_.UpdateCredentials("account_id", "refresh_token");
+ oauth2_service_.UpdateCredentials("account_id2", "refresh_token2");
+ oauth2_service_.refresh_tokens().clear();
+ ResetObserverCounts();
+
+ oauth2_service_.LoadCredentials("account_id");
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2, token_available_count_);
+ EXPECT_EQ(0, token_revoked_count_);
+ EXPECT_EQ(1, tokens_loaded_count_);
+ ResetObserverCounts();
+
+ // TODO(fgorski): Enable below when implemented:
+ // EXPECT_TRUE(oauth2_servive_->RefreshTokenIsAvailable("account_id"));
+ // EXPECT_TRUE(oauth2_service_.RefreshTokenIsAvailable("account_id2"));
+
+ oauth2_service_.RevokeAllCredentials();
+ EXPECT_EQ(0, token_available_count_);
+ EXPECT_EQ(2, token_revoked_count_);
+ EXPECT_EQ(0, tokens_loaded_count_);
+ ResetObserverCounts();
+}
+
+TEST_F(MutableProfileOAuth2TokenServiceTest, PersistanceNotifications) {
+ EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
+ oauth2_service_.UpdateCredentials("account_id", "refresh_token");
+ ExpectOneTokenAvailableNotification();
+
+ oauth2_service_.UpdateCredentials("account_id", "refresh_token");
+ ExpectNoNotifications();
+
+ oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
+ ExpectOneTokenAvailableNotification();
+
+ oauth2_service_.RevokeCredentials("account_id");
+ ExpectOneTokenRevokedNotification();
+
+ oauth2_service_.UpdateCredentials("account_id", "refresh_token2");
+ ExpectOneTokenAvailableNotification();
+
+ oauth2_service_.RevokeAllCredentials();
+ ResetObserverCounts();
+}
+
+TEST_F(MutableProfileOAuth2TokenServiceTest, GetAccounts) {
+ EXPECT_TRUE(oauth2_service_.GetAccounts().empty());
+ oauth2_service_.UpdateCredentials("account_id1", "refresh_token1");
+ oauth2_service_.UpdateCredentials("account_id2", "refresh_token2");
+ std::vector<std::string> accounts = oauth2_service_.GetAccounts();
+ EXPECT_EQ(2u, accounts.size());
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id2"));
+ oauth2_service_.RevokeCredentials("account_id2");
+ accounts = oauth2_service_.GetAccounts();
+ EXPECT_EQ(1u, oauth2_service_.GetAccounts().size());
+ EXPECT_EQ(1, count(accounts.begin(), accounts.end(), "account_id1"));
+}
+
+TEST_F(MutableProfileOAuth2TokenServiceTest, TokenServiceUpdateClearsCache) {
+ EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
+ std::set<std::string> scope_list;
+ scope_list.insert("scope");
+ oauth2_service_.UpdateCredentials(kEmail, "refreshToken");
+ ExpectOneTokenAvailableNotification();
+ factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ GetValidTokenResponse("token", 3600),
+ net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+
+ scoped_ptr<OAuth2TokenService::Request> request(
+ oauth2_service_.StartRequest(kEmail, scope_list, &consumer_));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("token", consumer_.last_token_);
+ EXPECT_EQ(1, oauth2_service_.cache_size_for_testing());
+
+ // Signs out and signs in
+ oauth2_service_.RevokeCredentials(kEmail);
+ ExpectOneTokenRevokedNotification();
+
+ EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
+ oauth2_service_.UpdateCredentials(kEmail, "refreshToken");
+ ExpectOneTokenAvailableNotification();
+ factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ GetValidTokenResponse("another token", 3600),
+ net::HTTP_OK,
+ net::URLRequestStatus::SUCCESS);
+
+ request = oauth2_service_.StartRequest(kEmail, scope_list, &consumer_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
+ EXPECT_EQ(0, consumer_.number_of_errors_);
+ EXPECT_EQ("another token", consumer_.last_token_);
+ EXPECT_EQ(1, oauth2_service_.cache_size_for_testing());
+}
+
+TEST_F(MutableProfileOAuth2TokenServiceTest, FetchTransientError) {
+ factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
+ "",
+ net::HTTP_FORBIDDEN,
+ net::URLRequestStatus::FAILED);
+
+ EXPECT_EQ(0, oauth2_service_.cache_size_for_testing());
+ std::set<std::string> scope_list;
+ scope_list.insert("scope");
+ oauth2_service_.set_max_authorization_token_fetch_retries_for_testing(0);
+ oauth2_service_.UpdateCredentials(kEmail, "refreshToken");
+ ExpectOneTokenAvailableNotification();
+
+ scoped_ptr<OAuth2TokenService::Request> request(
+ oauth2_service_.StartRequest(kEmail, scope_list, &consumer_));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(GoogleServiceAuthError::AuthErrorNone(),
+ oauth2_service_.signin_error_controller()->auth_error());
+}
diff --git a/components/signin/core/browser/test_signin_client.cc b/components/signin/core/browser/test_signin_client.cc
new file mode 100644
index 0000000..dd75e19
--- /dev/null
+++ b/components/signin/core/browser/test_signin_client.cc
@@ -0,0 +1,46 @@
+// Copyright 2014 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 "base/logging.h"
+#include "components/signin/core/browser/test_signin_client.h"
+#include "components/signin/core/browser/webdata/token_service_table.h"
+#include "components/webdata/common/web_data_service_base.h"
+#include "components/webdata/common/web_database_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TestSigninClient::TestSigninClient()
+ : request_context_(new net::TestURLRequestContextGetter(
+ base::MessageLoopProxy::current())) {
+ LoadDatabase();
+}
+
+TestSigninClient::~TestSigninClient() {}
+
+PrefService* TestSigninClient::GetPrefs() { return NULL; }
+
+scoped_refptr<TokenWebData> TestSigninClient::GetDatabase() {
+ return database_;
+}
+
+bool TestSigninClient::CanRevokeCredentials() { return true; }
+
+net::URLRequestContextGetter* TestSigninClient::GetURLRequestContext() {
+ return request_context_;
+}
+
+void TestSigninClient::LoadDatabase() {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ base::FilePath path = temp_dir_.path().AppendASCII("TestWebDB");
+ scoped_refptr<WebDatabaseService> web_database =
+ new WebDatabaseService(path,
+ base::MessageLoopProxy::current(),
+ base::MessageLoopProxy::current());
+ web_database->AddTable(scoped_ptr<WebDatabaseTable>(new TokenServiceTable()));
+ web_database->LoadDatabase();
+ database_ = new TokenWebData(web_database,
+ base::MessageLoopProxy::current(),
+ base::MessageLoopProxy::current(),
+ WebDataServiceBase::ProfileErrorCallback());
+ database_->Init();
+}
diff --git a/components/signin/core/browser/test_signin_client.h b/components/signin/core/browser/test_signin_client.h
new file mode 100644
index 0000000..d1d2fac
--- /dev/null
+++ b/components/signin/core/browser/test_signin_client.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_TEST_SIGNIN_CLIENT_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_TEST_SIGNIN_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ref_counted.h"
+#include "components/signin/core/browser/signin_client.h"
+#include "net/url_request/url_request_test_util.h"
+
+// An implementation of SigninClient for use in unittests. Instantiates test
+// versions of the various objects that SigninClient is required to provide as
+// part of its interface.
+class TestSigninClient : public SigninClient {
+ public:
+ TestSigninClient();
+ virtual ~TestSigninClient();
+
+ // SigninClient implementation that is specialized for unit tests.
+
+ // Returns NULL.
+ // NOTE: This should be changed to return a properly-initalized PrefService
+ // once there is a unit test that requires it.
+ virtual PrefService* GetPrefs() OVERRIDE;
+
+ // Returns a pointer to a loaded database.
+ virtual scoped_refptr<TokenWebData> GetDatabase() OVERRIDE;
+
+ // Returns true.
+ virtual bool CanRevokeCredentials() OVERRIDE;
+
+ // Returns a TestURLRequestContextGetter.
+ virtual net::URLRequestContextGetter* GetURLRequestContext() OVERRIDE;
+
+ private:
+ // Loads the token database.
+ void LoadDatabase();
+
+ base::ScopedTempDir temp_dir_;
+ scoped_refptr<net::TestURLRequestContextGetter> request_context_;
+ scoped_refptr<TokenWebData> database_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSigninClient);
+};
+
+#endif // COMPONENTS_SIGNIN_CORE_BROWSER_TEST_SIGNIN_CLIENT_H_