sync_session_unittest.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2009 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 "chrome/browser/sync/sessions/sync_session.h"
6
7#include "chrome/browser/sync/engine/conflict_resolver.h"
8#include "chrome/browser/sync/engine/syncer_types.h"
9#include "chrome/browser/sync/engine/syncer_util.h"
10#include "chrome/browser/sync/syncable/directory_manager.h"
11#include "chrome/browser/sync/syncable/syncable.h"
12#include "chrome/test/sync/engine/test_directory_setter_upper.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15using syncable::MultiTypeTimeStamp;
16using syncable::WriteTransaction;
17
18namespace browser_sync {
19namespace sessions {
20namespace {
21
22class SyncSessionTest : public testing::Test,
23                        public SyncSession::Delegate,
24                        public ModelSafeWorkerRegistrar {
25 public:
26  SyncSessionTest() : controller_invocations_allowed_(false) {
27    GetModelSafeRoutingInfo(&routes_);
28  }
29  virtual void SetUp() {
30    context_.reset(new SyncSessionContext(NULL, NULL, NULL, this));
31    session_.reset(new SyncSession(context_.get(), this));
32  }
33  virtual void TearDown() {
34    session_.reset();
35    context_.reset();
36  }
37
38  virtual void OnSilencedUntil(const base::TimeTicks& silenced_until) {
39    FailControllerInvocationIfDisabled("OnSilencedUntil");
40  }
41  virtual bool IsSyncingCurrentlySilenced() {
42    FailControllerInvocationIfDisabled("IsSyncingCurrentlySilenced");
43   return false;
44  }
45  virtual void OnReceivedLongPollIntervalUpdate(
46      const base::TimeDelta& new_interval) {
47    FailControllerInvocationIfDisabled("OnReceivedLongPollIntervalUpdate");
48  }
49  virtual void OnReceivedShortPollIntervalUpdate(
50      const base::TimeDelta& new_interval) {
51    FailControllerInvocationIfDisabled("OnReceivedShortPollIntervalUpdate");
52  }
53  virtual void OnShouldStopSyncingPermanently() {
54      FailControllerInvocationIfDisabled("OnShouldStopSyncingPermanently");
55  }
56
57  // ModelSafeWorkerRegistrar implementation.
58  virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) {}
59  virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) {
60    (*out)[syncable::BOOKMARKS] = GROUP_UI;
61    (*out)[syncable::AUTOFILL] = GROUP_UI;
62  }
63
64  StatusController* status() { return session_->status_controller(); }
65 protected:
66  void FailControllerInvocationIfDisabled(const std::string& msg) {
67    if (!controller_invocations_allowed_)
68      FAIL() << msg;
69  }
70
71  MultiTypeTimeStamp ParamsMeaningAllEnabledTypes() {
72    MultiTypeTimeStamp request_params;
73    request_params.timestamp = 2000;
74    request_params.data_types[syncable::BOOKMARKS] = true;
75    request_params.data_types[syncable::AUTOFILL] = true;
76    return request_params;
77  }
78
79  MultiTypeTimeStamp ParamsMeaningJustOneEnabledType() {
80    MultiTypeTimeStamp request_params;
81    request_params.timestamp = 5000;
82    request_params.data_types[syncable::AUTOFILL] = true;
83    return request_params;
84  }
85
86  bool controller_invocations_allowed_;
87  scoped_ptr<SyncSession> session_;
88  scoped_ptr<SyncSessionContext> context_;
89  ModelSafeRoutingInfo routes_;
90};
91
92TEST_F(SyncSessionTest, ScopedContextHelpers) {
93  ConflictResolver resolver;
94  SyncerEventChannel* channel = new SyncerEventChannel();
95  EXPECT_FALSE(context_->resolver());
96  EXPECT_FALSE(context_->syncer_event_channel());
97  {
98    ScopedSessionContextConflictResolver s_resolver(context_.get(), &resolver);
99    ScopedSessionContextSyncerEventChannel s_channel(context_.get(), channel);
100    EXPECT_EQ(&resolver, context_->resolver());
101    EXPECT_EQ(channel, context_->syncer_event_channel());
102  }
103  EXPECT_FALSE(context_->resolver());
104  EXPECT_FALSE(context_->syncer_event_channel());
105  channel->Notify(SyncerEvent(SyncerEvent::SHUTDOWN_USE_WITH_CARE));
106  delete channel;
107}
108
109TEST_F(SyncSessionTest, SetWriteTransaction) {
110  TestDirectorySetterUpper db;
111  db.SetUp();
112  session_.reset(NULL);
113  context_.reset(new SyncSessionContext(NULL, NULL, db.manager(), this));
114  session_.reset(new SyncSession(context_.get(), this));
115  context_->set_account_name(db.name());
116  syncable::ScopedDirLookup dir(context_->directory_manager(),
117                                context_->account_name());
118  ASSERT_TRUE(dir.good());
119
120  SyncSession session(context_.get(), this);
121  EXPECT_TRUE(NULL == session.write_transaction());
122  {
123    WriteTransaction trans(dir, syncable::UNITTEST, __FILE__, __LINE__);
124    sessions::ScopedSetSessionWriteTransaction set_trans(&session, &trans);
125    EXPECT_TRUE(&trans == session.write_transaction());
126  }
127  db.TearDown();
128}
129
130TEST_F(SyncSessionTest, MoreToSyncIfUnsyncedGreaterThanCommitted) {
131  // If any forward progress was made during the session, and the number of
132  // unsynced handles still exceeds the number of commit ids we added, there is
133  // more to sync. For example, this occurs if we had more commit ids
134  // than could fit in a single commit batch.
135  EXPECT_FALSE(session_->HasMoreToSync());
136  OrderedCommitSet commit_set(routes_);
137  commit_set.AddCommitItem(0, syncable::Id(), syncable::BOOKMARKS);
138  status()->set_commit_set(commit_set);
139  EXPECT_FALSE(session_->HasMoreToSync());
140
141  std::vector<int64> unsynced_handles;
142  unsynced_handles.push_back(1);
143  unsynced_handles.push_back(2);
144  status()->set_unsynced_handles(unsynced_handles);
145  EXPECT_FALSE(session_->HasMoreToSync());
146  status()->increment_num_successful_commits();
147  EXPECT_TRUE(session_->HasMoreToSync());
148}
149
150TEST_F(SyncSessionTest, MoreToSyncIfConflictSetsBuilt) {
151  // If we built conflict sets, then we need to loop back and try
152  // to get updates & commit again.
153  status()->update_conflict_sets_built(true);
154  EXPECT_TRUE(session_->HasMoreToSync());
155}
156
157TEST_F(SyncSessionTest, MoreToDownloadIfDownloadFailed) {
158  status()->set_updates_request_parameters(ParamsMeaningAllEnabledTypes());
159
160  // When DownloadUpdatesCommand fails, these should be false.
161  EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
162  EXPECT_FALSE(status()->download_updates_succeeded());
163
164  // Download updates has its own loop in the syncer; it shouldn't factor
165  // into HasMoreToSync.
166  EXPECT_FALSE(session_->HasMoreToSync());
167}
168
169TEST_F(SyncSessionTest, MoreToDownloadIfGotTimestamp) {
170  status()->set_updates_request_parameters(ParamsMeaningAllEnabledTypes());
171
172  // When the server returns a timestamp, that means there's more to download.
173  status()->mutable_updates_response()->mutable_get_updates()
174      ->set_new_timestamp(1000000L);
175  EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
176  EXPECT_TRUE(status()->download_updates_succeeded());
177
178  // Download updates has its own loop in the syncer; it shouldn't factor
179  // into HasMoreToSync.
180  EXPECT_FALSE(session_->HasMoreToSync());
181}
182
183TEST_F(SyncSessionTest, MoreToDownloadIfGotNoTimestamp) {
184  status()->set_updates_request_parameters(ParamsMeaningAllEnabledTypes());
185
186  // When the server returns a timestamp, that means we're up to date.
187  status()->mutable_updates_response()->mutable_get_updates()
188      ->clear_new_timestamp();
189  EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload());
190  EXPECT_TRUE(status()->download_updates_succeeded());
191
192  // Download updates has its own loop in the syncer; it shouldn't factor
193  // into HasMoreToSync.
194  EXPECT_FALSE(session_->HasMoreToSync());
195}
196
197TEST_F(SyncSessionTest, MoreToDownloadIfGotNoTimestampForSubset) {
198  status()->set_updates_request_parameters(ParamsMeaningJustOneEnabledType());
199
200  // When the server returns a timestamp, that means we're up to date for that
201  // type.  But there may still be more to download if there are other
202  // datatypes that we didn't request on this go-round.
203  status()->mutable_updates_response()->mutable_get_updates()
204    ->clear_new_timestamp();
205  EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
206  EXPECT_TRUE(status()->download_updates_succeeded());
207
208  // Download updates has its own loop in the syncer; it shouldn't factor
209  // into HasMoreToSync.
210  EXPECT_FALSE(session_->HasMoreToSync());
211}
212
213TEST_F(SyncSessionTest, MoreToDownloadIfGotTimestampAndEntries) {
214  status()->set_updates_request_parameters(ParamsMeaningAllEnabledTypes());
215  // The actual entry count should not factor into the HasMoreToSync
216  // determination.
217  status()->mutable_updates_response()->mutable_get_updates()->add_entries();
218  status()->mutable_updates_response()->mutable_get_updates()
219      ->set_new_timestamp(1000000L);;
220  EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
221  EXPECT_TRUE(status()->download_updates_succeeded());
222
223  // Download updates has its own loop in the syncer; it shouldn't factor
224  // into HasMoreToSync.
225  EXPECT_FALSE(session_->HasMoreToSync());
226}
227
228
229TEST_F(SyncSessionTest, MoreToSyncIfConflictsResolved) {
230  // Conflict resolution happens after get updates and commit,
231  // so we need to loop back and get updates / commit again now
232  // that we have made forward progress.
233  status()->update_conflicts_resolved(true);
234  EXPECT_TRUE(session_->HasMoreToSync());
235}
236
237}  // namespace
238}  // namespace sessions
239}  // namespace browser_sync
240