online_attempt_unittest.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2010 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#include <string> 6 7#include "base/message_loop.h" 8#include "base/ref_counted.h" 9#include "chrome/browser/browser_thread.h" 10#include "chrome/browser/chromeos/cros/mock_library_loader.h" 11#include "chrome/browser/chromeos/login/auth_attempt_state.h" 12#include "chrome/browser/chromeos/login/online_attempt.h" 13#include "chrome/browser/chromeos/login/mock_auth_attempt_state_resolver.h" 14#include "chrome/browser/chromeos/login/mock_url_fetchers.h" 15#include "chrome/browser/chromeos/login/test_attempt_state.h" 16#include "chrome/common/net/gaia/gaia_auth_consumer.h" 17#include "chrome/common/net/gaia/gaia_authenticator2_unittest.h" 18#include "chrome/test/testing_profile.h" 19#include "googleurl/src/gurl.h" 20#include "testing/gmock/include/gmock/gmock.h" 21#include "testing/gtest/include/gtest/gtest.h" 22 23using ::testing::AnyNumber; 24using ::testing::Invoke; 25using ::testing::Return; 26using ::testing::_; 27 28namespace chromeos { 29 30class OnlineAttemptTest : public ::testing::Test { 31 public: 32 OnlineAttemptTest() 33 : message_loop_(MessageLoop::TYPE_UI), 34 ui_thread_(BrowserThread::UI, &message_loop_), 35 io_thread_(BrowserThread::IO), 36 state_("", "", "", "", ""), 37 resolver_(new MockAuthAttemptStateResolver) { 38 } 39 40 virtual ~OnlineAttemptTest() {} 41 42 virtual void SetUp() { 43 CrosLibrary::TestApi* test_api = CrosLibrary::Get()->GetTestApi(); 44 45 MockLibraryLoader* loader = new MockLibraryLoader(); 46 ON_CALL(*loader, Load(_)) 47 .WillByDefault(Return(true)); 48 EXPECT_CALL(*loader, Load(_)) 49 .Times(AnyNumber()); 50 51 // Passes ownership of |loader| to CrosLibrary. 52 test_api->SetLibraryLoader(loader, true); 53 54 attempt_ = new OnlineAttempt(&state_, resolver_.get()); 55 56 io_thread_.Start(); 57 } 58 59 virtual void TearDown() { 60 // Prevent bogus gMock leak check from firing. 61 chromeos::CrosLibrary::TestApi* test_api = 62 chromeos::CrosLibrary::Get()->GetTestApi(); 63 test_api->SetLibraryLoader(NULL, false); 64 } 65 66 void RunFailureTest(const GoogleServiceAuthError& error) { 67 EXPECT_CALL(*(resolver_.get()), Resolve()) 68 .Times(1) 69 .RetiresOnSaturation(); 70 71 BrowserThread::PostTask( 72 BrowserThread::IO, FROM_HERE, 73 NewRunnableMethod(attempt_.get(), 74 &OnlineAttempt::OnClientLoginFailure, 75 error)); 76 // Force IO thread to finish tasks so I can verify |state_|. 77 io_thread_.Stop(); 78 EXPECT_TRUE(error == state_.online_outcome().error()); 79 } 80 81 void CancelLogin(OnlineAttempt* auth) { 82 BrowserThread::PostTask( 83 BrowserThread::IO, 84 FROM_HERE, 85 NewRunnableMethod(auth, 86 &OnlineAttempt::CancelClientLogin)); 87 } 88 89 static void Quit() { 90 BrowserThread::PostTask( 91 BrowserThread::UI, FROM_HERE, new MessageLoop::QuitTask()); 92 } 93 94 static void RunCancelTest(OnlineAttempt* attempt, Profile* profile) { 95 attempt->Initiate(profile); 96 MessageLoop::current()->RunAllPending(); 97 } 98 99 MessageLoop message_loop_; 100 BrowserThread ui_thread_; 101 BrowserThread io_thread_; 102 TestAttemptState state_; 103 scoped_ptr<MockAuthAttemptStateResolver> resolver_; 104 scoped_refptr<OnlineAttempt> attempt_; 105}; 106 107TEST_F(OnlineAttemptTest, LoginSuccess) { 108 GaiaAuthConsumer::ClientLoginResult result; 109 EXPECT_CALL(*(resolver_.get()), Resolve()) 110 .Times(1) 111 .RetiresOnSaturation(); 112 113 BrowserThread::PostTask( 114 BrowserThread::IO, FROM_HERE, 115 NewRunnableMethod(attempt_.get(), 116 &OnlineAttempt::OnClientLoginSuccess, 117 result)); 118 // Force IO thread to finish tasks so I can verify |state_|. 119 io_thread_.Stop(); 120 EXPECT_TRUE(result == state_.credentials()); 121} 122 123TEST_F(OnlineAttemptTest, LoginCancelRetry) { 124 GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED); 125 TestingProfile profile; 126 127 EXPECT_CALL(*(resolver_.get()), Resolve()) 128 .WillOnce(Invoke(OnlineAttemptTest::Quit)) 129 .RetiresOnSaturation(); 130 131 // This is how we inject fake URLFetcher objects, with a factory. 132 // This factory creates fake URLFetchers that Start() a fake fetch attempt 133 // and then come back on the IO thread saying they've been canceled. 134 MockFactory<GotCanceledFetcher> factory; 135 URLFetcher::set_factory(&factory); 136 137 BrowserThread::PostTask( 138 BrowserThread::IO, FROM_HERE, 139 NewRunnableFunction(&OnlineAttemptTest::RunCancelTest, 140 attempt_.get(), &profile)); 141 142 MessageLoop::current()->Run(); 143 144 EXPECT_TRUE(error == state_.online_outcome().error()); 145 EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED, 146 state_.online_outcome().reason()); 147 URLFetcher::set_factory(NULL); 148} 149 150TEST_F(OnlineAttemptTest, LoginTimeout) { 151 LoginFailure error(LoginFailure::LOGIN_TIMED_OUT); 152 TestingProfile profile; 153 154 EXPECT_CALL(*(resolver_.get()), Resolve()) 155 .WillOnce(Invoke(OnlineAttemptTest::Quit)) 156 .RetiresOnSaturation(); 157 158 // This is how we inject fake URLFetcher objects, with a factory. 159 // This factory creates fake URLFetchers that Start() a fake fetch attempt 160 // and then come back on the IO thread saying they've been canceled. 161 MockFactory<ExpectCanceledFetcher> factory; 162 URLFetcher::set_factory(&factory); 163 164 BrowserThread::PostTask( 165 BrowserThread::IO, FROM_HERE, 166 NewRunnableFunction(&OnlineAttemptTest::RunCancelTest, 167 attempt_.get(), &profile)); 168 169 // Post a task to cancel the login attempt. 170 CancelLogin(attempt_.get()); 171 172 MessageLoop::current()->Run(); 173 174 EXPECT_EQ(LoginFailure::LOGIN_TIMED_OUT, state_.online_outcome().reason()); 175 URLFetcher::set_factory(NULL); 176} 177 178TEST_F(OnlineAttemptTest, LoginNetFailure) { 179 RunFailureTest( 180 GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET)); 181} 182 183TEST_F(OnlineAttemptTest, LoginDenied) { 184 RunFailureTest( 185 GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 186} 187 188TEST_F(OnlineAttemptTest, LoginAccountDisabled) { 189 RunFailureTest( 190 GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED)); 191} 192 193TEST_F(OnlineAttemptTest, LoginAccountDeleted) { 194 RunFailureTest( 195 GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED)); 196} 197 198TEST_F(OnlineAttemptTest, LoginServiceUnavailable) { 199 RunFailureTest( 200 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); 201} 202 203TEST_F(OnlineAttemptTest, CaptchaErrorOutputted) { 204 GoogleServiceAuthError auth_error = 205 GoogleServiceAuthError::FromCaptchaChallenge( 206 "CCTOKEN", 207 GURL("http://www.google.com/accounts/Captcha?ctoken=CCTOKEN"), 208 GURL("http://www.google.com/login/captcha")); 209 RunFailureTest(auth_error); 210} 211 212TEST_F(OnlineAttemptTest, TwoFactorSuccess) { 213 EXPECT_CALL(*(resolver_.get()), Resolve()) 214 .Times(1) 215 .RetiresOnSaturation(); 216 GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR); 217 BrowserThread::PostTask( 218 BrowserThread::IO, FROM_HERE, 219 NewRunnableMethod(attempt_.get(), 220 &OnlineAttempt::OnClientLoginFailure, 221 error)); 222 223 // Force IO thread to finish tasks so I can verify |state_|. 224 io_thread_.Stop(); 225 EXPECT_TRUE(GoogleServiceAuthError::None() == 226 state_.online_outcome().error()); 227 EXPECT_TRUE(GaiaAuthConsumer::ClientLoginResult() == state_.credentials()); 228} 229 230} // namespace chromeos 231