Home | History | Annotate | Download | only in login
      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:
     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() {
     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 
    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 
    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 
    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 
    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 
    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 
    231 TEST_F(OnlineAttemptTest, LoginNetFailure) {
    232   RunFailureTest(
    233       GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET));
    234 }
    235 
    236 TEST_F(OnlineAttemptTest, LoginDenied) {
    237   RunFailureTest(
    238       GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
    239 }
    240 
    241 TEST_F(OnlineAttemptTest, LoginAccountDisabled) {
    242   RunFailureTest(
    243       GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED));
    244 }
    245 
    246 TEST_F(OnlineAttemptTest, LoginAccountDeleted) {
    247   RunFailureTest(
    248       GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED));
    249 }
    250 
    251 TEST_F(OnlineAttemptTest, LoginServiceUnavailable) {
    252   RunFailureTest(
    253       GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
    254 }
    255 
    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 
    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