• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "base/memory/ref_counted.h"
8 #include "chrome/browser/sync/engine/conflict_resolver.h"
9 #include "chrome/browser/sync/engine/mock_model_safe_workers.h"
10 #include "chrome/browser/sync/engine/syncer_types.h"
11 #include "chrome/browser/sync/engine/syncer_util.h"
12 #include "chrome/browser/sync/syncable/directory_manager.h"
13 #include "chrome/browser/sync/syncable/model_type.h"
14 #include "chrome/browser/sync/syncable/syncable.h"
15 #include "chrome/test/sync/engine/test_directory_setter_upper.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 using syncable::WriteTransaction;
19 
20 namespace browser_sync {
21 namespace sessions {
22 namespace {
23 
24 class SyncSessionTest : public testing::Test,
25                         public SyncSession::Delegate,
26                         public ModelSafeWorkerRegistrar {
27  public:
SyncSessionTest()28   SyncSessionTest() : controller_invocations_allowed_(false) {
29     GetModelSafeRoutingInfo(&routes_);
30   }
31 
MakeSession()32   SyncSession* MakeSession() {
33     return new SyncSession(context_.get(), this, SyncSourceInfo(), routes_,
34                            std::vector<ModelSafeWorker*>());
35   }
36 
SetUp()37   virtual void SetUp() {
38     context_.reset(new SyncSessionContext(NULL, NULL, this,
39         std::vector<SyncEngineEventListener*>()));
40     routes_.clear();
41     routes_[syncable::BOOKMARKS] = GROUP_UI;
42     routes_[syncable::AUTOFILL] = GROUP_UI;
43     session_.reset(MakeSession());
44   }
TearDown()45   virtual void TearDown() {
46     session_.reset();
47     context_.reset();
48   }
49 
OnSilencedUntil(const base::TimeTicks & silenced_until)50   virtual void OnSilencedUntil(const base::TimeTicks& silenced_until) {
51     FailControllerInvocationIfDisabled("OnSilencedUntil");
52   }
IsSyncingCurrentlySilenced()53   virtual bool IsSyncingCurrentlySilenced() {
54     FailControllerInvocationIfDisabled("IsSyncingCurrentlySilenced");
55     return false;
56   }
OnReceivedLongPollIntervalUpdate(const base::TimeDelta & new_interval)57   virtual void OnReceivedLongPollIntervalUpdate(
58       const base::TimeDelta& new_interval) {
59     FailControllerInvocationIfDisabled("OnReceivedLongPollIntervalUpdate");
60   }
OnReceivedShortPollIntervalUpdate(const base::TimeDelta & new_interval)61   virtual void OnReceivedShortPollIntervalUpdate(
62       const base::TimeDelta& new_interval) {
63     FailControllerInvocationIfDisabled("OnReceivedShortPollIntervalUpdate");
64   }
OnShouldStopSyncingPermanently()65   virtual void OnShouldStopSyncingPermanently() {
66     FailControllerInvocationIfDisabled("OnShouldStopSyncingPermanently");
67   }
68 
69   // ModelSafeWorkerRegistrar implementation.
GetWorkers(std::vector<ModelSafeWorker * > * out)70   virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) {}
GetModelSafeRoutingInfo(ModelSafeRoutingInfo * out)71   virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) {
72     out->swap(routes_);
73   }
74 
status()75   StatusController* status() { return session_->status_controller(); }
76  protected:
FailControllerInvocationIfDisabled(const std::string & msg)77   void FailControllerInvocationIfDisabled(const std::string& msg) {
78     if (!controller_invocations_allowed_)
79       FAIL() << msg;
80   }
81 
ParamsMeaningAllEnabledTypes()82   syncable::ModelTypeBitSet ParamsMeaningAllEnabledTypes() {
83     syncable::ModelTypeBitSet request_params;
84     request_params[syncable::BOOKMARKS] = true;
85     request_params[syncable::AUTOFILL] = true;
86     return request_params;
87   }
88 
ParamsMeaningJustOneEnabledType()89   syncable::ModelTypeBitSet ParamsMeaningJustOneEnabledType() {
90     syncable::ModelTypeBitSet request_params;
91     request_params[syncable::AUTOFILL] = true;
92     return request_params;
93   }
94 
95   bool controller_invocations_allowed_;
96   scoped_ptr<SyncSession> session_;
97   scoped_ptr<SyncSessionContext> context_;
98   ModelSafeRoutingInfo routes_;
99 };
100 
TEST_F(SyncSessionTest,ScopedContextHelpers)101 TEST_F(SyncSessionTest, ScopedContextHelpers) {
102   ConflictResolver resolver;
103   EXPECT_FALSE(context_->resolver());
104   {
105     ScopedSessionContextConflictResolver s_resolver(context_.get(), &resolver);
106     EXPECT_EQ(&resolver, context_->resolver());
107   }
108   EXPECT_FALSE(context_->resolver());
109 }
110 
TEST_F(SyncSessionTest,SetWriteTransaction)111 TEST_F(SyncSessionTest, SetWriteTransaction) {
112   TestDirectorySetterUpper db;
113   db.SetUp();
114   session_.reset();
115   context_.reset(new SyncSessionContext(NULL, db.manager(), this,
116       std::vector<SyncEngineEventListener*>()));
117   session_.reset(MakeSession());
118   context_->set_account_name(db.name());
119   syncable::ScopedDirLookup dir(context_->directory_manager(),
120                                 context_->account_name());
121   ASSERT_TRUE(dir.good());
122 
123   scoped_ptr<SyncSession> session(MakeSession());
124   EXPECT_TRUE(NULL == session->write_transaction());
125   {
126     WriteTransaction trans(dir, syncable::UNITTEST, __FILE__, __LINE__);
127     sessions::ScopedSetSessionWriteTransaction set_trans(session.get(), &trans);
128     EXPECT_TRUE(&trans == session->write_transaction());
129   }
130   db.TearDown();
131 }
132 
TEST_F(SyncSessionTest,MoreToSyncIfUnsyncedGreaterThanCommitted)133 TEST_F(SyncSessionTest, MoreToSyncIfUnsyncedGreaterThanCommitted) {
134   // If any forward progress was made during the session, and the number of
135   // unsynced handles still exceeds the number of commit ids we added, there is
136   // more to sync. For example, this occurs if we had more commit ids
137   // than could fit in a single commit batch.
138   EXPECT_FALSE(session_->HasMoreToSync());
139   OrderedCommitSet commit_set(routes_);
140   commit_set.AddCommitItem(0, syncable::Id(), syncable::BOOKMARKS);
141   status()->set_commit_set(commit_set);
142   EXPECT_FALSE(session_->HasMoreToSync());
143 
144   std::vector<int64> unsynced_handles;
145   unsynced_handles.push_back(1);
146   unsynced_handles.push_back(2);
147   status()->set_unsynced_handles(unsynced_handles);
148   EXPECT_FALSE(session_->HasMoreToSync());
149   status()->increment_num_successful_commits();
150   EXPECT_TRUE(session_->HasMoreToSync());
151 }
152 
TEST_F(SyncSessionTest,MoreToSyncIfConflictSetsBuilt)153 TEST_F(SyncSessionTest, MoreToSyncIfConflictSetsBuilt) {
154   // If we built conflict sets, then we need to loop back and try
155   // to get updates & commit again.
156   status()->update_conflict_sets_built(true);
157   EXPECT_TRUE(session_->HasMoreToSync());
158 }
159 
TEST_F(SyncSessionTest,MoreToDownloadIfDownloadFailed)160 TEST_F(SyncSessionTest, MoreToDownloadIfDownloadFailed) {
161   status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
162 
163   // When DownloadUpdatesCommand fails, these should be false.
164   EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
165   EXPECT_FALSE(status()->download_updates_succeeded());
166 
167   // Download updates has its own loop in the syncer; it shouldn't factor
168   // into HasMoreToSync.
169   EXPECT_FALSE(session_->HasMoreToSync());
170 }
171 
TEST_F(SyncSessionTest,MoreToDownloadIfGotChangesRemaining)172 TEST_F(SyncSessionTest, MoreToDownloadIfGotChangesRemaining) {
173   status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
174 
175   // When the server returns changes_remaining, that means there's
176   // more to download.
177   status()->mutable_updates_response()->mutable_get_updates()
178      ->set_changes_remaining(1000L);
179   EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
180   EXPECT_TRUE(status()->download_updates_succeeded());
181 
182   // Download updates has its own loop in the syncer; it shouldn't factor
183   // into HasMoreToSync.
184   EXPECT_FALSE(session_->HasMoreToSync());
185 }
186 
TEST_F(SyncSessionTest,MoreToDownloadIfGotNoChangesRemaining)187 TEST_F(SyncSessionTest, MoreToDownloadIfGotNoChangesRemaining) {
188   status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
189 
190   // When the server returns a timestamp, that means we're up to date.
191   status()->mutable_updates_response()->mutable_get_updates()
192       ->set_changes_remaining(0);
193   EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload());
194   EXPECT_TRUE(status()->download_updates_succeeded());
195 
196   // Download updates has its own loop in the syncer; it shouldn't factor
197   // into HasMoreToSync.
198   EXPECT_FALSE(session_->HasMoreToSync());
199 }
200 
TEST_F(SyncSessionTest,MoreToDownloadIfGotNoChangesRemainingForSubset)201 TEST_F(SyncSessionTest, MoreToDownloadIfGotNoChangesRemainingForSubset) {
202   status()->set_updates_request_types(ParamsMeaningJustOneEnabledType());
203 
204   // When the server returns a timestamp, that means we're up to date for that
205   // type.  But there may still be more to download if there are other
206   // datatypes that we didn't request on this go-round.
207   status()->mutable_updates_response()->mutable_get_updates()
208       ->set_changes_remaining(0);
209 
210   EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload());
211   EXPECT_TRUE(status()->download_updates_succeeded());
212 
213   // Download updates has its own loop in the syncer; it shouldn't factor
214   // into HasMoreToSync.
215   EXPECT_FALSE(session_->HasMoreToSync());
216 }
217 
TEST_F(SyncSessionTest,MoreToDownloadIfGotChangesRemainingAndEntries)218 TEST_F(SyncSessionTest, MoreToDownloadIfGotChangesRemainingAndEntries) {
219   status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
220   // The actual entry count should not factor into the HasMoreToSync
221   // determination.
222   status()->mutable_updates_response()->mutable_get_updates()->add_entries();
223   status()->mutable_updates_response()->mutable_get_updates()
224       ->set_changes_remaining(1000000L);;
225   EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload());
226   EXPECT_TRUE(status()->download_updates_succeeded());
227 
228   // Download updates has its own loop in the syncer; it shouldn't factor
229   // into HasMoreToSync.
230   EXPECT_FALSE(session_->HasMoreToSync());
231 }
232 
TEST_F(SyncSessionTest,MoreToDownloadIfGotNoChangesRemainingAndEntries)233 TEST_F(SyncSessionTest, MoreToDownloadIfGotNoChangesRemainingAndEntries) {
234   status()->set_updates_request_types(ParamsMeaningAllEnabledTypes());
235   // The actual entry count should not factor into the HasMoreToSync
236   // determination.
237   status()->mutable_updates_response()->mutable_get_updates()->add_entries();
238   status()->mutable_updates_response()->mutable_get_updates()
239       ->set_changes_remaining(0);
240   EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload());
241   EXPECT_TRUE(status()->download_updates_succeeded());
242 
243   // Download updates has its own loop in the syncer; it shouldn't factor
244   // into HasMoreToSync.
245   EXPECT_FALSE(session_->HasMoreToSync());
246 }
247 
TEST_F(SyncSessionTest,MoreToSyncIfConflictsResolved)248 TEST_F(SyncSessionTest, MoreToSyncIfConflictsResolved) {
249   // Conflict resolution happens after get updates and commit,
250   // so we need to loop back and get updates / commit again now
251   // that we have made forward progress.
252   status()->update_conflicts_resolved(true);
253   EXPECT_TRUE(session_->HasMoreToSync());
254 }
255 
TEST_F(SyncSessionTest,ResetTransientState)256 TEST_F(SyncSessionTest, ResetTransientState) {
257   status()->update_conflicts_resolved(true);
258   status()->increment_num_successful_commits();
259   EXPECT_TRUE(session_->HasMoreToSync());
260   session_->ResetTransientState();
261   EXPECT_FALSE(status()->conflicts_resolved());
262   EXPECT_FALSE(session_->HasMoreToSync());
263   EXPECT_FALSE(status()->TestAndClearIsDirty());
264 }
265 
TEST_F(SyncSessionTest,Coalesce)266 TEST_F(SyncSessionTest, Coalesce) {
267   std::vector<ModelSafeWorker*> workers_one, workers_two;
268   ModelSafeRoutingInfo routes_one, routes_two;
269   syncable::ModelTypePayloadMap one_type =
270       syncable::ModelTypePayloadMapFromBitSet(
271           ParamsMeaningJustOneEnabledType(),
272           std::string());
273   syncable::ModelTypePayloadMap all_types =
274       syncable::ModelTypePayloadMapFromBitSet(
275           ParamsMeaningAllEnabledTypes(),
276           std::string());
277   SyncSourceInfo source_one(sync_pb::GetUpdatesCallerInfo::PERIODIC, one_type);
278   SyncSourceInfo source_two(sync_pb::GetUpdatesCallerInfo::LOCAL, all_types);
279 
280   scoped_refptr<MockDBModelWorker> db_worker(new MockDBModelWorker());
281   scoped_refptr<MockUIModelWorker> ui_worker(new MockUIModelWorker());
282   workers_one.push_back(db_worker);
283   workers_two.push_back(db_worker);
284   workers_two.push_back(ui_worker);
285   routes_one[syncable::AUTOFILL] = GROUP_DB;
286   routes_two[syncable::AUTOFILL] = GROUP_DB;
287   routes_two[syncable::BOOKMARKS] = GROUP_UI;
288   SyncSession one(context_.get(), this, source_one, routes_one, workers_one);
289   SyncSession two(context_.get(), this, source_two, routes_two, workers_two);
290 
291   one.Coalesce(two);
292 
293   EXPECT_EQ(two.source().updates_source, one.source().updates_source);
294   EXPECT_EQ(all_types, one.source().types);
295   std::vector<ModelSafeWorker*>::const_iterator it_db =
296       std::find(one.workers().begin(), one.workers().end(), db_worker);
297   std::vector<ModelSafeWorker*>::const_iterator it_ui =
298       std::find(one.workers().begin(), one.workers().end(), ui_worker);
299   EXPECT_NE(it_db, one.workers().end());
300   EXPECT_NE(it_ui, one.workers().end());
301   EXPECT_EQ(routes_two, one.routing_info());
302 }
303 
TEST_F(SyncSessionTest,MakeTypePayloadMapFromBitSet)304 TEST_F(SyncSessionTest, MakeTypePayloadMapFromBitSet) {
305   syncable::ModelTypeBitSet types;
306   std::string payload = "test";
307   syncable::ModelTypePayloadMap types_with_payloads =
308       syncable::ModelTypePayloadMapFromBitSet(types,
309                                               payload);
310   EXPECT_TRUE(types_with_payloads.empty());
311 
312   types[syncable::BOOKMARKS] = true;
313   types[syncable::PASSWORDS] = true;
314   types[syncable::AUTOFILL] = true;
315   payload = "test2";
316   types_with_payloads = syncable::ModelTypePayloadMapFromBitSet(types, payload);
317 
318   ASSERT_EQ(3U, types_with_payloads.size());
319   EXPECT_EQ(types_with_payloads[syncable::BOOKMARKS], payload);
320   EXPECT_EQ(types_with_payloads[syncable::PASSWORDS], payload);
321   EXPECT_EQ(types_with_payloads[syncable::AUTOFILL], payload);
322 }
323 
TEST_F(SyncSessionTest,MakeTypePayloadMapFromRoutingInfo)324 TEST_F(SyncSessionTest, MakeTypePayloadMapFromRoutingInfo) {
325   std::string payload = "test";
326   syncable::ModelTypePayloadMap types_with_payloads
327       = syncable::ModelTypePayloadMapFromRoutingInfo(routes_, payload);
328   ASSERT_EQ(routes_.size(), types_with_payloads.size());
329   for (ModelSafeRoutingInfo::iterator iter = routes_.begin();
330        iter != routes_.end();
331        ++iter) {
332     EXPECT_EQ(payload, types_with_payloads[iter->first]);
333   }
334 }
335 
TEST_F(SyncSessionTest,CoalescePayloads)336 TEST_F(SyncSessionTest, CoalescePayloads) {
337   syncable::ModelTypePayloadMap original;
338   std::string empty_payload;
339   std::string payload1 = "payload1";
340   std::string payload2 = "payload2";
341   std::string payload3 = "payload3";
342   original[syncable::BOOKMARKS] = empty_payload;
343   original[syncable::PASSWORDS] = payload1;
344   original[syncable::AUTOFILL] = payload2;
345   original[syncable::THEMES] = payload3;
346 
347   syncable::ModelTypePayloadMap update;
348   update[syncable::BOOKMARKS] = empty_payload;  // Same.
349   update[syncable::PASSWORDS] = empty_payload;  // Overwrite with empty.
350   update[syncable::AUTOFILL] = payload1;        // Overwrite with non-empty.
351   update[syncable::SESSIONS] = payload2;        // New.
352   // Themes untouched.
353 
354   CoalescePayloads(&original, update);
355   ASSERT_EQ(5U, original.size());
356   EXPECT_EQ(empty_payload, original[syncable::BOOKMARKS]);
357   EXPECT_EQ(payload1, original[syncable::PASSWORDS]);
358   EXPECT_EQ(payload1, original[syncable::AUTOFILL]);
359   EXPECT_EQ(payload2, original[syncable::SESSIONS]);
360   EXPECT_EQ(payload3, original[syncable::THEMES]);
361 }
362 
363 }  // namespace
364 }  // namespace sessions
365 }  // namespace browser_sync
366