| // Copyright (c) 2012 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 "base/bind.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/run_loop.h" |
| #include "chrome/browser/chromeos/login/auth_attempt_state.h" |
| #include "chrome/browser/chromeos/login/mock_auth_attempt_state_resolver.h" |
| #include "chrome/browser/chromeos/login/mock_url_fetchers.h" |
| #include "chrome/browser/chromeos/login/online_attempt.h" |
| #include "chrome/browser/chromeos/login/test_attempt_state.h" |
| #include "chrome/browser/chromeos/login/user.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "google_apis/gaia/gaia_auth_consumer.h" |
| #include "google_apis/gaia/mock_url_fetcher_factory.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| using ::testing::AnyNumber; |
| using ::testing::Invoke; |
| using ::testing::Return; |
| using ::testing::_; |
| using content::BrowserThread; |
| |
| namespace chromeos { |
| |
| class OnlineAttemptTest : public testing::Test { |
| public: |
| OnlineAttemptTest() |
| : state_(UserContext(), "", "", "", User::USER_TYPE_REGULAR, false), |
| attempt_(new OnlineAttempt(&state_, &resolver_)) { |
| } |
| |
| void RunFailureTest(const GoogleServiceAuthError& error) { |
| EXPECT_CALL(resolver_, Resolve()) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&OnlineAttempt::OnClientLoginFailure, |
| attempt_->weak_factory_.GetWeakPtr(), |
| error)); |
| // Force UI thread to finish tasks so I can verify |state_|. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(error == state_.online_outcome().error()); |
| } |
| |
| void CancelLogin(OnlineAttempt* auth) { |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&OnlineAttempt::CancelClientLogin, |
| auth->weak_factory_.GetWeakPtr())); |
| } |
| |
| content::TestBrowserThreadBundle thread_bundle_; |
| TestAttemptState state_; |
| MockAuthAttemptStateResolver resolver_; |
| scoped_ptr<OnlineAttempt> attempt_; |
| }; |
| |
| TEST_F(OnlineAttemptTest, LoginSuccess) { |
| EXPECT_CALL(resolver_, Resolve()) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&OnlineAttempt::OnClientLoginSuccess, |
| attempt_->weak_factory_.GetWeakPtr(), |
| GaiaAuthConsumer::ClientLoginResult())); |
| // Force UI thread to finish tasks so I can verify |state_|. |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| TEST_F(OnlineAttemptTest, LoginCancelRetry) { |
| GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); |
| TestingProfile profile; |
| |
| base::RunLoop run_loop; |
| EXPECT_CALL(resolver_, Resolve()) |
| .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit)) |
| .RetiresOnSaturation(); |
| |
| // This is how we inject fake URLFetcher objects, with a factory. |
| // This factory creates fake URLFetchers that Start() a fake fetch attempt |
| // and then come back on the UI thread saying they've been canceled. |
| MockURLFetcherFactory<GotCanceledFetcher> factory; |
| |
| attempt_->Initiate(&profile); |
| |
| run_loop.Run(); |
| |
| EXPECT_TRUE(error == state_.online_outcome().error()); |
| EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED, |
| state_.online_outcome().reason()); |
| } |
| |
| TEST_F(OnlineAttemptTest, LoginTimeout) { |
| LoginFailure error(LoginFailure::LOGIN_TIMED_OUT); |
| TestingProfile profile; |
| |
| base::RunLoop run_loop; |
| EXPECT_CALL(resolver_, Resolve()) |
| .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit)) |
| .RetiresOnSaturation(); |
| |
| // This is how we inject fake URLFetcher objects, with a factory. |
| // This factory creates fake URLFetchers that Start() a fake fetch attempt |
| // and then come back on the UI thread saying they've been canceled. |
| MockURLFetcherFactory<ExpectCanceledFetcher> factory; |
| |
| attempt_->Initiate(&profile); |
| |
| // Post a task to cancel the login attempt. |
| CancelLogin(attempt_.get()); |
| |
| run_loop.Run(); |
| |
| EXPECT_EQ(LoginFailure::LOGIN_TIMED_OUT, state_.online_outcome().reason()); |
| } |
| |
| TEST_F(OnlineAttemptTest, HostedLoginRejected) { |
| LoginFailure error( |
| LoginFailure::FromNetworkAuthFailure( |
| GoogleServiceAuthError( |
| GoogleServiceAuthError::HOSTED_NOT_ALLOWED))); |
| TestingProfile profile; |
| |
| base::RunLoop run_loop; |
| EXPECT_CALL(resolver_, Resolve()) |
| .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit)) |
| .RetiresOnSaturation(); |
| |
| // This is how we inject fake URLFetcher objects, with a factory. |
| MockURLFetcherFactory<HostedFetcher> factory; |
| |
| TestAttemptState local_state(UserContext(), "", "", "", |
| User::USER_TYPE_REGULAR, true); |
| attempt_.reset(new OnlineAttempt(&local_state, &resolver_)); |
| attempt_->Initiate(&profile); |
| |
| run_loop.Run(); |
| |
| EXPECT_EQ(error, local_state.online_outcome()); |
| EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED, |
| local_state.online_outcome().reason()); |
| } |
| |
| TEST_F(OnlineAttemptTest, FullLogin) { |
| TestingProfile profile; |
| |
| base::RunLoop run_loop; |
| EXPECT_CALL(resolver_, Resolve()) |
| .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit)) |
| .RetiresOnSaturation(); |
| |
| // This is how we inject fake URLFetcher objects, with a factory. |
| MockURLFetcherFactory<SuccessFetcher> factory; |
| |
| TestAttemptState local_state(UserContext(), "", "", "", |
| User::USER_TYPE_REGULAR, true); |
| attempt_.reset(new OnlineAttempt(&local_state, &resolver_)); |
| attempt_->Initiate(&profile); |
| |
| run_loop.Run(); |
| |
| EXPECT_EQ(LoginFailure::LoginFailureNone(), local_state.online_outcome()); |
| } |
| |
| TEST_F(OnlineAttemptTest, LoginNetFailure) { |
| RunFailureTest( |
| GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET)); |
| } |
| |
| TEST_F(OnlineAttemptTest, LoginDenied) { |
| RunFailureTest( |
| GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); |
| } |
| |
| TEST_F(OnlineAttemptTest, LoginAccountDisabled) { |
| RunFailureTest( |
| GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED)); |
| } |
| |
| TEST_F(OnlineAttemptTest, LoginAccountDeleted) { |
| RunFailureTest( |
| GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED)); |
| } |
| |
| TEST_F(OnlineAttemptTest, LoginServiceUnavailable) { |
| RunFailureTest( |
| GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); |
| } |
| |
| TEST_F(OnlineAttemptTest, CaptchaErrorOutputted) { |
| GoogleServiceAuthError auth_error = |
| GoogleServiceAuthError::FromClientLoginCaptchaChallenge( |
| "CCTOKEN", |
| GURL("http://accounts.google.com/Captcha?ctoken=CCTOKEN"), |
| GURL("http://www.google.com/login/captcha")); |
| RunFailureTest(auth_error); |
| } |
| |
| TEST_F(OnlineAttemptTest, TwoFactorSuccess) { |
| EXPECT_CALL(resolver_, Resolve()) |
| .Times(1) |
| .RetiresOnSaturation(); |
| GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR); |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&OnlineAttempt::OnClientLoginFailure, |
| attempt_->weak_factory_.GetWeakPtr(), |
| error)); |
| |
| // Force UI thread to finish tasks so I can verify |state_|. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(GoogleServiceAuthError::AuthErrorNone() == |
| state_.online_outcome().error()); |
| } |
| |
| } // namespace chromeos |