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