| Index: chrome/browser/signin/account_service_flag_fetcher_unittest.cc
|
| diff --git a/chrome/browser/signin/account_service_flag_fetcher_unittest.cc b/chrome/browser/signin/account_service_flag_fetcher_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..eb1e5b437b71e4ad998280108c731e9a093b0e2e
|
| --- /dev/null
|
| +++ b/chrome/browser/signin/account_service_flag_fetcher_unittest.cc
|
| @@ -0,0 +1,308 @@
|
| +// 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 <string>
|
| +#include <vector>
|
| +
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
|
| +#include "components/signin/core/browser/account_service_flag_fetcher.h"
|
| +#include "google_apis/gaia/gaia_urls.h"
|
| +#include "net/url_request/test_url_fetcher_factory.h"
|
| +#include "net/url_request/url_request_test_util.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +const char kAccountId[] = "user@gmail.com";
|
| +const char kDifferentAccountId[] = "some_other_user@gmail.com";
|
| +
|
| +const int kGaiaAuthFetcherURLFetcherID = 0;
|
| +
|
| +// TODO(treib): This class should really live in components/signin/ next to the
|
| +// AccountServiceFlagFetcher, but it uses the FakePO2TS which lives in
|
| +// chrome/browser/ (because it uses the AndroidPO2TS which depends on stuff from
|
| +// chrome/browser/). So when the AndroidPO2TS is componentized, then this should
|
| +// move as well.
|
| +class AccountServiceFlagFetcherTest : public testing::Test {
|
| + public:
|
| + AccountServiceFlagFetcherTest()
|
| + : request_context_(new net::TestURLRequestContextGetter(
|
| + base::MessageLoopProxy::current())) {
|
| + service_flags_.push_back("some_flag");
|
| + service_flags_.push_back("another_flag");
|
| + service_flags_.push_back("andonemore");
|
| + }
|
| +
|
| + MOCK_METHOD2(OnFlagsFetched,
|
| + void(AccountServiceFlagFetcher::ResultCode result,
|
| + const std::vector<std::string>& flags));
|
| +
|
| + protected:
|
| + net::TestURLFetcher* GetLoginURLFetcher() {
|
| + net::TestURLFetcher* fetcher =
|
| + url_fetcher_factory_.GetFetcherByID(kGaiaAuthFetcherURLFetcherID);
|
| + EXPECT_TRUE(fetcher);
|
| +
|
| + EXPECT_EQ(GaiaUrls::GetInstance()->oauth1_login_url(),
|
| + fetcher->GetOriginalURL());
|
| +
|
| + return fetcher;
|
| + }
|
| +
|
| + net::TestURLFetcher* GetGetUserInfoURLFetcher() {
|
| + net::TestURLFetcher* fetcher =
|
| + url_fetcher_factory_.GetFetcherByID(kGaiaAuthFetcherURLFetcherID);
|
| + EXPECT_TRUE(fetcher);
|
| +
|
| + EXPECT_EQ(GaiaUrls::GetInstance()->get_user_info_url(),
|
| + fetcher->GetOriginalURL());
|
| +
|
| + return fetcher;
|
| + }
|
| +
|
| + void SendValidLoginResponse() {
|
| + net::TestURLFetcher* fetcher = GetLoginURLFetcher();
|
| + fetcher->set_status(
|
| + net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0));
|
| + fetcher->set_response_code(net::HTTP_OK);
|
| + fetcher->SetResponseString(std::string("SID=sid\nLSID=lsid\nAuth=auth\n"));
|
| + fetcher->delegate()->OnURLFetchComplete(fetcher);
|
| + }
|
| +
|
| + void SendFailedLoginResponse() {
|
| + net::TestURLFetcher* fetcher = GetLoginURLFetcher();
|
| + fetcher->set_status(
|
| + net::URLRequestStatus(net::URLRequestStatus::CANCELED, 0));
|
| + fetcher->set_response_code(net::HTTP_OK);
|
| + fetcher->SetResponseString(std::string());
|
| + fetcher->delegate()->OnURLFetchComplete(fetcher);
|
| + }
|
| +
|
| + void SendValidGetUserInfoResponse() {
|
| + net::TestURLFetcher* fetcher = GetGetUserInfoURLFetcher();
|
| + fetcher->set_status(
|
| + net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0));
|
| + fetcher->set_response_code(net::HTTP_OK);
|
| + fetcher->SetResponseString(BuildGetUserInfoResponse());
|
| + fetcher->delegate()->OnURLFetchComplete(fetcher);
|
| + }
|
| +
|
| + void SendInvalidGetUserInfoResponse() {
|
| + net::TestURLFetcher* fetcher = GetGetUserInfoURLFetcher();
|
| + fetcher->set_status(
|
| + net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0));
|
| + fetcher->set_response_code(net::HTTP_OK);
|
| + fetcher->SetResponseString(std::string("allServicesIsMissing=true"));
|
| + fetcher->delegate()->OnURLFetchComplete(fetcher);
|
| + }
|
| +
|
| + void SendFailedGetUserInfoResponse() {
|
| + net::TestURLFetcher* fetcher = GetGetUserInfoURLFetcher();
|
| + fetcher->set_status(
|
| + net::URLRequestStatus(net::URLRequestStatus::CANCELED, 0));
|
| + fetcher->set_response_code(net::HTTP_OK);
|
| + fetcher->SetResponseString(std::string());
|
| + fetcher->delegate()->OnURLFetchComplete(fetcher);
|
| + }
|
| +
|
| + std::string BuildGetUserInfoResponse() const {
|
| + return "allServices=" + JoinString(service_flags_, ',');
|
| + }
|
| +
|
| + base::MessageLoop message_loop_;
|
| + FakeProfileOAuth2TokenService token_service_;
|
| + scoped_refptr<net::TestURLRequestContextGetter> request_context_;
|
| + net::TestURLFetcherFactory url_fetcher_factory_;
|
| + net::ResponseCookies cookies_;
|
| + std::vector<std::string> service_flags_;
|
| +};
|
| +
|
| +TEST_F(AccountServiceFlagFetcherTest, Success) {
|
| + token_service_.UpdateCredentials(kAccountId, "refresh_token");
|
| +
|
| + AccountServiceFlagFetcher fetcher(
|
| + kAccountId,
|
| + &token_service_,
|
| + request_context_.get(),
|
| + base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched,
|
| + base::Unretained(this)));
|
| +
|
| + // Since a refresh token is already available, we should immediately get a
|
| + // request for an access token.
|
| + EXPECT_EQ(1U, token_service_.GetPendingRequests().size());
|
| +
|
| + token_service_.IssueAllTokensForAccount(
|
| + kAccountId,
|
| + "access_token",
|
| + base::Time::Now() + base::TimeDelta::FromHours(1));
|
| +
|
| + SendValidLoginResponse();
|
| +
|
| + EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SUCCESS,
|
| + service_flags_));
|
| + SendValidGetUserInfoResponse();
|
| +}
|
| +
|
| +TEST_F(AccountServiceFlagFetcherTest, SuccessAfterWaitingForRefreshToken) {
|
| + AccountServiceFlagFetcher fetcher(
|
| + kAccountId,
|
| + &token_service_,
|
| + request_context_.get(),
|
| + base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched,
|
| + base::Unretained(this)));
|
| +
|
| + // Since there is no refresh token yet, we should not get a request for an
|
| + // access token at this point.
|
| + EXPECT_EQ(0U, token_service_.GetPendingRequests().size());
|
| +
|
| + token_service_.UpdateCredentials(kAccountId, "refresh_token");
|
| +
|
| + // Now there is a refresh token and we should have got a request for an
|
| + // access token.
|
| + EXPECT_EQ(1U, token_service_.GetPendingRequests().size());
|
| +
|
| + token_service_.IssueAllTokensForAccount(
|
| + kAccountId,
|
| + "access_token",
|
| + base::Time::Now() + base::TimeDelta::FromHours(1));
|
| +
|
| + SendValidLoginResponse();
|
| +
|
| + EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SUCCESS,
|
| + service_flags_));
|
| + SendValidGetUserInfoResponse();
|
| +}
|
| +
|
| +TEST_F(AccountServiceFlagFetcherTest, NoRefreshToken) {
|
| + AccountServiceFlagFetcher fetcher(
|
| + kAccountId,
|
| + &token_service_,
|
| + request_context_.get(),
|
| + base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched,
|
| + base::Unretained(this)));
|
| +
|
| + token_service_.UpdateCredentials(kDifferentAccountId, "refresh_token");
|
| +
|
| + // Credentials for a different user should be ignored, i.e. not result in a
|
| + // request for an access token.
|
| + EXPECT_EQ(0U, token_service_.GetPendingRequests().size());
|
| +
|
| + // After all refresh tokens have been loaded, there is still no token for our
|
| + // user, so we expect a token error.
|
| + EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::TOKEN_ERROR,
|
| + std::vector<std::string>()));
|
| + token_service_.IssueAllRefreshTokensLoaded();
|
| +}
|
| +
|
| +TEST_F(AccountServiceFlagFetcherTest, GetTokenFailure) {
|
| + token_service_.UpdateCredentials(kAccountId, "refresh_token");
|
| +
|
| + AccountServiceFlagFetcher fetcher(
|
| + kAccountId,
|
| + &token_service_,
|
| + request_context_.get(),
|
| + base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched,
|
| + base::Unretained(this)));
|
| +
|
| + // On failure to get an access token we expect a token error.
|
| + EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::TOKEN_ERROR,
|
| + std::vector<std::string>()));
|
| + token_service_.IssueErrorForAllPendingRequestsForAccount(
|
| + kAccountId,
|
| + GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
|
| +}
|
| +
|
| +TEST_F(AccountServiceFlagFetcherTest, ClientLoginFailure) {
|
| + token_service_.UpdateCredentials(kAccountId, "refresh_token");
|
| +
|
| + AccountServiceFlagFetcher fetcher(
|
| + kAccountId,
|
| + &token_service_,
|
| + request_context_.get(),
|
| + base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched,
|
| + base::Unretained(this)));
|
| +
|
| + token_service_.IssueAllTokensForAccount(
|
| + kAccountId,
|
| + "access_token",
|
| + base::Time::Now() + base::TimeDelta::FromHours(1));
|
| +
|
| + // Login failure should result in a service error.
|
| + EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SERVICE_ERROR,
|
| + std::vector<std::string>()));
|
| + SendFailedLoginResponse();
|
| +}
|
| +
|
| +TEST_F(AccountServiceFlagFetcherTest, GetUserInfoInvalidResponse) {
|
| + token_service_.UpdateCredentials(kAccountId, "refresh_token");
|
| +
|
| + AccountServiceFlagFetcher fetcher(
|
| + kAccountId,
|
| + &token_service_,
|
| + request_context_.get(),
|
| + base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched,
|
| + base::Unretained(this)));
|
| +
|
| + token_service_.IssueAllTokensForAccount(
|
| + kAccountId,
|
| + "access_token",
|
| + base::Time::Now() + base::TimeDelta::FromHours(1));
|
| +
|
| + SendValidLoginResponse();
|
| +
|
| + // Invalid response data from GetUserInfo should result in a service error.
|
| + EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SERVICE_ERROR,
|
| + std::vector<std::string>()));
|
| + SendInvalidGetUserInfoResponse();
|
| +}
|
| +
|
| +TEST_F(AccountServiceFlagFetcherTest, GetUserInfoFailure) {
|
| + token_service_.UpdateCredentials(kAccountId, "refresh_token");
|
| +
|
| + AccountServiceFlagFetcher fetcher(
|
| + kAccountId,
|
| + &token_service_,
|
| + request_context_.get(),
|
| + base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched,
|
| + base::Unretained(this)));
|
| +
|
| + token_service_.IssueAllTokensForAccount(
|
| + kAccountId,
|
| + "access_token",
|
| + base::Time::Now() + base::TimeDelta::FromHours(1));
|
| +
|
| + SendValidLoginResponse();
|
| +
|
| + // Failed GetUserInfo call should result in a service error.
|
| + EXPECT_CALL(*this, OnFlagsFetched(AccountServiceFlagFetcher::SERVICE_ERROR,
|
| + std::vector<std::string>()));
|
| + SendFailedGetUserInfoResponse();
|
| +}
|
| +
|
| +TEST_F(AccountServiceFlagFetcherTest, DestroyFetcher) {
|
| + token_service_.UpdateCredentials(kAccountId, "refresh_token");
|
| +
|
| + // When the fetcher is destroyed before the request completes, OnFlagsFetched
|
| + // should not be called.
|
| + EXPECT_CALL(*this, OnFlagsFetched(testing::_, testing::_)).Times(0);
|
| +
|
| + AccountServiceFlagFetcher fetcher(
|
| + kAccountId,
|
| + &token_service_,
|
| + request_context_.get(),
|
| + base::Bind(&AccountServiceFlagFetcherTest::OnFlagsFetched,
|
| + base::Unretained(this)));
|
| +
|
| + token_service_.IssueAllTokensForAccount(
|
| + kAccountId,
|
| + "access_token",
|
| + base::Time::Now() + base::TimeDelta::FromHours(1));
|
| +
|
| + SendValidLoginResponse();
|
| + // Do not send a GetUserInfo response, but make sure the request is there.
|
| + GetGetUserInfoURLFetcher();
|
| +}
|
|
|