sync_errors_test.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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 "base/prefs/pref_member.h"
6#include "base/prefs/pref_service.h"
7#include "chrome/browser/sync/profile_sync_service.h"
8#include "chrome/browser/sync/test/integration/bookmarks_helper.h"
9#include "chrome/browser/sync/test/integration/passwords_helper.h"
10#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
11#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
12#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
13#include "chrome/browser/sync/test/integration/sync_test.h"
14#include "chrome/common/pref_names.h"
15#include "google_apis/gaia/google_service_auth_error.h"
16#include "sync/protocol/sync_protocol_error.h"
17
18using bookmarks_helper::AddFolder;
19using bookmarks_helper::SetTitle;
20using sync_integration_test_util::AwaitCommitActivityCompletion;
21
22namespace {
23
24class SyncDisabledChecker : public SingleClientStatusChangeChecker {
25 public:
26  explicit SyncDisabledChecker(ProfileSyncService* service)
27      : SingleClientStatusChangeChecker(service) {}
28
29  virtual bool IsExitConditionSatisfied() OVERRIDE {
30    return !service()->setup_in_progress() &&
31           !service()->HasSyncSetupCompleted();
32  }
33
34  virtual std::string GetDebugMessage() const OVERRIDE {
35    return "Sync Disabled";
36  }
37};
38
39bool AwaitSyncDisabled(ProfileSyncService* service) {
40  SyncDisabledChecker checker(service);
41  checker.Wait();
42  return !checker.TimedOut();
43}
44
45class SyncErrorTest : public SyncTest {
46 public:
47  // TODO(pvalenzuela): Switch to SINGLE_CLIENT once FakeServer
48  // supports this scenario.
49  SyncErrorTest() : SyncTest(SINGLE_CLIENT_LEGACY) {}
50  virtual ~SyncErrorTest() {}
51
52 private:
53  DISALLOW_COPY_AND_ASSIGN(SyncErrorTest);
54};
55
56// Helper class that waits until the sync engine has hit an actionable error.
57class ActionableErrorChecker : public SingleClientStatusChangeChecker {
58 public:
59  explicit ActionableErrorChecker(ProfileSyncService* service)
60      : SingleClientStatusChangeChecker(service) {}
61
62  virtual ~ActionableErrorChecker() {}
63
64  // Checks if an actionable error has been hit. Called repeatedly each time PSS
65  // notifies observers of a state change.
66  virtual bool IsExitConditionSatisfied() OVERRIDE {
67    ProfileSyncService::Status status;
68    service()->QueryDetailedSyncStatus(&status);
69    return (status.sync_protocol_error.action != syncer::UNKNOWN_ACTION &&
70            service()->HasUnrecoverableError());
71  }
72
73  virtual std::string GetDebugMessage() const OVERRIDE {
74    return "ActionableErrorChecker";
75  }
76
77 private:
78  DISALLOW_COPY_AND_ASSIGN(ActionableErrorChecker);
79};
80
81IN_PROC_BROWSER_TEST_F(SyncErrorTest, BirthdayErrorTest) {
82  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
83
84  // Add an item, wait for sync, and trigger a birthday error on the server.
85  const BookmarkNode* node1 = AddFolder(0, 0, L"title1");
86  SetTitle(0, node1, L"new_title1");
87  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
88  TriggerBirthdayError();
89
90  // Now make one more change so we will do another sync.
91  const BookmarkNode* node2 = AddFolder(0, 0, L"title2");
92  SetTitle(0, node2, L"new_title2");
93  ASSERT_TRUE(AwaitSyncDisabled(GetSyncService((0))));
94}
95
96IN_PROC_BROWSER_TEST_F(SyncErrorTest, ActionableErrorTest) {
97  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
98
99  const BookmarkNode* node1 = AddFolder(0, 0, L"title1");
100  SetTitle(0, node1, L"new_title1");
101  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
102
103  syncer::SyncProtocolError protocol_error;
104  protocol_error.error_type = syncer::TRANSIENT_ERROR;
105  protocol_error.action = syncer::UPGRADE_CLIENT;
106  protocol_error.error_description = "Not My Fault";
107  protocol_error.url = "www.google.com";
108  TriggerSyncError(protocol_error, SyncTest::ERROR_FREQUENCY_ALWAYS);
109
110  // Now make one more change so we will do another sync.
111  const BookmarkNode* node2 = AddFolder(0, 0, L"title2");
112  SetTitle(0, node2, L"new_title2");
113
114  // Wait until an actionable error is encountered.
115  ActionableErrorChecker actionable_error_checker(GetSyncService((0)));
116  actionable_error_checker.Wait();
117  ASSERT_FALSE(actionable_error_checker.TimedOut());
118
119  ProfileSyncService::Status status;
120  GetSyncService((0))->QueryDetailedSyncStatus(&status);
121  ASSERT_EQ(status.sync_protocol_error.error_type, protocol_error.error_type);
122  ASSERT_EQ(status.sync_protocol_error.action, protocol_error.action);
123  ASSERT_EQ(status.sync_protocol_error.url, protocol_error.url);
124  ASSERT_EQ(status.sync_protocol_error.error_description,
125      protocol_error.error_description);
126}
127
128// Disabled, http://crbug.com/351160 .
129IN_PROC_BROWSER_TEST_F(SyncErrorTest, DISABLED_ErrorWhileSettingUp) {
130  ASSERT_TRUE(SetupClients());
131
132  syncer::SyncProtocolError protocol_error;
133  protocol_error.error_type = syncer::TRANSIENT_ERROR;
134  protocol_error.error_description = "Not My Fault";
135  protocol_error.url = "www.google.com";
136
137  if (GetSyncService(0)->auto_start_enabled()) {
138    // In auto start enabled platforms like chrome os we should be
139    // able to set up even if the first sync while setting up fails.
140    // Trigger error on every 2 out of 3 requests.
141    TriggerSyncError(protocol_error, SyncTest::ERROR_FREQUENCY_TWO_THIRDS);
142    // Now setup sync and it should succeed.
143    ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
144  } else {
145    // In Non auto start enabled environments if the setup sync fails then
146    // the setup would fail. So setup sync normally.
147    ASSERT_TRUE(SetupSync()) << "Setup sync failed";
148    ASSERT_TRUE(GetClient(0)->DisableSyncForDatatype(syncer::AUTOFILL));
149
150    // Trigger error on every 2 out of 3 requests.
151    TriggerSyncError(protocol_error, SyncTest::ERROR_FREQUENCY_TWO_THIRDS);
152
153    // Now enable a datatype, whose first 2 syncs would fail, but we should
154    // recover and setup succesfully on the third attempt.
155    ASSERT_TRUE(GetClient(0)->EnableSyncForDatatype(syncer::AUTOFILL));
156  }
157}
158
159IN_PROC_BROWSER_TEST_F(SyncErrorTest,
160    BirthdayErrorUsingActionableErrorTest) {
161  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
162
163  const BookmarkNode* node1 = AddFolder(0, 0, L"title1");
164  SetTitle(0, node1, L"new_title1");
165  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
166
167  syncer::SyncProtocolError protocol_error;
168  protocol_error.error_type = syncer::NOT_MY_BIRTHDAY;
169  protocol_error.action = syncer::DISABLE_SYNC_ON_CLIENT;
170  protocol_error.error_description = "Not My Fault";
171  protocol_error.url = "www.google.com";
172  TriggerSyncError(protocol_error, SyncTest::ERROR_FREQUENCY_ALWAYS);
173
174  // Now make one more change so we will do another sync.
175  const BookmarkNode* node2 = AddFolder(0, 0, L"title2");
176  SetTitle(0, node2, L"new_title2");
177  ASSERT_TRUE(AwaitSyncDisabled(GetSyncService((0))));
178  ProfileSyncService::Status status;
179  GetSyncService((0))->QueryDetailedSyncStatus(&status);
180  ASSERT_EQ(status.sync_protocol_error.error_type, protocol_error.error_type);
181  ASSERT_EQ(status.sync_protocol_error.action, protocol_error.action);
182  ASSERT_EQ(status.sync_protocol_error.url, protocol_error.url);
183  ASSERT_EQ(status.sync_protocol_error.error_description,
184      protocol_error.error_description);
185}
186
187// TODO(lipalani): Fix the typed_url dtc so this test case can pass.
188IN_PROC_BROWSER_TEST_F(SyncErrorTest, DISABLED_DisableDatatypeWhileRunning) {
189  ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
190  syncer::ModelTypeSet synced_datatypes =
191      GetSyncService((0))->GetPreferredDataTypes();
192  ASSERT_TRUE(synced_datatypes.Has(syncer::TYPED_URLS));
193  GetProfile(0)->GetPrefs()->SetBoolean(
194      prefs::kSavingBrowserHistoryDisabled, true);
195
196  synced_datatypes = GetSyncService((0))->GetPreferredDataTypes();
197  ASSERT_FALSE(synced_datatypes.Has(syncer::TYPED_URLS));
198
199  const BookmarkNode* node1 = AddFolder(0, 0, L"title1");
200  SetTitle(0, node1, L"new_title1");
201  ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0))));
202  // TODO(lipalani)" Verify initial sync ended for typed url is false.
203}
204
205}  // namespace
206