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