• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <string>
6 
7 #include "base/memory/ref_counted.h"
8 #include "base/message_loop.h"
9 #include "chrome/browser/chromeos/cros/mock_library_loader.h"
10 #include "chrome/browser/chromeos/login/auth_attempt_state.h"
11 #include "chrome/browser/chromeos/login/online_attempt.h"
12 #include "chrome/browser/chromeos/login/mock_auth_attempt_state_resolver.h"
13 #include "chrome/browser/chromeos/login/mock_url_fetchers.h"
14 #include "chrome/browser/chromeos/login/test_attempt_state.h"
15 #include "chrome/common/net/gaia/gaia_auth_consumer.h"
16 #include "chrome/common/net/gaia/gaia_auth_fetcher_unittest.h"
17 #include "chrome/test/testing_profile.h"
18 #include "content/browser/browser_thread.h"
19 #include "googleurl/src/gurl.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 
23 using ::testing::AnyNumber;
24 using ::testing::Invoke;
25 using ::testing::Return;
26 using ::testing::_;
27 
28 namespace chromeos {
29 
30 class OnlineAttemptTest : public ::testing::Test {
31  public:
OnlineAttemptTest()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 
~OnlineAttemptTest()40   virtual ~OnlineAttemptTest() {}
41 
SetUp()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 
TearDown()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 
RunFailureTest(const GoogleServiceAuthError & error)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 
CancelLogin(OnlineAttempt * auth)81   void CancelLogin(OnlineAttempt* auth) {
82     BrowserThread::PostTask(
83         BrowserThread::IO,
84         FROM_HERE,
85         NewRunnableMethod(auth,
86                           &OnlineAttempt::CancelClientLogin));
87   }
88 
Quit()89   static void Quit() {
90     BrowserThread::PostTask(
91         BrowserThread::UI, FROM_HERE, new MessageLoop::QuitTask());
92   }
93 
RunThreadTest()94   static void RunThreadTest() {
95     MessageLoop::current()->RunAllPending();
96   }
97 
98   MessageLoop message_loop_;
99   BrowserThread ui_thread_;
100   BrowserThread io_thread_;
101   TestAttemptState state_;
102   scoped_ptr<MockAuthAttemptStateResolver> resolver_;
103   scoped_refptr<OnlineAttempt> attempt_;
104 };
105 
TEST_F(OnlineAttemptTest,LoginSuccess)106 TEST_F(OnlineAttemptTest, LoginSuccess) {
107   GaiaAuthConsumer::ClientLoginResult result;
108   EXPECT_CALL(*(resolver_.get()), Resolve())
109       .Times(1)
110       .RetiresOnSaturation();
111 
112   BrowserThread::PostTask(
113       BrowserThread::IO, FROM_HERE,
114       NewRunnableMethod(attempt_.get(),
115                         &OnlineAttempt::OnClientLoginSuccess,
116                         result));
117   // Force IO thread to finish tasks so I can verify |state_|.
118   io_thread_.Stop();
119   EXPECT_TRUE(result == state_.credentials());
120 }
121 
TEST_F(OnlineAttemptTest,LoginCancelRetry)122 TEST_F(OnlineAttemptTest, LoginCancelRetry) {
123   GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
124   TestingProfile profile;
125 
126   EXPECT_CALL(*(resolver_.get()), Resolve())
127       .WillOnce(Invoke(OnlineAttemptTest::Quit))
128       .RetiresOnSaturation();
129 
130   // This is how we inject fake URLFetcher objects, with a factory.
131   // This factory creates fake URLFetchers that Start() a fake fetch attempt
132   // and then come back on the IO thread saying they've been canceled.
133   MockFactory<GotCanceledFetcher> factory;
134   URLFetcher::set_factory(&factory);
135 
136   attempt_->Initiate(&profile);
137   BrowserThread::PostTask(
138       BrowserThread::IO, FROM_HERE,
139       NewRunnableFunction(&OnlineAttemptTest::RunThreadTest));
140 
141   MessageLoop::current()->Run();
142 
143   EXPECT_TRUE(error == state_.online_outcome().error());
144   EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED,
145             state_.online_outcome().reason());
146   URLFetcher::set_factory(NULL);
147 }
148 
TEST_F(OnlineAttemptTest,LoginTimeout)149 TEST_F(OnlineAttemptTest, LoginTimeout) {
150   LoginFailure error(LoginFailure::LOGIN_TIMED_OUT);
151   TestingProfile profile;
152 
153   EXPECT_CALL(*(resolver_.get()), Resolve())
154       .WillOnce(Invoke(OnlineAttemptTest::Quit))
155       .RetiresOnSaturation();
156 
157   // This is how we inject fake URLFetcher objects, with a factory.
158   // This factory creates fake URLFetchers that Start() a fake fetch attempt
159   // and then come back on the IO thread saying they've been canceled.
160   MockFactory<ExpectCanceledFetcher> factory;
161   URLFetcher::set_factory(&factory);
162 
163   attempt_->Initiate(&profile);
164   BrowserThread::PostTask(
165       BrowserThread::IO, FROM_HERE,
166       NewRunnableFunction(&OnlineAttemptTest::RunThreadTest));
167 
168   // Post a task to cancel the login attempt.
169   CancelLogin(attempt_.get());
170 
171   MessageLoop::current()->Run();
172 
173   EXPECT_EQ(LoginFailure::LOGIN_TIMED_OUT, state_.online_outcome().reason());
174   URLFetcher::set_factory(NULL);
175 }
176 
TEST_F(OnlineAttemptTest,HostedLoginRejected)177 TEST_F(OnlineAttemptTest, HostedLoginRejected) {
178   LoginFailure error(
179       LoginFailure::FromNetworkAuthFailure(
180           GoogleServiceAuthError(
181               GoogleServiceAuthError::HOSTED_NOT_ALLOWED)));
182   TestingProfile profile;
183 
184   EXPECT_CALL(*(resolver_.get()), Resolve())
185       .WillOnce(Invoke(OnlineAttemptTest::Quit))
186       .RetiresOnSaturation();
187 
188   // This is how we inject fake URLFetcher objects, with a factory.
189   MockFactory<HostedFetcher> factory;
190   URLFetcher::set_factory(&factory);
191 
192   TestAttemptState local_state("", "", "", "", "", true);
193   attempt_ = new OnlineAttempt(&local_state, resolver_.get());
194   attempt_->Initiate(&profile);
195   BrowserThread::PostTask(
196       BrowserThread::IO, FROM_HERE,
197       NewRunnableFunction(&OnlineAttemptTest::RunThreadTest));
198 
199   MessageLoop::current()->Run();
200 
201   EXPECT_EQ(error, local_state.online_outcome());
202   EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED,
203             local_state.online_outcome().reason());
204   URLFetcher::set_factory(NULL);
205 }
206 
TEST_F(OnlineAttemptTest,FullLogin)207 TEST_F(OnlineAttemptTest, FullLogin) {
208   TestingProfile profile;
209 
210   EXPECT_CALL(*(resolver_.get()), Resolve())
211       .WillOnce(Invoke(OnlineAttemptTest::Quit))
212       .RetiresOnSaturation();
213 
214   // This is how we inject fake URLFetcher objects, with a factory.
215   MockFactory<SuccessFetcher> factory;
216   URLFetcher::set_factory(&factory);
217 
218   TestAttemptState local_state("", "", "", "", "", true);
219   attempt_ = new OnlineAttempt(&local_state, resolver_.get());
220   attempt_->Initiate(&profile);
221   BrowserThread::PostTask(
222       BrowserThread::IO, FROM_HERE,
223       NewRunnableFunction(&OnlineAttemptTest::RunThreadTest));
224 
225   MessageLoop::current()->Run();
226 
227   EXPECT_EQ(LoginFailure::None(), local_state.online_outcome());
228   URLFetcher::set_factory(NULL);
229 }
230 
TEST_F(OnlineAttemptTest,LoginNetFailure)231 TEST_F(OnlineAttemptTest, LoginNetFailure) {
232   RunFailureTest(
233       GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET));
234 }
235 
TEST_F(OnlineAttemptTest,LoginDenied)236 TEST_F(OnlineAttemptTest, LoginDenied) {
237   RunFailureTest(
238       GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
239 }
240 
TEST_F(OnlineAttemptTest,LoginAccountDisabled)241 TEST_F(OnlineAttemptTest, LoginAccountDisabled) {
242   RunFailureTest(
243       GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED));
244 }
245 
TEST_F(OnlineAttemptTest,LoginAccountDeleted)246 TEST_F(OnlineAttemptTest, LoginAccountDeleted) {
247   RunFailureTest(
248       GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED));
249 }
250 
TEST_F(OnlineAttemptTest,LoginServiceUnavailable)251 TEST_F(OnlineAttemptTest, LoginServiceUnavailable) {
252   RunFailureTest(
253       GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
254 }
255 
TEST_F(OnlineAttemptTest,CaptchaErrorOutputted)256 TEST_F(OnlineAttemptTest, CaptchaErrorOutputted) {
257   GoogleServiceAuthError auth_error =
258       GoogleServiceAuthError::FromCaptchaChallenge(
259           "CCTOKEN",
260           GURL("http://www.google.com/accounts/Captcha?ctoken=CCTOKEN"),
261           GURL("http://www.google.com/login/captcha"));
262   RunFailureTest(auth_error);
263 }
264 
TEST_F(OnlineAttemptTest,TwoFactorSuccess)265 TEST_F(OnlineAttemptTest, TwoFactorSuccess) {
266   EXPECT_CALL(*(resolver_.get()), Resolve())
267       .Times(1)
268       .RetiresOnSaturation();
269   GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR);
270   BrowserThread::PostTask(
271       BrowserThread::IO, FROM_HERE,
272       NewRunnableMethod(attempt_.get(),
273                         &OnlineAttempt::OnClientLoginFailure,
274                         error));
275 
276   // Force IO thread to finish tasks so I can verify |state_|.
277   io_thread_.Stop();
278   EXPECT_TRUE(GoogleServiceAuthError::None() ==
279               state_.online_outcome().error());
280   EXPECT_TRUE(GaiaAuthConsumer::ClientLoginResult() == state_.credentials());
281 }
282 
283 }  // namespace chromeos
284