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