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.
5 #include "components/signin/core/browser/signin_error_controller.h"
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"
13 static const char kTestAccountId[] = "testuser@test.com";
14 static const char kTestUsername[] = "testuser@test.com";
15 static const char kOtherTestAccountId[] = "otheruser@test.com";
16 static const char kOtherTestUsername[] = "otheruser@test.com";
18 class SigninErrorControllerTest : public testing::Test {
20 void SetUp() override {
21 error_controller_.reset(new SigninErrorController());
24 scoped_ptr<SigninErrorController> error_controller_;
27 TEST_F(SigninErrorControllerTest, NoErrorAuthStatusProviders) {
28 scoped_ptr<FakeAuthStatusProvider> provider;
31 ASSERT_FALSE(error_controller_->HasError());
34 provider.reset(new FakeAuthStatusProvider(error_controller_.get()));
35 ASSERT_FALSE(error_controller_->HasError());
37 // Remove the provider.
39 ASSERT_FALSE(error_controller_->HasError());
42 TEST_F(SigninErrorControllerTest, ErrorAuthStatusProvider) {
43 scoped_ptr<FakeAuthStatusProvider> provider;
44 scoped_ptr<FakeAuthStatusProvider> error_provider;
46 provider.reset(new FakeAuthStatusProvider(error_controller_.get()));
47 ASSERT_FALSE(error_controller_->HasError());
49 error_provider.reset(new FakeAuthStatusProvider(error_controller_.get()));
50 error_provider->SetAuthError(
53 GoogleServiceAuthError(
54 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
55 ASSERT_TRUE(error_controller_->HasError());
57 error_provider.reset();
58 ASSERT_FALSE(error_controller_->HasError());
61 // All providers should be removed now.
62 ASSERT_FALSE(error_controller_->HasError());
65 TEST_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()));
71 ASSERT_FALSE(error_controller_->HasError());
72 provider0->SetAuthError(
75 GoogleServiceAuthError(
76 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
77 ASSERT_TRUE(error_controller_->HasError());
78 provider1->SetAuthError(
81 GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED));
82 ASSERT_TRUE(error_controller_->HasError());
84 // Now resolve the auth errors - the menu item should go away.
85 provider0->SetAuthError(kTestAccountId,
87 GoogleServiceAuthError::AuthErrorNone());
88 ASSERT_TRUE(error_controller_->HasError());
89 provider1->SetAuthError(kTestAccountId,
91 GoogleServiceAuthError::AuthErrorNone());
92 ASSERT_FALSE(error_controller_->HasError());
96 ASSERT_FALSE(error_controller_->HasError());
99 TEST_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()));
105 ASSERT_FALSE(error_controller_->HasError());
107 provider0->SetAuthError(
110 GoogleServiceAuthError(
111 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
112 provider1->SetAuthError(
115 GoogleServiceAuthError(GoogleServiceAuthError::NONE));
116 ASSERT_TRUE(error_controller_->HasError());
117 ASSERT_STREQ(kTestAccountId,
118 error_controller_->error_account_id().c_str());
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());
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());
141 ASSERT_FALSE(error_controller_->HasError());
144 // Verify that SigninErrorController handles errors properly.
145 TEST_F(SigninErrorControllerTest, AuthStatusEnumerateAllErrors) {
147 GoogleServiceAuthError::State error_state;
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 { GoogleServiceAuthError::WEB_LOGIN_REQUIRED, true },
167 COMPILE_ASSERT(arraysize(table) == GoogleServiceAuthError::NUM_STATES,
168 kTable_size_does_not_match_number_of_auth_error_types);
170 for (size_t i = 0; i < arraysize(table); ++i) {
171 FakeAuthStatusProvider provider(error_controller_.get());
172 provider.SetAuthError(kTestAccountId,
174 GoogleServiceAuthError(table[i].error_state));
176 EXPECT_EQ(error_controller_->HasError(), table[i].is_error);
178 if (table[i].is_error) {
179 EXPECT_EQ(table[i].error_state,
180 error_controller_->auth_error().state());
181 EXPECT_STREQ(kTestAccountId,
182 error_controller_->error_account_id().c_str());
184 EXPECT_EQ(GoogleServiceAuthError::NONE,
185 error_controller_->auth_error().state());
187 error_controller_->error_account_id().c_str());
192 // Verify that existing error is not replaced by new error.
193 TEST_F(SigninErrorControllerTest, AuthStatusChange) {
194 scoped_ptr<FakeAuthStatusProvider> fake_provider0(
195 new FakeAuthStatusProvider(error_controller_.get()));
196 scoped_ptr<FakeAuthStatusProvider> fake_provider1(
197 new FakeAuthStatusProvider(error_controller_.get()));
199 // If there are multiple providers in the provider set...
201 // | provider0 | provider1 | ...
202 // | NONE | INVALID_GAIA_CREDENTIALS | ...
204 // SigninErrorController picks the first error found when iterating through
205 // the set. But if another error crops up...
207 // | provider0 | provider1 | ...
208 // | SERVICE_UNAVAILABLE | INVALID_GAIA_CREDENTIALS | ...
210 // we want the controller to still use the original error.
212 // The provider pointers are stored in a set, which is sorted by std::less.
213 std::less<SigninErrorController::AuthStatusProvider*> compare;
214 FakeAuthStatusProvider* provider0 =
215 compare(fake_provider0.get(), fake_provider1.get()) ?
216 fake_provider0.get() : fake_provider1.get();
217 FakeAuthStatusProvider* provider1 =
218 provider0 == fake_provider0.get() ?
219 fake_provider1.get() : fake_provider0.get();
221 provider0->SetAuthError(
224 GoogleServiceAuthError(
225 GoogleServiceAuthError::NONE));
226 provider1->SetAuthError(
229 GoogleServiceAuthError(
230 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
231 ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
232 error_controller_->auth_error().state());
233 ASSERT_STREQ(kOtherTestAccountId,
234 error_controller_->error_account_id().c_str());
236 // Change the 1st provider's error.
237 provider1->SetAuthError(
240 GoogleServiceAuthError(
241 GoogleServiceAuthError::SERVICE_UNAVAILABLE));
242 ASSERT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE,
243 error_controller_->auth_error().state());
244 ASSERT_STREQ(kOtherTestAccountId,
245 error_controller_->error_account_id().c_str());
247 // Set the 0th provider's error -- nothing should change.
248 provider0->SetAuthError(
251 GoogleServiceAuthError(
252 GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE));
253 ASSERT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE,
254 error_controller_->auth_error().state());
255 ASSERT_STREQ(kOtherTestAccountId,
256 error_controller_->error_account_id().c_str());
258 // Clear the 1st provider's error, so the 0th provider's error is used.
259 provider1->SetAuthError(
262 GoogleServiceAuthError(
263 GoogleServiceAuthError::NONE));
264 ASSERT_EQ(GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE,
265 error_controller_->auth_error().state());
266 ASSERT_STREQ(kTestAccountId,
267 error_controller_->error_account_id().c_str());
269 fake_provider0.reset();
270 fake_provider1.reset();
271 ASSERT_FALSE(error_controller_->HasError());