Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / sync / sync_ui_util_unittest.cc
blobf84856a87305f6ddeb1960f2caad3a88446099de
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.
5 #include <set>
6 #include "base/basictypes.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/signin/fake_signin_manager.h"
10 #include "chrome/browser/signin/signin_error_controller_factory.h"
11 #include "chrome/browser/sync/profile_sync_service_mock.h"
12 #include "chrome/browser/sync/sync_ui_util.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "components/signin/core/browser/fake_auth_status_provider.h"
15 #include "components/signin/core/browser/signin_manager.h"
16 #include "content/public/test/test_browser_thread.h"
17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "testing/gmock/include/gmock/gmock-actions.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/base/l10n/l10n_util.h"
23 using ::testing::AtMost;
24 using ::testing::NiceMock;
25 using ::testing::Return;
26 using ::testing::ReturnRef;
27 using ::testing::SetArgPointee;
28 using ::testing::_;
29 using content::BrowserThread;
31 // A number of distinct states of the ProfileSyncService can be generated for
32 // tests.
33 enum DistinctState {
34 STATUS_CASE_SETUP_IN_PROGRESS,
35 STATUS_CASE_SETUP_ERROR,
36 STATUS_CASE_AUTHENTICATING,
37 STATUS_CASE_AUTH_ERROR,
38 STATUS_CASE_PROTOCOL_ERROR,
39 STATUS_CASE_PASSPHRASE_ERROR,
40 STATUS_CASE_SYNCED,
41 STATUS_CASE_SYNC_DISABLED_BY_POLICY,
42 NUMBER_OF_STATUS_CASES
45 namespace {
47 const char kTestUser[] = "test_user@test.com";
49 #if !defined(OS_CHROMEOS)
50 // Utility function to test that GetStatusLabelsForSyncGlobalError returns
51 // the correct results for the given states.
52 void VerifySyncGlobalErrorResult(NiceMock<ProfileSyncServiceMock>* service,
53 GoogleServiceAuthError::State error_state,
54 bool is_signed_in,
55 bool is_error) {
56 EXPECT_CALL(*service, HasSyncSetupCompleted())
57 .WillRepeatedly(Return(is_signed_in));
59 GoogleServiceAuthError auth_error(error_state);
60 EXPECT_CALL(*service, GetAuthError()).WillRepeatedly(ReturnRef(auth_error));
62 base::string16 label1, label2, label3;
63 sync_ui_util::GetStatusLabelsForSyncGlobalError(
64 service, &label1, &label2, &label3);
65 EXPECT_EQ(label1.empty(), !is_error);
66 EXPECT_EQ(label2.empty(), !is_error);
67 EXPECT_EQ(label3.empty(), !is_error);
69 #endif
71 } // namespace
74 class SyncUIUtilTest : public testing::Test {
75 private:
76 content::TestBrowserThreadBundle thread_bundle_;
79 #if !defined(OS_CHROMEOS)
80 // Test that GetStatusLabelsForSyncGlobalError returns an error if a
81 // passphrase is required.
82 TEST_F(SyncUIUtilTest, PassphraseGlobalError) {
83 scoped_ptr<Profile> profile(
84 ProfileSyncServiceMock::MakeSignedInTestingProfile());
85 NiceMock<ProfileSyncServiceMock> service(profile.get());
86 browser_sync::SyncBackendHost::Status status;
87 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
88 .WillRepeatedly(Return(false));
89 EXPECT_CALL(service, IsPassphraseRequired())
90 .WillRepeatedly(Return(true));
91 EXPECT_CALL(service, IsPassphraseRequiredForDecryption())
92 .WillRepeatedly(Return(true));
94 VerifySyncGlobalErrorResult(&service,
95 GoogleServiceAuthError::NONE,
96 true /* signed in */,
97 true /* error */);
100 // Test that GetStatusLabelsForSyncGlobalError returns an error if a
101 // passphrase is required and not for auth errors.
102 TEST_F(SyncUIUtilTest, AuthAndPassphraseGlobalError) {
103 scoped_ptr<Profile> profile(
104 ProfileSyncServiceMock::MakeSignedInTestingProfile());
105 NiceMock<ProfileSyncServiceMock> service(profile.get());
106 browser_sync::SyncBackendHost::Status status;
107 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
108 .WillRepeatedly(Return(false));
110 EXPECT_CALL(service, IsPassphraseRequired())
111 .WillRepeatedly(Return(true));
112 EXPECT_CALL(service, IsPassphraseRequiredForDecryption())
113 .WillRepeatedly(Return(true));
114 EXPECT_CALL(service, HasSyncSetupCompleted())
115 .WillRepeatedly(Return(true));
117 GoogleServiceAuthError auth_error(
118 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
119 EXPECT_CALL(service, GetAuthError()).WillRepeatedly(ReturnRef(auth_error));
120 base::string16 menu_label, label2, label3;
121 sync_ui_util::GetStatusLabelsForSyncGlobalError(
122 &service, &menu_label, &label2, &label3);
123 // Make sure we are still displaying the passphrase error badge (don't show
124 // auth errors through SyncUIUtil).
125 EXPECT_EQ(menu_label, l10n_util::GetStringUTF16(
126 IDS_SYNC_PASSPHRASE_ERROR_WRENCH_MENU_ITEM));
129 // Test that GetStatusLabelsForSyncGlobalError does not indicate errors for
130 // auth errors (these are reported through SigninGlobalError).
131 TEST_F(SyncUIUtilTest, AuthStateGlobalError) {
132 scoped_ptr<Profile> profile(
133 ProfileSyncServiceMock::MakeSignedInTestingProfile());
134 NiceMock<ProfileSyncServiceMock> service(profile.get());
136 browser_sync::SyncBackendHost::Status status;
137 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
138 .WillRepeatedly(Return(false));
140 GoogleServiceAuthError::State table[] = {
141 GoogleServiceAuthError::NONE,
142 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
143 GoogleServiceAuthError::USER_NOT_SIGNED_UP,
144 GoogleServiceAuthError::CONNECTION_FAILED,
145 GoogleServiceAuthError::CAPTCHA_REQUIRED,
146 GoogleServiceAuthError::ACCOUNT_DELETED,
147 GoogleServiceAuthError::ACCOUNT_DISABLED,
148 GoogleServiceAuthError::SERVICE_UNAVAILABLE,
149 GoogleServiceAuthError::TWO_FACTOR,
150 GoogleServiceAuthError::REQUEST_CANCELED,
151 GoogleServiceAuthError::HOSTED_NOT_ALLOWED
154 FakeSigninManagerBase signin(profile.get());
155 for (size_t i = 0; i < arraysize(table); ++i) {
156 VerifySyncGlobalErrorResult(&service,
157 table[i],
158 true /* signed in */,
159 false /* no error */);
160 VerifySyncGlobalErrorResult(&service,
161 table[i],
162 false /* not signed in */,
163 false /* no error */);
166 #endif
168 // TODO(tim): This shouldn't be required. r194857 removed the
169 // AuthInProgress override from FakeSigninManager, which meant this test started
170 // using the "real" SigninManager AuthInProgress logic. Without that override,
171 // it's no longer possible to test both chrome os + desktop flows as part of the
172 // same test, because AuthInProgress is always false on chrome os. Most of the
173 // tests are unaffected, but STATUS_CASE_AUTHENTICATING can't exist in both
174 // versions, so it we will require two separate tests, one using SigninManager
175 // and one using SigninManagerBase (which require different setup procedures.
176 class FakeSigninManagerForSyncUIUtilTest : public FakeSigninManagerBase {
177 public:
178 explicit FakeSigninManagerForSyncUIUtilTest(Profile* profile)
179 : FakeSigninManagerBase(profile), auth_in_progress_(false) {
180 Initialize(NULL);
183 ~FakeSigninManagerForSyncUIUtilTest() override {}
185 bool AuthInProgress() const override { return auth_in_progress_; }
187 void set_auth_in_progress() {
188 auth_in_progress_ = true;
191 private:
192 bool auth_in_progress_;
195 // Loads a ProfileSyncServiceMock to emulate one of a number of distinct cases
196 // in order to perform tests on the generated messages.
197 void GetDistinctCase(ProfileSyncServiceMock& service,
198 FakeSigninManagerForSyncUIUtilTest* signin,
199 FakeAuthStatusProvider* provider,
200 int caseNumber) {
201 // Auth Error object is returned by reference in mock and needs to stay in
202 // scope throughout test, so it is owned by calling method. However it is
203 // immutable so can only be allocated in this method.
204 switch (caseNumber) {
205 case STATUS_CASE_SETUP_IN_PROGRESS: {
206 EXPECT_CALL(service, HasSyncSetupCompleted())
207 .WillRepeatedly(Return(false));
208 EXPECT_CALL(service, FirstSetupInProgress())
209 .WillRepeatedly(Return(true));
210 browser_sync::SyncBackendHost::Status status;
211 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
212 .WillRepeatedly(DoAll(SetArgPointee<0>(status),
213 Return(false)));
214 return;
216 case STATUS_CASE_SETUP_ERROR: {
217 EXPECT_CALL(service, HasSyncSetupCompleted())
218 .WillRepeatedly(Return(false));
219 EXPECT_CALL(service, FirstSetupInProgress())
220 .WillRepeatedly(Return(false));
221 EXPECT_CALL(service, HasUnrecoverableError())
222 .WillRepeatedly(Return(true));
223 browser_sync::SyncBackendHost::Status status;
224 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
225 .WillRepeatedly(DoAll(SetArgPointee<0>(status),
226 Return(false)));
227 return;
229 case STATUS_CASE_AUTHENTICATING: {
230 EXPECT_CALL(service, HasSyncSetupCompleted())
231 .WillRepeatedly(Return(true));
232 EXPECT_CALL(service, SyncActive()).WillRepeatedly(Return(true));
233 EXPECT_CALL(service, IsPassphraseRequired())
234 .WillRepeatedly(Return(false));
235 browser_sync::SyncBackendHost::Status status;
236 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
237 .WillRepeatedly(DoAll(SetArgPointee<0>(status),
238 Return(false)));
239 EXPECT_CALL(service, HasUnrecoverableError())
240 .WillRepeatedly(Return(false));
241 signin->set_auth_in_progress();
242 return;
244 case STATUS_CASE_AUTH_ERROR: {
245 EXPECT_CALL(service, HasSyncSetupCompleted())
246 .WillRepeatedly(Return(true));
247 EXPECT_CALL(service, SyncActive()).WillRepeatedly(Return(true));
248 EXPECT_CALL(service, IsPassphraseRequired())
249 .WillRepeatedly(Return(false));
250 browser_sync::SyncBackendHost::Status status;
251 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
252 .WillRepeatedly(DoAll(SetArgPointee<0>(status),
253 Return(false)));
254 provider->SetAuthError(
255 kTestUser,
256 kTestUser,
257 GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
258 EXPECT_CALL(service, HasUnrecoverableError())
259 .WillRepeatedly(Return(false));
260 return;
262 case STATUS_CASE_PROTOCOL_ERROR: {
263 EXPECT_CALL(service, HasSyncSetupCompleted())
264 .WillRepeatedly(Return(true));
265 EXPECT_CALL(service, SyncActive()).WillRepeatedly(Return(true));
266 EXPECT_CALL(service, IsPassphraseRequired())
267 .WillRepeatedly(Return(false));
268 syncer::SyncProtocolError protocolError;
269 protocolError.action = syncer::STOP_AND_RESTART_SYNC;
270 browser_sync::SyncBackendHost::Status status;
271 status.sync_protocol_error = protocolError;
272 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
273 .WillRepeatedly(DoAll(SetArgPointee<0>(status),
274 Return(false)));
275 EXPECT_CALL(service, HasUnrecoverableError())
276 .WillRepeatedly(Return(false));
277 return;
279 case STATUS_CASE_PASSPHRASE_ERROR: {
280 EXPECT_CALL(service, HasSyncSetupCompleted())
281 .WillRepeatedly(Return(true));
282 EXPECT_CALL(service, SyncActive()).WillRepeatedly(Return(true));
283 browser_sync::SyncBackendHost::Status status;
284 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
285 .WillRepeatedly(DoAll(SetArgPointee<0>(status),
286 Return(false)));
287 EXPECT_CALL(service, HasUnrecoverableError())
288 .WillRepeatedly(Return(false));
289 EXPECT_CALL(service, IsPassphraseRequired())
290 .WillRepeatedly(Return(true));
291 EXPECT_CALL(service, IsPassphraseRequiredForDecryption())
292 .WillRepeatedly(Return(true));
293 return;
295 case STATUS_CASE_SYNCED: {
296 EXPECT_CALL(service, HasSyncSetupCompleted())
297 .WillRepeatedly(Return(true));
298 EXPECT_CALL(service, SyncActive()).WillRepeatedly(Return(true));
299 EXPECT_CALL(service, IsPassphraseRequired())
300 .WillRepeatedly(Return(false));
301 browser_sync::SyncBackendHost::Status status;
302 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
303 .WillRepeatedly(DoAll(SetArgPointee<0>(status),
304 Return(false)));
305 EXPECT_CALL(service, HasUnrecoverableError())
306 .WillRepeatedly(Return(false));
307 EXPECT_CALL(service, IsPassphraseRequired())
308 .WillRepeatedly(Return(false));
309 return;
311 case STATUS_CASE_SYNC_DISABLED_BY_POLICY: {
312 EXPECT_CALL(service, IsManaged()).WillRepeatedly(Return(true));
313 EXPECT_CALL(service, HasSyncSetupCompleted())
314 .WillRepeatedly(Return(false));
315 EXPECT_CALL(service, SyncActive()).WillRepeatedly(Return(false));
316 EXPECT_CALL(service, IsPassphraseRequired())
317 .WillRepeatedly(Return(false));
318 browser_sync::SyncBackendHost::Status status;
319 EXPECT_CALL(service, QueryDetailedSyncStatus(_))
320 .WillRepeatedly(DoAll(SetArgPointee<0>(status),
321 Return(false)));
322 EXPECT_CALL(service, HasUnrecoverableError())
323 .WillRepeatedly(Return(false));
324 return;
326 default:
327 NOTREACHED();
331 // This test ensures that a each distinctive ProfileSyncService statuses
332 // will return a unique combination of status and link messages from
333 // GetStatusLabels().
334 TEST_F(SyncUIUtilTest, DistinctCasesReportUniqueMessageSets) {
335 std::set<base::string16> messages;
336 for (int idx = 0; idx != NUMBER_OF_STATUS_CASES; idx++) {
337 scoped_ptr<Profile> profile(new TestingProfile());
338 ProfileSyncServiceMock service(profile.get());
339 GoogleServiceAuthError error = GoogleServiceAuthError::AuthErrorNone();
340 EXPECT_CALL(service, GetAuthError()).WillRepeatedly(ReturnRef(error));
341 FakeSigninManagerForSyncUIUtilTest signin(profile.get());
342 signin.SetAuthenticatedUsername(kTestUser);
343 scoped_ptr<FakeAuthStatusProvider> provider(new FakeAuthStatusProvider(
344 SigninErrorControllerFactory::GetForProfile(profile.get())));
345 GetDistinctCase(service, &signin, provider.get(), idx);
346 base::string16 status_label;
347 base::string16 link_label;
348 sync_ui_util::GetStatusLabels(&service,
349 signin,
350 sync_ui_util::WITH_HTML,
351 &status_label,
352 &link_label);
353 // If the status and link message combination is already present in the set
354 // of messages already seen, this is a duplicate rather than a unique
355 // message, and the test has failed.
356 EXPECT_FALSE(status_label.empty()) <<
357 "Empty status label returned for case #" << idx;
358 base::string16 combined_label =
359 status_label + base::ASCIIToUTF16("#") + link_label;
360 EXPECT_TRUE(messages.find(combined_label) == messages.end()) <<
361 "Duplicate message for case #" << idx << ": " << combined_label;
362 messages.insert(combined_label);
363 testing::Mock::VerifyAndClearExpectations(&service);
364 testing::Mock::VerifyAndClearExpectations(&signin);
365 EXPECT_CALL(service, GetAuthError()).WillRepeatedly(ReturnRef(error));
366 provider.reset();
367 signin.Shutdown();
371 // This test ensures that the html_links parameter on GetStatusLabels() is
372 // honored.
373 TEST_F(SyncUIUtilTest, HtmlNotIncludedInStatusIfNotRequested) {
374 for (int idx = 0; idx != NUMBER_OF_STATUS_CASES; idx++) {
375 scoped_ptr<Profile> profile(
376 ProfileSyncServiceMock::MakeSignedInTestingProfile());
377 ProfileSyncServiceMock service(profile.get());
378 GoogleServiceAuthError error = GoogleServiceAuthError::AuthErrorNone();
379 EXPECT_CALL(service, GetAuthError()).WillRepeatedly(ReturnRef(error));
380 FakeSigninManagerForSyncUIUtilTest signin(profile.get());
381 signin.SetAuthenticatedUsername(kTestUser);
382 scoped_ptr<FakeAuthStatusProvider> provider(new FakeAuthStatusProvider(
383 SigninErrorControllerFactory::GetForProfile(profile.get())));
384 GetDistinctCase(service, &signin, provider.get(), idx);
385 base::string16 status_label;
386 base::string16 link_label;
387 sync_ui_util::GetStatusLabels(&service,
388 signin,
389 sync_ui_util::PLAIN_TEXT,
390 &status_label,
391 &link_label);
393 // Ensures a search for string 'href' (found in links, not a string to be
394 // found in an English language message) fails when links are excluded from
395 // the status label.
396 EXPECT_FALSE(status_label.empty());
397 EXPECT_EQ(status_label.find(base::ASCIIToUTF16("href")),
398 base::string16::npos);
399 testing::Mock::VerifyAndClearExpectations(&service);
400 testing::Mock::VerifyAndClearExpectations(&signin);
401 EXPECT_CALL(service, GetAuthError()).WillRepeatedly(ReturnRef(error));
402 provider.reset();
403 signin.Shutdown();