// Copyright (c) 2011 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. // // A complete set of unit tests for GaiaAuthFetcher. // Originally ported from GoogleAuthenticator tests. #include <string> #include "base/message_loop.h" #include "base/string_util.h" #include "chrome/common/net/gaia/gaia_auth_consumer.h" #include "chrome/common/net/gaia/gaia_auth_fetcher.h" #include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h" #include "chrome/common/net/gaia/google_service_auth_error.h" #include "chrome/common/net/http_return.h" #include "chrome/common/net/test_url_fetcher_factory.h" #include "chrome/common/net/url_fetcher.h" #include "chrome/test/testing_profile.h" #include "googleurl/src/gurl.h" #include "net/base/net_errors.h" #include "net/url_request/url_request_status.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::_; MockFetcher::MockFetcher(bool success, const GURL& url, const std::string& results, URLFetcher::RequestType request_type, URLFetcher::Delegate* d) : URLFetcher(url, request_type, d), success_(success), url_(url), results_(results) {} MockFetcher::~MockFetcher() {} void MockFetcher::Start() { net::URLRequestStatus::Status code; int http_code; if (success_) { http_code = RC_REQUEST_OK; code = net::URLRequestStatus::SUCCESS; } else { http_code = RC_FORBIDDEN; code = net::URLRequestStatus::FAILED; } net::URLRequestStatus status(code, 0); delegate()->OnURLFetchComplete(NULL, url_, status, http_code, ResponseCookies(), results_); } class GaiaAuthFetcherTest : public testing::Test { public: GaiaAuthFetcherTest() : client_login_source_(GaiaAuthFetcher::kClientLoginUrl), issue_auth_token_source_(GaiaAuthFetcher::kIssueAuthTokenUrl) {} void RunParsingTest(const std::string& data, const std::string& sid, const std::string& lsid, const std::string& token) { std::string out_sid; std::string out_lsid; std::string out_token; GaiaAuthFetcher::ParseClientLoginResponse(data, &out_sid, &out_lsid, &out_token); EXPECT_EQ(lsid, out_lsid); EXPECT_EQ(sid, out_sid); EXPECT_EQ(token, out_token); } void RunErrorParsingTest(const std::string& data, const std::string& error, const std::string& error_url, const std::string& captcha_url, const std::string& captcha_token) { std::string out_error; std::string out_error_url; std::string out_captcha_url; std::string out_captcha_token; GaiaAuthFetcher::ParseClientLoginFailure(data, &out_error, &out_error_url, &out_captcha_url, &out_captcha_token); EXPECT_EQ(error, out_error); EXPECT_EQ(error_url, out_error_url); EXPECT_EQ(captcha_url, out_captcha_url); EXPECT_EQ(captcha_token, out_captcha_token); } ResponseCookies cookies_; GURL client_login_source_; GURL issue_auth_token_source_; TestingProfile profile_; protected: MessageLoop message_loop_; }; class MockGaiaConsumer : public GaiaAuthConsumer { public: MockGaiaConsumer() {} ~MockGaiaConsumer() {} MOCK_METHOD1(OnClientLoginSuccess, void(const ClientLoginResult& result)); MOCK_METHOD2(OnIssueAuthTokenSuccess, void(const std::string& service, const std::string& token)); MOCK_METHOD1(OnClientLoginFailure, void(const GoogleServiceAuthError& error)); MOCK_METHOD2(OnIssueAuthTokenFailure, void(const std::string& service, const GoogleServiceAuthError& error)); }; TEST_F(GaiaAuthFetcherTest, ErrorComparator) { GoogleServiceAuthError expected_error = GoogleServiceAuthError::FromConnectionError(-101); GoogleServiceAuthError matching_error = GoogleServiceAuthError::FromConnectionError(-101); EXPECT_TRUE(expected_error == matching_error); expected_error = GoogleServiceAuthError::FromConnectionError(6); EXPECT_FALSE(expected_error == matching_error); expected_error = GoogleServiceAuthError(GoogleServiceAuthError::NONE); EXPECT_FALSE(expected_error == matching_error); matching_error = GoogleServiceAuthError(GoogleServiceAuthError::NONE); EXPECT_TRUE(expected_error == matching_error); } TEST_F(GaiaAuthFetcherTest, LoginNetFailure) { int error_no = net::ERR_CONNECTION_RESET; net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no); GoogleServiceAuthError expected_error = GoogleServiceAuthError::FromConnectionError(error_no); MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginFailure(expected_error)) .Times(1); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); auth.OnURLFetchComplete(NULL, client_login_source_, status, 0, cookies_, std::string()); } TEST_F(GaiaAuthFetcherTest, TokenNetFailure) { int error_no = net::ERR_CONNECTION_RESET; net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no); GoogleServiceAuthError expected_error = GoogleServiceAuthError::FromConnectionError(error_no); MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnIssueAuthTokenFailure(_, expected_error)) .Times(1); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); auth.OnURLFetchComplete(NULL, issue_auth_token_source_, status, 0, cookies_, std::string()); } TEST_F(GaiaAuthFetcherTest, LoginDenied) { std::string data("Error=BadAuthentication"); net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); GoogleServiceAuthError expected_error( GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginFailure(expected_error)) .Times(1); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); auth.OnURLFetchComplete(NULL, client_login_source_, status, RC_FORBIDDEN, cookies_, data); } TEST_F(GaiaAuthFetcherTest, ParseRequest) { RunParsingTest("SID=sid\nLSID=lsid\nAuth=auth\n", "sid", "lsid", "auth"); RunParsingTest("LSID=lsid\nSID=sid\nAuth=auth\n", "sid", "lsid", "auth"); RunParsingTest("SID=sid\nLSID=lsid\nAuth=auth", "sid", "lsid", "auth"); RunParsingTest("SID=sid\nAuth=auth\n", "sid", "", "auth"); RunParsingTest("LSID=lsid\nAuth=auth\n", "", "lsid", "auth"); RunParsingTest("\nAuth=auth\n", "", "", "auth"); RunParsingTest("SID=sid", "sid", "", ""); } TEST_F(GaiaAuthFetcherTest, ParseErrorRequest) { RunErrorParsingTest("Url=U\n" "Error=E\n" "CaptchaToken=T\n" "CaptchaUrl=C\n", "E", "U", "C", "T"); RunErrorParsingTest("CaptchaToken=T\n" "Error=E\n" "Url=U\n" "CaptchaUrl=C\n", "E", "U", "C", "T"); RunErrorParsingTest("\n\n\nCaptchaToken=T\n" "\nError=E\n" "\nUrl=U\n" "CaptchaUrl=C\n", "E", "U", "C", "T"); } TEST_F(GaiaAuthFetcherTest, OnlineLogin) { std::string data("SID=sid\nLSID=lsid\nAuth=auth\n"); GaiaAuthConsumer::ClientLoginResult result; result.lsid = "lsid"; result.sid = "sid"; result.token = "auth"; result.data = data; MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginSuccess(result)) .Times(1); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); auth.OnURLFetchComplete(NULL, client_login_source_, status, RC_REQUEST_OK, cookies_, data); } TEST_F(GaiaAuthFetcherTest, WorkingIssueAuthToken) { MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnIssueAuthTokenSuccess(_, "token")) .Times(1); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); auth.OnURLFetchComplete(NULL, issue_auth_token_source_, status, RC_REQUEST_OK, cookies_, "token"); } TEST_F(GaiaAuthFetcherTest, CheckTwoFactorResponse) { std::string response = base::StringPrintf("Error=BadAuthentication\n%s\n", GaiaAuthFetcher::kSecondFactor); EXPECT_TRUE(GaiaAuthFetcher::IsSecondFactorSuccess(response)); } TEST_F(GaiaAuthFetcherTest, CheckNormalErrorCode) { std::string response = "Error=BadAuthentication\n"; EXPECT_FALSE(GaiaAuthFetcher::IsSecondFactorSuccess(response)); } TEST_F(GaiaAuthFetcherTest, TwoFactorLogin) { std::string response = base::StringPrintf("Error=BadAuthentication\n%s\n", GaiaAuthFetcher::kSecondFactor); GoogleServiceAuthError error = GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginFailure(error)) .Times(1); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); auth.OnURLFetchComplete(NULL, client_login_source_, status, RC_FORBIDDEN, cookies_, response); } TEST_F(GaiaAuthFetcherTest, CaptchaParse) { net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); std::string data = "Url=http://www.google.com/login/captcha\n" "Error=CaptchaRequired\n" "CaptchaToken=CCTOKEN\n" "CaptchaUrl=Captcha?ctoken=CCTOKEN\n"; GoogleServiceAuthError error = GaiaAuthFetcher::GenerateAuthError(data, status); std::string token = "CCTOKEN"; GURL image_url("http://www.google.com/accounts/Captcha?ctoken=CCTOKEN"); GURL unlock_url("http://www.google.com/login/captcha"); EXPECT_EQ(error.state(), GoogleServiceAuthError::CAPTCHA_REQUIRED); EXPECT_EQ(error.captcha().token, token); EXPECT_EQ(error.captcha().image_url, image_url); EXPECT_EQ(error.captcha().unlock_url, unlock_url); } TEST_F(GaiaAuthFetcherTest, AccountDeletedError) { net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); std::string data = "Error=AccountDeleted\n"; GoogleServiceAuthError error = GaiaAuthFetcher::GenerateAuthError(data, status); EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DELETED); } TEST_F(GaiaAuthFetcherTest, AccountDisabledError) { net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); std::string data = "Error=AccountDisabled\n"; GoogleServiceAuthError error = GaiaAuthFetcher::GenerateAuthError(data, status); EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DISABLED); } TEST_F(GaiaAuthFetcherTest,BadAuthenticationError) { net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); std::string data = "Error=BadAuthentication\n"; GoogleServiceAuthError error = GaiaAuthFetcher::GenerateAuthError(data, status); EXPECT_EQ(error.state(), GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); } TEST_F(GaiaAuthFetcherTest,IncomprehensibleError) { net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); std::string data = "Error=Gobbledygook\n"; GoogleServiceAuthError error = GaiaAuthFetcher::GenerateAuthError(data, status); EXPECT_EQ(error.state(), GoogleServiceAuthError::SERVICE_UNAVAILABLE); } TEST_F(GaiaAuthFetcherTest,ServiceUnavailableError) { net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); std::string data = "Error=ServiceUnavailable\n"; GoogleServiceAuthError error = GaiaAuthFetcher::GenerateAuthError(data, status); EXPECT_EQ(error.state(), GoogleServiceAuthError::SERVICE_UNAVAILABLE); } TEST_F(GaiaAuthFetcherTest, FullLogin) { MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginSuccess(_)) .Times(1); TestingProfile profile; MockFactory<MockFetcher> factory; URLFetcher::set_factory(&factory); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); auth.StartClientLogin("username", "password", "service", std::string(), std::string(), GaiaAuthFetcher::HostedAccountsAllowed); URLFetcher::set_factory(NULL); } TEST_F(GaiaAuthFetcherTest, FullLoginFailure) { MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginFailure(_)) .Times(1); TestingProfile profile; MockFactory<MockFetcher> factory; URLFetcher::set_factory(&factory); factory.set_success(false); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); auth.StartClientLogin("username", "password", "service", std::string(), std::string(), GaiaAuthFetcher::HostedAccountsAllowed); URLFetcher::set_factory(NULL); } TEST_F(GaiaAuthFetcherTest, ClientFetchPending) { MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnClientLoginSuccess(_)) .Times(1); TestingProfile profile; TestURLFetcherFactory factory; URLFetcher::set_factory(&factory); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); auth.StartClientLogin("username", "password", "service", std::string(), std::string(), GaiaAuthFetcher::HostedAccountsAllowed); URLFetcher::set_factory(NULL); EXPECT_TRUE(auth.HasPendingFetch()); auth.OnURLFetchComplete( NULL, client_login_source_, net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0), RC_REQUEST_OK, cookies_, "SID=sid\nLSID=lsid\nAuth=auth\n"); EXPECT_FALSE(auth.HasPendingFetch()); } TEST_F(GaiaAuthFetcherTest, FullTokenSuccess) { MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnIssueAuthTokenSuccess("service", "token")) .Times(1); TestingProfile profile; TestURLFetcherFactory factory; URLFetcher::set_factory(&factory); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); auth.StartIssueAuthToken("sid", "lsid", "service"); URLFetcher::set_factory(NULL); EXPECT_TRUE(auth.HasPendingFetch()); auth.OnURLFetchComplete( NULL, issue_auth_token_source_, net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0), RC_REQUEST_OK, cookies_, "token"); EXPECT_FALSE(auth.HasPendingFetch()); } TEST_F(GaiaAuthFetcherTest, FullTokenFailure) { MockGaiaConsumer consumer; EXPECT_CALL(consumer, OnIssueAuthTokenFailure("service", _)) .Times(1); TestingProfile profile; TestURLFetcherFactory factory; URLFetcher::set_factory(&factory); GaiaAuthFetcher auth(&consumer, std::string(), profile_.GetRequestContext()); auth.StartIssueAuthToken("sid", "lsid", "service"); URLFetcher::set_factory(NULL); EXPECT_TRUE(auth.HasPendingFetch()); auth.OnURLFetchComplete( NULL, issue_auth_token_source_, net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0), RC_FORBIDDEN, cookies_, ""); EXPECT_FALSE(auth.HasPendingFetch()); }