signin_error_controller_unittest.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
1// Copyright 2014 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 "components/signin/core/browser/signin_error_controller.h" 6 7#include <functional> 8 9#include "base/memory/scoped_ptr.h" 10#include "components/signin/core/browser/fake_auth_status_provider.h" 11#include "testing/gtest/include/gtest/gtest.h" 12 13static const char kTestAccountId[] = "testuser@test.com"; 14static const char kOtherTestAccountId[] = "otheruser@test.com"; 15 16class SigninErrorControllerTest : public testing::Test { 17 public: 18 virtual void SetUp() OVERRIDE { 19 error_controller_.reset(new SigninErrorController()); 20 } 21 22 scoped_ptr<SigninErrorController> error_controller_; 23}; 24 25TEST_F(SigninErrorControllerTest, NoErrorAuthStatusProviders) { 26 scoped_ptr<FakeAuthStatusProvider> provider; 27 28 // No providers. 29 ASSERT_FALSE(error_controller_->HasError()); 30 31 // Add a provider. 32 provider.reset(new FakeAuthStatusProvider(error_controller_.get())); 33 ASSERT_FALSE(error_controller_->HasError()); 34 35 // Remove the provider. 36 provider.reset(); 37 ASSERT_FALSE(error_controller_->HasError()); 38} 39 40TEST_F(SigninErrorControllerTest, ErrorAuthStatusProvider) { 41 scoped_ptr<FakeAuthStatusProvider> provider; 42 scoped_ptr<FakeAuthStatusProvider> error_provider; 43 44 provider.reset(new FakeAuthStatusProvider(error_controller_.get())); 45 ASSERT_FALSE(error_controller_->HasError()); 46 47 error_provider.reset(new FakeAuthStatusProvider(error_controller_.get())); 48 error_provider->SetAuthError(kTestAccountId, GoogleServiceAuthError( 49 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 50 ASSERT_TRUE(error_controller_->HasError()); 51 52 error_provider.reset(); 53 ASSERT_FALSE(error_controller_->HasError()); 54 55 provider.reset(); 56 // All providers should be removed now. 57 ASSERT_FALSE(error_controller_->HasError()); 58} 59 60TEST_F(SigninErrorControllerTest, AuthStatusProviderErrorTransition) { 61 scoped_ptr<FakeAuthStatusProvider> provider0( 62 new FakeAuthStatusProvider(error_controller_.get())); 63 scoped_ptr<FakeAuthStatusProvider> provider1( 64 new FakeAuthStatusProvider(error_controller_.get())); 65 66 ASSERT_FALSE(error_controller_->HasError()); 67 provider0->SetAuthError( 68 kTestAccountId, 69 GoogleServiceAuthError( 70 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 71 ASSERT_TRUE(error_controller_->HasError()); 72 provider1->SetAuthError( 73 kTestAccountId, 74 GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED)); 75 ASSERT_TRUE(error_controller_->HasError()); 76 77 // Now resolve the auth errors - the menu item should go away. 78 provider0->SetAuthError(kTestAccountId, 79 GoogleServiceAuthError::AuthErrorNone()); 80 ASSERT_TRUE(error_controller_->HasError()); 81 provider1->SetAuthError(kTestAccountId, 82 GoogleServiceAuthError::AuthErrorNone()); 83 ASSERT_FALSE(error_controller_->HasError()); 84 85 provider0.reset(); 86 provider1.reset(); 87 ASSERT_FALSE(error_controller_->HasError()); 88} 89 90TEST_F(SigninErrorControllerTest, AuthStatusProviderAccountTransition) { 91 scoped_ptr<FakeAuthStatusProvider> provider0( 92 new FakeAuthStatusProvider(error_controller_.get())); 93 scoped_ptr<FakeAuthStatusProvider> provider1( 94 new FakeAuthStatusProvider(error_controller_.get())); 95 96 ASSERT_FALSE(error_controller_->HasError()); 97 98 provider0->SetAuthError( 99 kTestAccountId, 100 GoogleServiceAuthError( 101 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 102 provider1->SetAuthError( 103 kOtherTestAccountId, 104 GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 105 ASSERT_TRUE(error_controller_->HasError()); 106 ASSERT_STREQ(kTestAccountId, 107 error_controller_->error_account_id().c_str()); 108 109 // Swap providers reporting errors. 110 provider1->set_error_without_status_change( 111 GoogleServiceAuthError( 112 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 113 provider0->set_error_without_status_change( 114 GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 115 error_controller_->AuthStatusChanged(); 116 ASSERT_TRUE(error_controller_->HasError()); 117 ASSERT_STREQ(kOtherTestAccountId, 118 error_controller_->error_account_id().c_str()); 119 120 // Now resolve the auth errors - the menu item should go away. 121 provider0->set_error_without_status_change( 122 GoogleServiceAuthError::AuthErrorNone()); 123 provider1->set_error_without_status_change( 124 GoogleServiceAuthError::AuthErrorNone()); 125 error_controller_->AuthStatusChanged(); 126 ASSERT_FALSE(error_controller_->HasError()); 127 128 provider0.reset(); 129 provider1.reset(); 130 ASSERT_FALSE(error_controller_->HasError()); 131} 132 133// Verify that SigninErrorController handles errors properly. 134TEST_F(SigninErrorControllerTest, AuthStatusEnumerateAllErrors) { 135 typedef struct { 136 GoogleServiceAuthError::State error_state; 137 bool is_error; 138 } ErrorTableEntry; 139 140 ErrorTableEntry table[] = { 141 { GoogleServiceAuthError::NONE, false }, 142 { GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, true }, 143 { GoogleServiceAuthError::USER_NOT_SIGNED_UP, true }, 144 { GoogleServiceAuthError::CONNECTION_FAILED, false }, 145 { GoogleServiceAuthError::CAPTCHA_REQUIRED, true }, 146 { GoogleServiceAuthError::ACCOUNT_DELETED, true }, 147 { GoogleServiceAuthError::ACCOUNT_DISABLED, true }, 148 { GoogleServiceAuthError::SERVICE_UNAVAILABLE, true }, 149 { GoogleServiceAuthError::TWO_FACTOR, true }, 150 { GoogleServiceAuthError::REQUEST_CANCELED, true }, 151 { GoogleServiceAuthError::HOSTED_NOT_ALLOWED, true }, 152 { GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE, true }, 153 { GoogleServiceAuthError::SERVICE_ERROR, true }, 154 }; 155 COMPILE_ASSERT(ARRAYSIZE_UNSAFE(table) == GoogleServiceAuthError::NUM_STATES, 156 kTable_size_does_not_match_number_of_auth_error_types); 157 158 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(table); ++i) { 159 FakeAuthStatusProvider provider(error_controller_.get()); 160 provider.SetAuthError(kTestAccountId, 161 GoogleServiceAuthError(table[i].error_state)); 162 163 EXPECT_EQ(error_controller_->HasError(), table[i].is_error); 164 165 if (table[i].is_error) { 166 EXPECT_EQ(table[i].error_state, 167 error_controller_->auth_error().state()); 168 EXPECT_STREQ(kTestAccountId, 169 error_controller_->error_account_id().c_str()); 170 } else { 171 EXPECT_EQ(GoogleServiceAuthError::NONE, 172 error_controller_->auth_error().state()); 173 EXPECT_STREQ("", 174 error_controller_->error_account_id().c_str()); 175 } 176 } 177} 178 179// Verify that existing error is not replaced by new error. 180TEST_F(SigninErrorControllerTest, AuthStatusChange) { 181 scoped_ptr<FakeAuthStatusProvider> fake_provider0( 182 new FakeAuthStatusProvider(error_controller_.get())); 183 scoped_ptr<FakeAuthStatusProvider> fake_provider1( 184 new FakeAuthStatusProvider(error_controller_.get())); 185 186 // If there are multiple providers in the provider set... 187 // 188 // | provider0 | provider1 | ... 189 // | NONE | INVALID_GAIA_CREDENTIALS | ... 190 // 191 // SigninErrorController picks the first error found when iterating through 192 // the set. But if another error crops up... 193 // 194 // | provider0 | provider1 | ... 195 // | SERVICE_UNAVAILABLE | INVALID_GAIA_CREDENTIALS | ... 196 // 197 // we want the controller to still use the original error. 198 199 // The provider pointers are stored in a set, which is sorted by std::less. 200 std::less<SigninErrorController::AuthStatusProvider*> compare; 201 FakeAuthStatusProvider* provider0 = 202 compare(fake_provider0.get(), fake_provider1.get()) ? 203 fake_provider0.get() : fake_provider1.get(); 204 FakeAuthStatusProvider* provider1 = 205 provider0 == fake_provider0.get() ? 206 fake_provider1.get() : fake_provider0.get(); 207 208 provider0->SetAuthError( 209 kTestAccountId, 210 GoogleServiceAuthError( 211 GoogleServiceAuthError::NONE)); 212 provider1->SetAuthError( 213 kOtherTestAccountId, 214 GoogleServiceAuthError( 215 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 216 ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, 217 error_controller_->auth_error().state()); 218 ASSERT_STREQ(kOtherTestAccountId, 219 error_controller_->error_account_id().c_str()); 220 221 // Change the 1st provider's error. 222 provider1->SetAuthError( 223 kOtherTestAccountId, 224 GoogleServiceAuthError( 225 GoogleServiceAuthError::SERVICE_UNAVAILABLE)); 226 ASSERT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE, 227 error_controller_->auth_error().state()); 228 ASSERT_STREQ(kOtherTestAccountId, 229 error_controller_->error_account_id().c_str()); 230 231 // Set the 0th provider's error -- nothing should change. 232 provider0->SetAuthError( 233 kTestAccountId, 234 GoogleServiceAuthError( 235 GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE)); 236 ASSERT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE, 237 error_controller_->auth_error().state()); 238 ASSERT_STREQ(kOtherTestAccountId, 239 error_controller_->error_account_id().c_str()); 240 241 // Clear the 1st provider's error, so the 0th provider's error is used. 242 provider1->SetAuthError( 243 kOtherTestAccountId, 244 GoogleServiceAuthError( 245 GoogleServiceAuthError::NONE)); 246 ASSERT_EQ(GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE, 247 error_controller_->auth_error().state()); 248 ASSERT_STREQ(kTestAccountId, 249 error_controller_->error_account_id().c_str()); 250 251 fake_provider0.reset(); 252 fake_provider1.reset(); 253 ASSERT_FALSE(error_controller_->HasError()); 254} 255