online_attempt_unittest.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
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_auth_fetcher_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_("", "", "", "", "", false), 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 RunThreadTest(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::RunThreadTest, 140 attempt_, &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::RunThreadTest, 167 attempt_, &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, HostedLoginRejected) { 179 LoginFailure error( 180 LoginFailure::FromNetworkAuthFailure( 181 GoogleServiceAuthError( 182 GoogleServiceAuthError::HOSTED_NOT_ALLOWED))); 183 TestingProfile profile; 184 185 EXPECT_CALL(*(resolver_.get()), Resolve()) 186 .WillOnce(Invoke(OnlineAttemptTest::Quit)) 187 .RetiresOnSaturation(); 188 189 // This is how we inject fake URLFetcher objects, with a factory. 190 MockFactory<HostedFetcher> factory; 191 URLFetcher::set_factory(&factory); 192 193 TestAttemptState local_state("", "", "", "", "", true); 194 attempt_ = new OnlineAttempt(&local_state, resolver_.get()); 195 BrowserThread::PostTask( 196 BrowserThread::IO, FROM_HERE, 197 NewRunnableFunction(&OnlineAttemptTest::RunThreadTest, 198 attempt_, &profile)); 199 200 MessageLoop::current()->Run(); 201 202 EXPECT_EQ(error, local_state.online_outcome()); 203 EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED, 204 local_state.online_outcome().reason()); 205 URLFetcher::set_factory(NULL); 206} 207 208TEST_F(OnlineAttemptTest, FullLogin) { 209 TestingProfile profile; 210 211 EXPECT_CALL(*(resolver_.get()), Resolve()) 212 .WillOnce(Invoke(OnlineAttemptTest::Quit)) 213 .RetiresOnSaturation(); 214 215 // This is how we inject fake URLFetcher objects, with a factory. 216 MockFactory<SuccessFetcher> factory; 217 URLFetcher::set_factory(&factory); 218 219 TestAttemptState local_state("", "", "", "", "", true); 220 attempt_ = new OnlineAttempt(&local_state, resolver_.get()); 221 BrowserThread::PostTask( 222 BrowserThread::IO, FROM_HERE, 223 NewRunnableFunction(&OnlineAttemptTest::RunThreadTest, 224 attempt_, &profile)); 225 226 MessageLoop::current()->Run(); 227 228 EXPECT_EQ(LoginFailure::None(), local_state.online_outcome()); 229 URLFetcher::set_factory(NULL); 230} 231 232TEST_F(OnlineAttemptTest, LoginNetFailure) { 233 RunFailureTest( 234 GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET)); 235} 236 237TEST_F(OnlineAttemptTest, LoginDenied) { 238 RunFailureTest( 239 GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 240} 241 242TEST_F(OnlineAttemptTest, LoginAccountDisabled) { 243 RunFailureTest( 244 GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED)); 245} 246 247TEST_F(OnlineAttemptTest, LoginAccountDeleted) { 248 RunFailureTest( 249 GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED)); 250} 251 252TEST_F(OnlineAttemptTest, LoginServiceUnavailable) { 253 RunFailureTest( 254 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); 255} 256 257TEST_F(OnlineAttemptTest, CaptchaErrorOutputted) { 258 GoogleServiceAuthError auth_error = 259 GoogleServiceAuthError::FromCaptchaChallenge( 260 "CCTOKEN", 261 GURL("http://www.google.com/accounts/Captcha?ctoken=CCTOKEN"), 262 GURL("http://www.google.com/login/captcha")); 263 RunFailureTest(auth_error); 264} 265 266TEST_F(OnlineAttemptTest, TwoFactorSuccess) { 267 EXPECT_CALL(*(resolver_.get()), Resolve()) 268 .Times(1) 269 .RetiresOnSaturation(); 270 GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR); 271 BrowserThread::PostTask( 272 BrowserThread::IO, FROM_HERE, 273 NewRunnableMethod(attempt_.get(), 274 &OnlineAttempt::OnClientLoginFailure, 275 error)); 276 277 // Force IO thread to finish tasks so I can verify |state_|. 278 io_thread_.Stop(); 279 EXPECT_TRUE(GoogleServiceAuthError::None() == 280 state_.online_outcome().error()); 281 EXPECT_TRUE(GaiaAuthConsumer::ClientLoginResult() == state_.credentials()); 282} 283 284} // namespace chromeos 285