Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2012 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/bind.h"
      8 #include "base/memory/ref_counted.h"
      9 #include "base/run_loop.h"
     10 #include "chrome/browser/chromeos/login/auth_attempt_state.h"
     11 #include "chrome/browser/chromeos/login/mock_auth_attempt_state_resolver.h"
     12 #include "chrome/browser/chromeos/login/mock_url_fetchers.h"
     13 #include "chrome/browser/chromeos/login/online_attempt.h"
     14 #include "chrome/browser/chromeos/login/test_attempt_state.h"
     15 #include "chrome/browser/chromeos/login/user.h"
     16 #include "chrome/test/base/testing_profile.h"
     17 #include "content/public/browser/browser_thread.h"
     18 #include "content/public/test/test_browser_thread_bundle.h"
     19 #include "google_apis/gaia/gaia_auth_consumer.h"
     20 #include "google_apis/gaia/mock_url_fetcher_factory.h"
     21 #include "testing/gmock/include/gmock/gmock.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 #include "url/gurl.h"
     24 
     25 using ::testing::AnyNumber;
     26 using ::testing::Invoke;
     27 using ::testing::Return;
     28 using ::testing::_;
     29 using content::BrowserThread;
     30 
     31 namespace chromeos {
     32 
     33 class OnlineAttemptTest : public testing::Test {
     34  public:
     35   OnlineAttemptTest()
     36       : state_(UserContext(), "", "", User::USER_TYPE_REGULAR, false),
     37         attempt_(new OnlineAttempt(&state_, &resolver_)) {
     38   }
     39 
     40   void RunFailureTest(const GoogleServiceAuthError& error) {
     41     EXPECT_CALL(resolver_, Resolve())
     42         .Times(1)
     43         .RetiresOnSaturation();
     44 
     45     BrowserThread::PostTask(
     46         BrowserThread::UI, FROM_HERE,
     47         base::Bind(&OnlineAttempt::OnClientLoginFailure,
     48                    attempt_->weak_factory_.GetWeakPtr(),
     49                    error));
     50     // Force UI thread to finish tasks so I can verify |state_|.
     51     base::RunLoop().RunUntilIdle();
     52     EXPECT_TRUE(error == state_.online_outcome().error());
     53   }
     54 
     55   void CancelLogin(OnlineAttempt* auth) {
     56     BrowserThread::PostTask(
     57         BrowserThread::UI, FROM_HERE,
     58         base::Bind(&OnlineAttempt::CancelClientLogin,
     59                    auth->weak_factory_.GetWeakPtr()));
     60   }
     61 
     62   content::TestBrowserThreadBundle thread_bundle_;
     63   TestAttemptState state_;
     64   MockAuthAttemptStateResolver resolver_;
     65   scoped_ptr<OnlineAttempt> attempt_;
     66 };
     67 
     68 TEST_F(OnlineAttemptTest, LoginSuccess) {
     69   EXPECT_CALL(resolver_, Resolve())
     70       .Times(1)
     71       .RetiresOnSaturation();
     72 
     73   BrowserThread::PostTask(
     74       BrowserThread::UI, FROM_HERE,
     75       base::Bind(&OnlineAttempt::OnClientLoginSuccess,
     76                  attempt_->weak_factory_.GetWeakPtr(),
     77                  GaiaAuthConsumer::ClientLoginResult()));
     78   // Force UI thread to finish tasks so I can verify |state_|.
     79   base::RunLoop().RunUntilIdle();
     80 }
     81 
     82 TEST_F(OnlineAttemptTest, LoginCancelRetry) {
     83   GoogleServiceAuthError error(GoogleServiceAuthError::REQUEST_CANCELED);
     84   TestingProfile profile;
     85 
     86   base::RunLoop run_loop;
     87   EXPECT_CALL(resolver_, Resolve())
     88       .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
     89       .RetiresOnSaturation();
     90 
     91   // This is how we inject fake URLFetcher objects, with a factory.
     92   // This factory creates fake URLFetchers that Start() a fake fetch attempt
     93   // and then come back on the UI thread saying they've been canceled.
     94   MockURLFetcherFactory<GotCanceledFetcher> factory;
     95 
     96   attempt_->Initiate(&profile);
     97 
     98   run_loop.Run();
     99 
    100   EXPECT_TRUE(error == state_.online_outcome().error());
    101   EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED,
    102             state_.online_outcome().reason());
    103 }
    104 
    105 TEST_F(OnlineAttemptTest, LoginTimeout) {
    106   LoginFailure error(LoginFailure::LOGIN_TIMED_OUT);
    107   TestingProfile profile;
    108 
    109   base::RunLoop run_loop;
    110   EXPECT_CALL(resolver_, Resolve())
    111       .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
    112       .RetiresOnSaturation();
    113 
    114   // This is how we inject fake URLFetcher objects, with a factory.
    115   // This factory creates fake URLFetchers that Start() a fake fetch attempt
    116   // and then come back on the UI thread saying they've been canceled.
    117   MockURLFetcherFactory<ExpectCanceledFetcher> factory;
    118 
    119   attempt_->Initiate(&profile);
    120 
    121   // Post a task to cancel the login attempt.
    122   CancelLogin(attempt_.get());
    123 
    124   run_loop.Run();
    125 
    126   EXPECT_EQ(LoginFailure::LOGIN_TIMED_OUT, state_.online_outcome().reason());
    127 }
    128 
    129 TEST_F(OnlineAttemptTest, HostedLoginRejected) {
    130   LoginFailure error(
    131       LoginFailure::FromNetworkAuthFailure(
    132           GoogleServiceAuthError(
    133               GoogleServiceAuthError::HOSTED_NOT_ALLOWED)));
    134   TestingProfile profile;
    135 
    136   base::RunLoop run_loop;
    137   EXPECT_CALL(resolver_, Resolve())
    138       .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
    139       .RetiresOnSaturation();
    140 
    141   // This is how we inject fake URLFetcher objects, with a factory.
    142   MockURLFetcherFactory<HostedFetcher> factory;
    143 
    144   TestAttemptState local_state(UserContext(), "", "",
    145                                User::USER_TYPE_REGULAR, true);
    146   attempt_.reset(new OnlineAttempt(&local_state, &resolver_));
    147   attempt_->Initiate(&profile);
    148 
    149   run_loop.Run();
    150 
    151   EXPECT_EQ(error, local_state.online_outcome());
    152   EXPECT_EQ(LoginFailure::NETWORK_AUTH_FAILED,
    153             local_state.online_outcome().reason());
    154 }
    155 
    156 TEST_F(OnlineAttemptTest, FullLogin) {
    157   TestingProfile profile;
    158 
    159   base::RunLoop run_loop;
    160   EXPECT_CALL(resolver_, Resolve())
    161       .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit))
    162       .RetiresOnSaturation();
    163 
    164   // This is how we inject fake URLFetcher objects, with a factory.
    165   MockURLFetcherFactory<SuccessFetcher> factory;
    166 
    167   TestAttemptState local_state(UserContext(), "", "",
    168                                User::USER_TYPE_REGULAR, true);
    169   attempt_.reset(new OnlineAttempt(&local_state, &resolver_));
    170   attempt_->Initiate(&profile);
    171 
    172   run_loop.Run();
    173 
    174   EXPECT_EQ(LoginFailure::LoginFailureNone(), local_state.online_outcome());
    175 }
    176 
    177 TEST_F(OnlineAttemptTest, LoginNetFailure) {
    178   RunFailureTest(
    179       GoogleServiceAuthError::FromConnectionError(net::ERR_CONNECTION_RESET));
    180 }
    181 
    182 TEST_F(OnlineAttemptTest, LoginDenied) {
    183   RunFailureTest(
    184       GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
    185 }
    186 
    187 TEST_F(OnlineAttemptTest, LoginAccountDisabled) {
    188   RunFailureTest(
    189       GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED));
    190 }
    191 
    192 TEST_F(OnlineAttemptTest, LoginAccountDeleted) {
    193   RunFailureTest(
    194       GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED));
    195 }
    196 
    197 TEST_F(OnlineAttemptTest, LoginServiceUnavailable) {
    198   RunFailureTest(
    199       GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
    200 }
    201 
    202 TEST_F(OnlineAttemptTest, CaptchaErrorOutputted) {
    203   GoogleServiceAuthError auth_error =
    204       GoogleServiceAuthError::FromClientLoginCaptchaChallenge(
    205           "CCTOKEN",
    206           GURL("http://accounts.google.com/Captcha?ctoken=CCTOKEN"),
    207           GURL("http://www.google.com/login/captcha"));
    208   RunFailureTest(auth_error);
    209 }
    210 
    211 TEST_F(OnlineAttemptTest, TwoFactorSuccess) {
    212   EXPECT_CALL(resolver_, Resolve())
    213       .Times(1)
    214       .RetiresOnSaturation();
    215   GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR);
    216   BrowserThread::PostTask(
    217       BrowserThread::UI, FROM_HERE,
    218       base::Bind(&OnlineAttempt::OnClientLoginFailure,
    219                  attempt_->weak_factory_.GetWeakPtr(),
    220                  error));
    221 
    222   // Force UI thread to finish tasks so I can verify |state_|.
    223   base::RunLoop().RunUntilIdle();
    224   EXPECT_TRUE(GoogleServiceAuthError::AuthErrorNone() ==
    225               state_.online_outcome().error());
    226 }
    227 
    228 }  // namespace chromeos
    229