sync_session_unittest.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
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 "base/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 18using syncable::WriteTransaction; 19 20namespace browser_sync { 21namespace sessions { 22namespace { 23 24class SyncSessionTest : public testing::Test, 25 public SyncSession::Delegate, 26 public ModelSafeWorkerRegistrar { 27 public: 28 SyncSessionTest() : controller_invocations_allowed_(false) { 29 GetModelSafeRoutingInfo(&routes_); 30 } 31 32 SyncSession* MakeSession() { 33 return new SyncSession(context_.get(), this, SyncSourceInfo(), routes_, 34 std::vector<ModelSafeWorker*>()); 35 } 36 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 } 45 virtual void TearDown() { 46 session_.reset(); 47 context_.reset(); 48 } 49 50 virtual void OnSilencedUntil(const base::TimeTicks& silenced_until) { 51 FailControllerInvocationIfDisabled("OnSilencedUntil"); 52 } 53 virtual bool IsSyncingCurrentlySilenced() { 54 FailControllerInvocationIfDisabled("IsSyncingCurrentlySilenced"); 55 return false; 56 } 57 virtual void OnReceivedLongPollIntervalUpdate( 58 const base::TimeDelta& new_interval) { 59 FailControllerInvocationIfDisabled("OnReceivedLongPollIntervalUpdate"); 60 } 61 virtual void OnReceivedShortPollIntervalUpdate( 62 const base::TimeDelta& new_interval) { 63 FailControllerInvocationIfDisabled("OnReceivedShortPollIntervalUpdate"); 64 } 65 virtual void OnShouldStopSyncingPermanently() { 66 FailControllerInvocationIfDisabled("OnShouldStopSyncingPermanently"); 67 } 68 69 // ModelSafeWorkerRegistrar implementation. 70 virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) {} 71 virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) { 72 out->swap(routes_); 73 } 74 75 StatusController* status() { return session_->status_controller(); } 76 protected: 77 void FailControllerInvocationIfDisabled(const std::string& msg) { 78 if (!controller_invocations_allowed_) 79 FAIL() << msg; 80 } 81 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 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 101TEST_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 111TEST_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 133TEST_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 153TEST_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 160TEST_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 172TEST_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 187TEST_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 201TEST_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 218TEST_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 233TEST_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 248TEST_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 256TEST_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 266TEST_F(SyncSessionTest, Coalesce) { 267 std::vector<ModelSafeWorker*> workers_one, workers_two; 268 ModelSafeRoutingInfo routes_one, routes_two; 269 TypePayloadMap one_type = sessions::MakeTypePayloadMapFromBitSet( 270 ParamsMeaningJustOneEnabledType(), 271 std::string());; 272 TypePayloadMap all_types = sessions::MakeTypePayloadMapFromBitSet( 273 ParamsMeaningAllEnabledTypes(), 274 std::string());; 275 SyncSourceInfo source_one(sync_pb::GetUpdatesCallerInfo::PERIODIC, one_type); 276 SyncSourceInfo source_two(sync_pb::GetUpdatesCallerInfo::LOCAL, all_types); 277 278 scoped_refptr<MockDBModelWorker> db_worker(new MockDBModelWorker()); 279 scoped_refptr<MockUIModelWorker> ui_worker(new MockUIModelWorker()); 280 workers_one.push_back(db_worker); 281 workers_two.push_back(db_worker); 282 workers_two.push_back(ui_worker); 283 routes_one[syncable::AUTOFILL] = GROUP_DB; 284 routes_two[syncable::AUTOFILL] = GROUP_DB; 285 routes_two[syncable::BOOKMARKS] = GROUP_UI; 286 SyncSession one(context_.get(), this, source_one, routes_one, workers_one); 287 SyncSession two(context_.get(), this, source_two, routes_two, workers_two); 288 289 one.Coalesce(two); 290 291 EXPECT_EQ(two.source().updates_source, one.source().updates_source); 292 EXPECT_EQ(all_types, one.source().types); 293 std::vector<ModelSafeWorker*>::const_iterator it_db = 294 std::find(one.workers().begin(), one.workers().end(), db_worker); 295 std::vector<ModelSafeWorker*>::const_iterator it_ui = 296 std::find(one.workers().begin(), one.workers().end(), ui_worker); 297 EXPECT_NE(it_db, one.workers().end()); 298 EXPECT_NE(it_ui, one.workers().end()); 299 EXPECT_EQ(routes_two, one.routing_info()); 300} 301 302TEST_F(SyncSessionTest, MakeTypePayloadMapFromBitSet) { 303 syncable::ModelTypeBitSet types; 304 std::string payload = "test"; 305 TypePayloadMap types_with_payloads = MakeTypePayloadMapFromBitSet(types, 306 payload); 307 EXPECT_TRUE(types_with_payloads.empty()); 308 309 types[syncable::BOOKMARKS] = true; 310 types[syncable::PASSWORDS] = true; 311 types[syncable::AUTOFILL] = true; 312 payload = "test2"; 313 types_with_payloads = MakeTypePayloadMapFromBitSet(types, payload); 314 315 ASSERT_EQ(3U, types_with_payloads.size()); 316 EXPECT_EQ(types_with_payloads[syncable::BOOKMARKS], payload); 317 EXPECT_EQ(types_with_payloads[syncable::PASSWORDS], payload); 318 EXPECT_EQ(types_with_payloads[syncable::AUTOFILL], payload); 319} 320 321TEST_F(SyncSessionTest, MakeTypePayloadMapFromRoutingInfo) { 322 std::string payload = "test"; 323 TypePayloadMap types_with_payloads 324 = MakeTypePayloadMapFromRoutingInfo(routes_, payload); 325 ASSERT_EQ(routes_.size(), types_with_payloads.size()); 326 for (ModelSafeRoutingInfo::iterator iter = routes_.begin(); 327 iter != routes_.end(); 328 ++iter) { 329 EXPECT_EQ(payload, types_with_payloads[iter->first]); 330 } 331} 332 333TEST_F(SyncSessionTest, CoalescePayloads) { 334 TypePayloadMap original; 335 std::string empty_payload; 336 std::string payload1 = "payload1"; 337 std::string payload2 = "payload2"; 338 std::string payload3 = "payload3"; 339 original[syncable::BOOKMARKS] = empty_payload; 340 original[syncable::PASSWORDS] = payload1; 341 original[syncable::AUTOFILL] = payload2; 342 original[syncable::THEMES] = payload3; 343 344 TypePayloadMap update; 345 update[syncable::BOOKMARKS] = empty_payload; // Same. 346 update[syncable::PASSWORDS] = empty_payload; // Overwrite with empty. 347 update[syncable::AUTOFILL] = payload1; // Overwrite with non-empty. 348 update[syncable::SESSIONS] = payload2; // New. 349 // Themes untouched. 350 351 CoalescePayloads(&original, update); 352 ASSERT_EQ(5U, original.size()); 353 EXPECT_EQ(empty_payload, original[syncable::BOOKMARKS]); 354 EXPECT_EQ(payload1, original[syncable::PASSWORDS]); 355 EXPECT_EQ(payload1, original[syncable::AUTOFILL]); 356 EXPECT_EQ(payload2, original[syncable::SESSIONS]); 357 EXPECT_EQ(payload3, original[syncable::THEMES]); 358} 359 360} // namespace 361} // namespace sessions 362} // namespace browser_sync 363