1 // Copyright (c) 2011 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 // A complete set of unit tests for GaiaAuthFetcher. 6 // Originally ported from GoogleAuthenticator tests. 7 8 #include <string> 9 10 #include "base/message_loop.h" 11 #include "base/string_util.h" 12 #include "chrome/common/net/gaia/gaia_auth_consumer.h" 13 #include "chrome/common/net/gaia/gaia_auth_fetcher.h" 14 #include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h" 15 #include "chrome/common/net/gaia/google_service_auth_error.h" 16 #include "chrome/common/net/http_return.h" 17 #include "chrome/common/net/test_url_fetcher_factory.h" 18 #include "chrome/common/net/url_fetcher.h" 19 #include "chrome/test/testing_profile.h" 20 #include "googleurl/src/gurl.h" 21 #include "net/base/net_errors.h" 22 #include "net/url_request/url_request_status.h" 23 #include "testing/gmock/include/gmock/gmock.h" 24 #include "testing/gtest/include/gtest/gtest.h" 25 26 using ::testing::_; 27 28 MockFetcher::MockFetcher(bool success, 29 const GURL& url, 30 const std::string& results, 31 URLFetcher::RequestType request_type, 32 URLFetcher::Delegate* d) 33 : URLFetcher(url, request_type, d), 34 success_(success), 35 url_(url), 36 results_(results) {} 37 38 MockFetcher::~MockFetcher() {} 39 40 void MockFetcher::Start() { 41 net::URLRequestStatus::Status code; 42 int http_code; 43 if (success_) { 44 http_code = RC_REQUEST_OK; 45 code = net::URLRequestStatus::SUCCESS; 46 } else { 47 http_code = RC_FORBIDDEN; 48 code = net::URLRequestStatus::FAILED; 49 } 50 51 net::URLRequestStatus status(code, 0); 52 delegate()->OnURLFetchComplete(NULL, 53 url_, 54 status, 55 http_code, 56 ResponseCookies(), 57 results_); 58 } 59 60 61 class GaiaAuthFetcherTest : public testing::Test { 62 public: 63 GaiaAuthFetcherTest() 64 : client_login_source_(GaiaAuthFetcher::kClientLoginUrl), 65 issue_auth_token_source_(GaiaAuthFetcher::kIssueAuthTokenUrl) {} 66 67 void RunParsingTest(const std::string& data, 68 const std::string& sid, 69 const std::string& lsid, 70 const std::string& token) { 71 std::string out_sid; 72 std::string out_lsid; 73 std::string out_token; 74 75 GaiaAuthFetcher::ParseClientLoginResponse(data, 76 &out_sid, 77 &out_lsid, 78 &out_token); 79 EXPECT_EQ(lsid, out_lsid); 80 EXPECT_EQ(sid, out_sid); 81 EXPECT_EQ(token, out_token); 82 } 83 84 void RunErrorParsingTest(const std::string& data, 85 const std::string& error, 86 const std::string& error_url, 87 const std::string& captcha_url, 88 const std::string& captcha_token) { 89 std::string out_error; 90 std::string out_error_url; 91 std::string out_captcha_url; 92 std::string out_captcha_token; 93 94 GaiaAuthFetcher::ParseClientLoginFailure(data, 95 &out_error, 96 &out_error_url, 97 &out_captcha_url, 98 &out_captcha_token); 99 EXPECT_EQ(error, out_error); 100 EXPECT_EQ(error_url, out_error_url); 101 EXPECT_EQ(captcha_url, out_captcha_url); 102 EXPECT_EQ(captcha_token, out_captcha_token); 103 } 104 105 ResponseCookies cookies_; 106 GURL client_login_source_; 107 GURL issue_auth_token_source_; 108 TestingProfile profile_; 109 protected: 110 MessageLoop message_loop_; 111 }; 112 113 class MockGaiaConsumer : public GaiaAuthConsumer { 114 public: 115 MockGaiaConsumer() {} 116 ~MockGaiaConsumer() {} 117 118 MOCK_METHOD1(OnClientLoginSuccess, void(const ClientLoginResult& result)); 119 MOCK_METHOD2(OnIssueAuthTokenSuccess, void(const std::string& service, 120 const std::string& token)); 121 MOCK_METHOD1(OnClientLoginFailure, 122 void(const GoogleServiceAuthError& error)); 123 MOCK_METHOD2(OnIssueAuthTokenFailure, void(const std::string& service, 124 const GoogleServiceAuthError& error)); 125 }; 126 127 TEST_F(GaiaAuthFetcherTest, ErrorComparator) { 128 GoogleServiceAuthError expected_error = 129 GoogleServiceAuthError::FromConnectionError(-101); 130 131 GoogleServiceAuthError matching_error = 132 GoogleServiceAuthError::FromConnectionError(-101); 133 134 EXPECT_TRUE(expected_error == matching_error); 135 136 expected_error = GoogleServiceAuthError::FromConnectionError(6); 137 138 EXPECT_FALSE(expected_error == matching_error); 139 140 expected_error = GoogleServiceAuthError(GoogleServiceAuthError::NONE); 141 142 EXPECT_FALSE(expected_error == matching_error); 143 144 matching_error = GoogleServiceAuthError(GoogleServiceAuthError::NONE); 145 146 EXPECT_TRUE(expected_error == matching_error); 147 } 148 149 TEST_F(GaiaAuthFetcherTest, LoginNetFailure) { 150 int error_no = net::ERR_CONNECTION_RESET; 151 net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no); 152 153 GoogleServiceAuthError expected_error = 154 GoogleServiceAuthError::FromConnectionError(error_no); 155 156 MockGaiaConsumer consumer; 157 EXPECT_CALL(consumer, OnClientLoginFailure(expected_error)) 158 .Times(1); 159 160 GaiaAuthFetcher auth(&consumer, std::string(), 161 profile_.GetRequestContext()); 162 163 auth.OnURLFetchComplete(NULL, 164 client_login_source_, 165 status, 166 0, 167 cookies_, 168 std::string()); 169 } 170 171 TEST_F(GaiaAuthFetcherTest, TokenNetFailure) { 172 int error_no = net::ERR_CONNECTION_RESET; 173 net::URLRequestStatus status(net::URLRequestStatus::FAILED, error_no); 174 175 GoogleServiceAuthError expected_error = 176 GoogleServiceAuthError::FromConnectionError(error_no); 177 178 MockGaiaConsumer consumer; 179 EXPECT_CALL(consumer, OnIssueAuthTokenFailure(_, expected_error)) 180 .Times(1); 181 182 GaiaAuthFetcher auth(&consumer, std::string(), 183 profile_.GetRequestContext()); 184 185 auth.OnURLFetchComplete(NULL, 186 issue_auth_token_source_, 187 status, 188 0, 189 cookies_, 190 std::string()); 191 } 192 193 194 TEST_F(GaiaAuthFetcherTest, LoginDenied) { 195 std::string data("Error=BadAuthentication"); 196 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 197 198 GoogleServiceAuthError expected_error( 199 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 200 201 MockGaiaConsumer consumer; 202 EXPECT_CALL(consumer, OnClientLoginFailure(expected_error)) 203 .Times(1); 204 205 GaiaAuthFetcher auth(&consumer, std::string(), 206 profile_.GetRequestContext()); 207 auth.OnURLFetchComplete(NULL, 208 client_login_source_, 209 status, 210 RC_FORBIDDEN, 211 cookies_, 212 data); 213 } 214 215 TEST_F(GaiaAuthFetcherTest, ParseRequest) { 216 RunParsingTest("SID=sid\nLSID=lsid\nAuth=auth\n", "sid", "lsid", "auth"); 217 RunParsingTest("LSID=lsid\nSID=sid\nAuth=auth\n", "sid", "lsid", "auth"); 218 RunParsingTest("SID=sid\nLSID=lsid\nAuth=auth", "sid", "lsid", "auth"); 219 RunParsingTest("SID=sid\nAuth=auth\n", "sid", "", "auth"); 220 RunParsingTest("LSID=lsid\nAuth=auth\n", "", "lsid", "auth"); 221 RunParsingTest("\nAuth=auth\n", "", "", "auth"); 222 RunParsingTest("SID=sid", "sid", "", ""); 223 } 224 225 TEST_F(GaiaAuthFetcherTest, ParseErrorRequest) { 226 RunErrorParsingTest("Url=U\n" 227 "Error=E\n" 228 "CaptchaToken=T\n" 229 "CaptchaUrl=C\n", "E", "U", "C", "T"); 230 RunErrorParsingTest("CaptchaToken=T\n" 231 "Error=E\n" 232 "Url=U\n" 233 "CaptchaUrl=C\n", "E", "U", "C", "T"); 234 RunErrorParsingTest("\n\n\nCaptchaToken=T\n" 235 "\nError=E\n" 236 "\nUrl=U\n" 237 "CaptchaUrl=C\n", "E", "U", "C", "T"); 238 } 239 240 241 TEST_F(GaiaAuthFetcherTest, OnlineLogin) { 242 std::string data("SID=sid\nLSID=lsid\nAuth=auth\n"); 243 244 GaiaAuthConsumer::ClientLoginResult result; 245 result.lsid = "lsid"; 246 result.sid = "sid"; 247 result.token = "auth"; 248 result.data = data; 249 250 MockGaiaConsumer consumer; 251 EXPECT_CALL(consumer, OnClientLoginSuccess(result)) 252 .Times(1); 253 254 GaiaAuthFetcher auth(&consumer, std::string(), 255 profile_.GetRequestContext()); 256 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 257 auth.OnURLFetchComplete(NULL, 258 client_login_source_, 259 status, 260 RC_REQUEST_OK, 261 cookies_, 262 data); 263 } 264 265 TEST_F(GaiaAuthFetcherTest, WorkingIssueAuthToken) { 266 MockGaiaConsumer consumer; 267 EXPECT_CALL(consumer, OnIssueAuthTokenSuccess(_, "token")) 268 .Times(1); 269 270 GaiaAuthFetcher auth(&consumer, std::string(), 271 profile_.GetRequestContext()); 272 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 273 auth.OnURLFetchComplete(NULL, 274 issue_auth_token_source_, 275 status, 276 RC_REQUEST_OK, 277 cookies_, 278 "token"); 279 } 280 281 TEST_F(GaiaAuthFetcherTest, CheckTwoFactorResponse) { 282 std::string response = 283 base::StringPrintf("Error=BadAuthentication\n%s\n", 284 GaiaAuthFetcher::kSecondFactor); 285 EXPECT_TRUE(GaiaAuthFetcher::IsSecondFactorSuccess(response)); 286 } 287 288 TEST_F(GaiaAuthFetcherTest, CheckNormalErrorCode) { 289 std::string response = "Error=BadAuthentication\n"; 290 EXPECT_FALSE(GaiaAuthFetcher::IsSecondFactorSuccess(response)); 291 } 292 293 TEST_F(GaiaAuthFetcherTest, TwoFactorLogin) { 294 std::string response = base::StringPrintf("Error=BadAuthentication\n%s\n", 295 GaiaAuthFetcher::kSecondFactor); 296 297 GoogleServiceAuthError error = 298 GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR); 299 300 MockGaiaConsumer consumer; 301 EXPECT_CALL(consumer, OnClientLoginFailure(error)) 302 .Times(1); 303 304 GaiaAuthFetcher auth(&consumer, std::string(), 305 profile_.GetRequestContext()); 306 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 307 auth.OnURLFetchComplete(NULL, 308 client_login_source_, 309 status, 310 RC_FORBIDDEN, 311 cookies_, 312 response); 313 } 314 315 TEST_F(GaiaAuthFetcherTest, CaptchaParse) { 316 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 317 std::string data = "Url=http://www.google.com/login/captcha\n" 318 "Error=CaptchaRequired\n" 319 "CaptchaToken=CCTOKEN\n" 320 "CaptchaUrl=Captcha?ctoken=CCTOKEN\n"; 321 GoogleServiceAuthError error = 322 GaiaAuthFetcher::GenerateAuthError(data, status); 323 324 std::string token = "CCTOKEN"; 325 GURL image_url("http://www.google.com/accounts/Captcha?ctoken=CCTOKEN"); 326 GURL unlock_url("http://www.google.com/login/captcha"); 327 328 EXPECT_EQ(error.state(), GoogleServiceAuthError::CAPTCHA_REQUIRED); 329 EXPECT_EQ(error.captcha().token, token); 330 EXPECT_EQ(error.captcha().image_url, image_url); 331 EXPECT_EQ(error.captcha().unlock_url, unlock_url); 332 } 333 334 TEST_F(GaiaAuthFetcherTest, AccountDeletedError) { 335 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 336 std::string data = "Error=AccountDeleted\n"; 337 GoogleServiceAuthError error = 338 GaiaAuthFetcher::GenerateAuthError(data, status); 339 EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DELETED); 340 } 341 342 TEST_F(GaiaAuthFetcherTest, AccountDisabledError) { 343 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 344 std::string data = "Error=AccountDisabled\n"; 345 GoogleServiceAuthError error = 346 GaiaAuthFetcher::GenerateAuthError(data, status); 347 EXPECT_EQ(error.state(), GoogleServiceAuthError::ACCOUNT_DISABLED); 348 } 349 350 TEST_F(GaiaAuthFetcherTest,BadAuthenticationError) { 351 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 352 std::string data = "Error=BadAuthentication\n"; 353 GoogleServiceAuthError error = 354 GaiaAuthFetcher::GenerateAuthError(data, status); 355 EXPECT_EQ(error.state(), GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 356 } 357 358 TEST_F(GaiaAuthFetcherTest,IncomprehensibleError) { 359 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 360 std::string data = "Error=Gobbledygook\n"; 361 GoogleServiceAuthError error = 362 GaiaAuthFetcher::GenerateAuthError(data, status); 363 EXPECT_EQ(error.state(), GoogleServiceAuthError::SERVICE_UNAVAILABLE); 364 } 365 366 TEST_F(GaiaAuthFetcherTest,ServiceUnavailableError) { 367 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0); 368 std::string data = "Error=ServiceUnavailable\n"; 369 GoogleServiceAuthError error = 370 GaiaAuthFetcher::GenerateAuthError(data, status); 371 EXPECT_EQ(error.state(), GoogleServiceAuthError::SERVICE_UNAVAILABLE); 372 } 373 374 TEST_F(GaiaAuthFetcherTest, FullLogin) { 375 MockGaiaConsumer consumer; 376 EXPECT_CALL(consumer, OnClientLoginSuccess(_)) 377 .Times(1); 378 379 TestingProfile profile; 380 381 MockFactory<MockFetcher> factory; 382 URLFetcher::set_factory(&factory); 383 384 GaiaAuthFetcher auth(&consumer, std::string(), 385 profile_.GetRequestContext()); 386 auth.StartClientLogin("username", 387 "password", 388 "service", 389 std::string(), 390 std::string(), 391 GaiaAuthFetcher::HostedAccountsAllowed); 392 393 URLFetcher::set_factory(NULL); 394 } 395 396 TEST_F(GaiaAuthFetcherTest, FullLoginFailure) { 397 MockGaiaConsumer consumer; 398 EXPECT_CALL(consumer, OnClientLoginFailure(_)) 399 .Times(1); 400 401 TestingProfile profile; 402 403 MockFactory<MockFetcher> factory; 404 URLFetcher::set_factory(&factory); 405 factory.set_success(false); 406 407 GaiaAuthFetcher auth(&consumer, std::string(), 408 profile_.GetRequestContext()); 409 auth.StartClientLogin("username", 410 "password", 411 "service", 412 std::string(), 413 std::string(), 414 GaiaAuthFetcher::HostedAccountsAllowed); 415 416 URLFetcher::set_factory(NULL); 417 } 418 419 TEST_F(GaiaAuthFetcherTest, ClientFetchPending) { 420 MockGaiaConsumer consumer; 421 EXPECT_CALL(consumer, OnClientLoginSuccess(_)) 422 .Times(1); 423 424 TestingProfile profile; 425 TestURLFetcherFactory factory; 426 URLFetcher::set_factory(&factory); 427 428 GaiaAuthFetcher auth(&consumer, std::string(), 429 profile_.GetRequestContext()); 430 auth.StartClientLogin("username", 431 "password", 432 "service", 433 std::string(), 434 std::string(), 435 GaiaAuthFetcher::HostedAccountsAllowed); 436 437 URLFetcher::set_factory(NULL); 438 EXPECT_TRUE(auth.HasPendingFetch()); 439 auth.OnURLFetchComplete( 440 NULL, 441 client_login_source_, 442 net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0), 443 RC_REQUEST_OK, 444 cookies_, 445 "SID=sid\nLSID=lsid\nAuth=auth\n"); 446 EXPECT_FALSE(auth.HasPendingFetch()); 447 } 448 449 TEST_F(GaiaAuthFetcherTest, FullTokenSuccess) { 450 MockGaiaConsumer consumer; 451 EXPECT_CALL(consumer, OnIssueAuthTokenSuccess("service", "token")) 452 .Times(1); 453 454 TestingProfile profile; 455 TestURLFetcherFactory factory; 456 URLFetcher::set_factory(&factory); 457 458 GaiaAuthFetcher auth(&consumer, std::string(), 459 profile_.GetRequestContext()); 460 auth.StartIssueAuthToken("sid", "lsid", "service"); 461 462 URLFetcher::set_factory(NULL); 463 EXPECT_TRUE(auth.HasPendingFetch()); 464 auth.OnURLFetchComplete( 465 NULL, 466 issue_auth_token_source_, 467 net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0), 468 RC_REQUEST_OK, 469 cookies_, 470 "token"); 471 EXPECT_FALSE(auth.HasPendingFetch()); 472 } 473 474 TEST_F(GaiaAuthFetcherTest, FullTokenFailure) { 475 MockGaiaConsumer consumer; 476 EXPECT_CALL(consumer, OnIssueAuthTokenFailure("service", _)) 477 .Times(1); 478 479 TestingProfile profile; 480 TestURLFetcherFactory factory; 481 URLFetcher::set_factory(&factory); 482 483 GaiaAuthFetcher auth(&consumer, std::string(), 484 profile_.GetRequestContext()); 485 auth.StartIssueAuthToken("sid", "lsid", "service"); 486 487 URLFetcher::set_factory(NULL); 488 EXPECT_TRUE(auth.HasPendingFetch()); 489 auth.OnURLFetchComplete( 490 NULL, 491 issue_auth_token_source_, 492 net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0), 493 RC_FORBIDDEN, 494 cookies_, 495 ""); 496 EXPECT_FALSE(auth.HasPendingFetch()); 497 } 498