| OLD | NEW |
| (Empty) |
| 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 "chrome/browser/sync/sessions/sync_session.h" | |
| 6 | |
| 7 #include "base/compiler_specific.h" | |
| 8 #include "base/location.h" | |
| 9 #include "base/memory/ref_counted.h" | |
| 10 #include "base/message_loop.h" | |
| 11 #include "chrome/browser/sync/engine/conflict_resolver.h" | |
| 12 #include "chrome/browser/sync/engine/syncer_types.h" | |
| 13 #include "chrome/browser/sync/sessions/session_state.h" | |
| 14 #include "chrome/browser/sync/sessions/status_controller.h" | |
| 15 #include "chrome/browser/sync/syncable/model_type.h" | |
| 16 #include "chrome/browser/sync/syncable/syncable.h" | |
| 17 #include "chrome/browser/sync/syncable/syncable_id.h" | |
| 18 #include "chrome/browser/sync/test/engine/fake_model_worker.h" | |
| 19 #include "chrome/browser/sync/test/engine/test_directory_setter_upper.h" | |
| 20 #include "chrome/browser/sync/test/fake_extensions_activity_monitor.h" | |
| 21 #include "testing/gtest/include/gtest/gtest.h" | |
| 22 | |
| 23 using syncable::WriteTransaction; | |
| 24 | |
| 25 namespace browser_sync { | |
| 26 namespace sessions { | |
| 27 namespace { | |
| 28 | |
| 29 class SyncSessionTest : public testing::Test, | |
| 30 public SyncSession::Delegate, | |
| 31 public ModelSafeWorkerRegistrar { | |
| 32 public: | |
| 33 SyncSessionTest() : controller_invocations_allowed_(false) {} | |
| 34 | |
| 35 SyncSession* MakeSession() { | |
| 36 std::vector<ModelSafeWorker*> workers; | |
| 37 GetWorkers(&workers); | |
| 38 return new SyncSession(context_.get(), this, SyncSourceInfo(), | |
| 39 routes_, workers); | |
| 40 } | |
| 41 | |
| 42 virtual void SetUp() { | |
| 43 context_.reset( | |
| 44 new SyncSessionContext( | |
| 45 NULL, NULL, this, &extensions_activity_monitor_, | |
| 46 std::vector<SyncEngineEventListener*>(), NULL)); | |
| 47 routes_.clear(); | |
| 48 routes_[syncable::BOOKMARKS] = GROUP_UI; | |
| 49 routes_[syncable::AUTOFILL] = GROUP_DB; | |
| 50 scoped_refptr<ModelSafeWorker> passive_worker( | |
| 51 new FakeModelWorker(GROUP_PASSIVE)); | |
| 52 scoped_refptr<ModelSafeWorker> ui_worker( | |
| 53 new FakeModelWorker(GROUP_UI)); | |
| 54 scoped_refptr<ModelSafeWorker> db_worker( | |
| 55 new FakeModelWorker(GROUP_DB)); | |
| 56 workers_.clear(); | |
| 57 workers_.push_back(passive_worker); | |
| 58 workers_.push_back(ui_worker); | |
| 59 workers_.push_back(db_worker); | |
| 60 session_.reset(MakeSession()); | |
| 61 } | |
| 62 virtual void TearDown() { | |
| 63 session_.reset(); | |
| 64 context_.reset(); | |
| 65 } | |
| 66 | |
| 67 virtual void OnSilencedUntil(const base::TimeTicks& silenced_until) OVERRIDE { | |
| 68 FailControllerInvocationIfDisabled("OnSilencedUntil"); | |
| 69 } | |
| 70 virtual bool IsSyncingCurrentlySilenced() OVERRIDE { | |
| 71 FailControllerInvocationIfDisabled("IsSyncingCurrentlySilenced"); | |
| 72 return false; | |
| 73 } | |
| 74 virtual void OnReceivedLongPollIntervalUpdate( | |
| 75 const base::TimeDelta& new_interval) OVERRIDE { | |
| 76 FailControllerInvocationIfDisabled("OnReceivedLongPollIntervalUpdate"); | |
| 77 } | |
| 78 virtual void OnReceivedShortPollIntervalUpdate( | |
| 79 const base::TimeDelta& new_interval) OVERRIDE { | |
| 80 FailControllerInvocationIfDisabled("OnReceivedShortPollIntervalUpdate"); | |
| 81 } | |
| 82 virtual void OnReceivedSessionsCommitDelay( | |
| 83 const base::TimeDelta& new_delay) OVERRIDE { | |
| 84 FailControllerInvocationIfDisabled("OnReceivedSessionsCommitDelay"); | |
| 85 } | |
| 86 virtual void OnShouldStopSyncingPermanently() OVERRIDE { | |
| 87 FailControllerInvocationIfDisabled("OnShouldStopSyncingPermanently"); | |
| 88 } | |
| 89 virtual void OnSyncProtocolError( | |
| 90 const sessions::SyncSessionSnapshot& snapshot) { | |
| 91 FailControllerInvocationIfDisabled("SyncProtocolError"); | |
| 92 } | |
| 93 | |
| 94 // ModelSafeWorkerRegistrar implementation. | |
| 95 virtual void GetWorkers(std::vector<ModelSafeWorker*>* out) OVERRIDE { | |
| 96 out->clear(); | |
| 97 for (std::vector<scoped_refptr<ModelSafeWorker> >::const_iterator it = | |
| 98 workers_.begin(); it != workers_.end(); ++it) { | |
| 99 out->push_back(it->get()); | |
| 100 } | |
| 101 } | |
| 102 virtual void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) OVERRIDE { | |
| 103 *out = routes_; | |
| 104 } | |
| 105 | |
| 106 StatusController* status() { return session_->mutable_status_controller(); } | |
| 107 protected: | |
| 108 void FailControllerInvocationIfDisabled(const std::string& msg) { | |
| 109 if (!controller_invocations_allowed_) | |
| 110 FAIL() << msg; | |
| 111 } | |
| 112 | |
| 113 syncable::ModelTypeSet ParamsMeaningAllEnabledTypes() { | |
| 114 syncable::ModelTypeSet request_params( | |
| 115 syncable::BOOKMARKS, syncable::AUTOFILL); | |
| 116 return request_params; | |
| 117 } | |
| 118 | |
| 119 syncable::ModelTypeSet ParamsMeaningJustOneEnabledType() { | |
| 120 return syncable::ModelTypeSet(syncable::AUTOFILL); | |
| 121 } | |
| 122 | |
| 123 MessageLoop message_loop_; | |
| 124 bool controller_invocations_allowed_; | |
| 125 scoped_ptr<SyncSession> session_; | |
| 126 scoped_ptr<SyncSessionContext> context_; | |
| 127 std::vector<scoped_refptr<ModelSafeWorker> > workers_; | |
| 128 ModelSafeRoutingInfo routes_; | |
| 129 FakeExtensionsActivityMonitor extensions_activity_monitor_; | |
| 130 }; | |
| 131 | |
| 132 TEST_F(SyncSessionTest, EnabledGroupsEmpty) { | |
| 133 routes_.clear(); | |
| 134 workers_.clear(); | |
| 135 scoped_ptr<SyncSession> session(MakeSession()); | |
| 136 std::set<ModelSafeGroup> expected_enabled_groups; | |
| 137 expected_enabled_groups.insert(GROUP_PASSIVE); | |
| 138 EXPECT_EQ(expected_enabled_groups, session->GetEnabledGroups()); | |
| 139 } | |
| 140 | |
| 141 TEST_F(SyncSessionTest, EnabledGroups) { | |
| 142 scoped_ptr<SyncSession> session(MakeSession()); | |
| 143 std::set<ModelSafeGroup> expected_enabled_groups; | |
| 144 expected_enabled_groups.insert(GROUP_PASSIVE); | |
| 145 expected_enabled_groups.insert(GROUP_UI); | |
| 146 expected_enabled_groups.insert(GROUP_DB); | |
| 147 EXPECT_EQ(expected_enabled_groups, session->GetEnabledGroups()); | |
| 148 } | |
| 149 | |
| 150 TEST_F(SyncSessionTest, EnabledGroupsWithConflictsEmpty) { | |
| 151 scoped_ptr<SyncSession> session(MakeSession()); | |
| 152 // Auto-create conflict progress. This shouldn't put that group in | |
| 153 // conflict. | |
| 154 session->mutable_status_controller()-> | |
| 155 GetUnrestrictedMutableConflictProgressForTest(GROUP_PASSIVE); | |
| 156 EXPECT_TRUE(session->GetEnabledGroupsWithConflicts().empty()); | |
| 157 } | |
| 158 | |
| 159 TEST_F(SyncSessionTest, EnabledGroupsWithConflicts) { | |
| 160 scoped_ptr<SyncSession> session(MakeSession()); | |
| 161 // Put GROUP_UI in conflict. | |
| 162 session->mutable_status_controller()-> | |
| 163 GetUnrestrictedMutableConflictProgressForTest(GROUP_UI)-> | |
| 164 AddSimpleConflictingItemById(syncable::Id()); | |
| 165 std::set<ModelSafeGroup> expected_enabled_groups_with_conflicts; | |
| 166 expected_enabled_groups_with_conflicts.insert(GROUP_UI); | |
| 167 EXPECT_EQ(expected_enabled_groups_with_conflicts, | |
| 168 session->GetEnabledGroupsWithConflicts()); | |
| 169 } | |
| 170 | |
| 171 TEST_F(SyncSessionTest, ScopedContextHelpers) { | |
| 172 ConflictResolver resolver; | |
| 173 EXPECT_FALSE(context_->resolver()); | |
| 174 { | |
| 175 ScopedSessionContextConflictResolver s_resolver(context_.get(), &resolver); | |
| 176 EXPECT_EQ(&resolver, context_->resolver()); | |
| 177 } | |
| 178 EXPECT_FALSE(context_->resolver()); | |
| 179 } | |
| 180 | |
| 181 TEST_F(SyncSessionTest, SetWriteTransaction) { | |
| 182 TestDirectorySetterUpper dir_maker; | |
| 183 dir_maker.SetUp(); | |
| 184 syncable::Directory* directory = dir_maker.directory(); | |
| 185 | |
| 186 scoped_ptr<SyncSession> session(MakeSession()); | |
| 187 EXPECT_TRUE(NULL == session->write_transaction()); | |
| 188 { | |
| 189 WriteTransaction trans(FROM_HERE, syncable::UNITTEST, directory); | |
| 190 sessions::ScopedSetSessionWriteTransaction set_trans(session.get(), &trans); | |
| 191 EXPECT_TRUE(&trans == session->write_transaction()); | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 TEST_F(SyncSessionTest, MoreToSyncIfUnsyncedGreaterThanCommitted) { | |
| 196 // If any forward progress was made during the session, and the number of | |
| 197 // unsynced handles still exceeds the number of commit ids we added, there is | |
| 198 // more to sync. For example, this occurs if we had more commit ids | |
| 199 // than could fit in a single commit batch. | |
| 200 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 201 OrderedCommitSet commit_set(routes_); | |
| 202 commit_set.AddCommitItem(0, syncable::Id(), syncable::BOOKMARKS); | |
| 203 status()->set_commit_set(commit_set); | |
| 204 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 205 | |
| 206 std::vector<int64> unsynced_handles; | |
| 207 unsynced_handles.push_back(1); | |
| 208 unsynced_handles.push_back(2); | |
| 209 status()->set_unsynced_handles(unsynced_handles); | |
| 210 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 211 status()->increment_num_successful_commits(); | |
| 212 EXPECT_TRUE(session_->HasMoreToSync()); | |
| 213 } | |
| 214 | |
| 215 TEST_F(SyncSessionTest, MoreToDownloadIfDownloadFailed) { | |
| 216 status()->set_updates_request_types(ParamsMeaningAllEnabledTypes()); | |
| 217 | |
| 218 // When DownloadUpdatesCommand fails, these should be false. | |
| 219 EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload()); | |
| 220 EXPECT_FALSE(status()->download_updates_succeeded()); | |
| 221 | |
| 222 // Download updates has its own loop in the syncer; it shouldn't factor | |
| 223 // into HasMoreToSync. | |
| 224 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 225 } | |
| 226 | |
| 227 TEST_F(SyncSessionTest, MoreToDownloadIfGotChangesRemaining) { | |
| 228 status()->set_updates_request_types(ParamsMeaningAllEnabledTypes()); | |
| 229 | |
| 230 // When the server returns changes_remaining, that means there's | |
| 231 // more to download. | |
| 232 status()->mutable_updates_response()->mutable_get_updates() | |
| 233 ->set_changes_remaining(1000L); | |
| 234 EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload()); | |
| 235 EXPECT_TRUE(status()->download_updates_succeeded()); | |
| 236 | |
| 237 // Download updates has its own loop in the syncer; it shouldn't factor | |
| 238 // into HasMoreToSync. | |
| 239 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 240 } | |
| 241 | |
| 242 TEST_F(SyncSessionTest, MoreToDownloadIfGotNoChangesRemaining) { | |
| 243 status()->set_updates_request_types(ParamsMeaningAllEnabledTypes()); | |
| 244 | |
| 245 // When the server returns a timestamp, that means we're up to date. | |
| 246 status()->mutable_updates_response()->mutable_get_updates() | |
| 247 ->set_changes_remaining(0); | |
| 248 EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload()); | |
| 249 EXPECT_TRUE(status()->download_updates_succeeded()); | |
| 250 | |
| 251 // Download updates has its own loop in the syncer; it shouldn't factor | |
| 252 // into HasMoreToSync. | |
| 253 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 254 } | |
| 255 | |
| 256 TEST_F(SyncSessionTest, MoreToDownloadIfGotNoChangesRemainingForSubset) { | |
| 257 status()->set_updates_request_types(ParamsMeaningJustOneEnabledType()); | |
| 258 | |
| 259 // When the server returns a timestamp, that means we're up to date for that | |
| 260 // type. But there may still be more to download if there are other | |
| 261 // datatypes that we didn't request on this go-round. | |
| 262 status()->mutable_updates_response()->mutable_get_updates() | |
| 263 ->set_changes_remaining(0); | |
| 264 | |
| 265 EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload()); | |
| 266 EXPECT_TRUE(status()->download_updates_succeeded()); | |
| 267 | |
| 268 // Download updates has its own loop in the syncer; it shouldn't factor | |
| 269 // into HasMoreToSync. | |
| 270 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 271 } | |
| 272 | |
| 273 TEST_F(SyncSessionTest, MoreToDownloadIfGotChangesRemainingAndEntries) { | |
| 274 status()->set_updates_request_types(ParamsMeaningAllEnabledTypes()); | |
| 275 // The actual entry count should not factor into the HasMoreToSync | |
| 276 // determination. | |
| 277 status()->mutable_updates_response()->mutable_get_updates()->add_entries(); | |
| 278 status()->mutable_updates_response()->mutable_get_updates() | |
| 279 ->set_changes_remaining(1000000L);; | |
| 280 EXPECT_FALSE(status()->ServerSaysNothingMoreToDownload()); | |
| 281 EXPECT_TRUE(status()->download_updates_succeeded()); | |
| 282 | |
| 283 // Download updates has its own loop in the syncer; it shouldn't factor | |
| 284 // into HasMoreToSync. | |
| 285 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 286 } | |
| 287 | |
| 288 TEST_F(SyncSessionTest, MoreToDownloadIfGotNoChangesRemainingAndEntries) { | |
| 289 status()->set_updates_request_types(ParamsMeaningAllEnabledTypes()); | |
| 290 // The actual entry count should not factor into the HasMoreToSync | |
| 291 // determination. | |
| 292 status()->mutable_updates_response()->mutable_get_updates()->add_entries(); | |
| 293 status()->mutable_updates_response()->mutable_get_updates() | |
| 294 ->set_changes_remaining(0); | |
| 295 EXPECT_TRUE(status()->ServerSaysNothingMoreToDownload()); | |
| 296 EXPECT_TRUE(status()->download_updates_succeeded()); | |
| 297 | |
| 298 // Download updates has its own loop in the syncer; it shouldn't factor | |
| 299 // into HasMoreToSync. | |
| 300 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 301 } | |
| 302 | |
| 303 TEST_F(SyncSessionTest, MoreToSyncIfConflictsResolved) { | |
| 304 // Conflict resolution happens after get updates and commit, | |
| 305 // so we need to loop back and get updates / commit again now | |
| 306 // that we have made forward progress. | |
| 307 status()->update_conflicts_resolved(true); | |
| 308 EXPECT_TRUE(session_->HasMoreToSync()); | |
| 309 } | |
| 310 | |
| 311 TEST_F(SyncSessionTest, ResetTransientState) { | |
| 312 status()->update_conflicts_resolved(true); | |
| 313 status()->increment_num_successful_commits(); | |
| 314 EXPECT_TRUE(session_->HasMoreToSync()); | |
| 315 session_->PrepareForAnotherSyncCycle(); | |
| 316 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION, | |
| 317 session_->source().updates_source); | |
| 318 EXPECT_FALSE(status()->conflicts_resolved()); | |
| 319 EXPECT_FALSE(session_->HasMoreToSync()); | |
| 320 EXPECT_FALSE(status()->TestAndClearIsDirty()); | |
| 321 } | |
| 322 | |
| 323 TEST_F(SyncSessionTest, Coalesce) { | |
| 324 std::vector<ModelSafeWorker*> workers_one, workers_two; | |
| 325 ModelSafeRoutingInfo routes_one, routes_two; | |
| 326 syncable::ModelTypePayloadMap one_type = | |
| 327 syncable::ModelTypePayloadMapFromEnumSet( | |
| 328 ParamsMeaningJustOneEnabledType(), | |
| 329 std::string()); | |
| 330 syncable::ModelTypePayloadMap all_types = | |
| 331 syncable::ModelTypePayloadMapFromEnumSet( | |
| 332 ParamsMeaningAllEnabledTypes(), | |
| 333 std::string()); | |
| 334 SyncSourceInfo source_one(sync_pb::GetUpdatesCallerInfo::PERIODIC, one_type); | |
| 335 SyncSourceInfo source_two(sync_pb::GetUpdatesCallerInfo::LOCAL, all_types); | |
| 336 | |
| 337 scoped_refptr<ModelSafeWorker> passive_worker( | |
| 338 new FakeModelWorker(GROUP_PASSIVE)); | |
| 339 scoped_refptr<ModelSafeWorker> db_worker(new FakeModelWorker(GROUP_DB)); | |
| 340 scoped_refptr<ModelSafeWorker> ui_worker(new FakeModelWorker(GROUP_UI)); | |
| 341 workers_one.push_back(passive_worker); | |
| 342 workers_one.push_back(db_worker); | |
| 343 workers_two.push_back(passive_worker); | |
| 344 workers_two.push_back(db_worker); | |
| 345 workers_two.push_back(ui_worker); | |
| 346 routes_one[syncable::AUTOFILL] = GROUP_DB; | |
| 347 routes_two[syncable::AUTOFILL] = GROUP_DB; | |
| 348 routes_two[syncable::BOOKMARKS] = GROUP_UI; | |
| 349 SyncSession one(context_.get(), this, source_one, routes_one, workers_one); | |
| 350 SyncSession two(context_.get(), this, source_two, routes_two, workers_two); | |
| 351 | |
| 352 std::set<ModelSafeGroup> expected_enabled_groups_one; | |
| 353 expected_enabled_groups_one.insert(GROUP_PASSIVE); | |
| 354 expected_enabled_groups_one.insert(GROUP_DB); | |
| 355 | |
| 356 std::set<ModelSafeGroup> expected_enabled_groups_two; | |
| 357 expected_enabled_groups_two.insert(GROUP_PASSIVE); | |
| 358 expected_enabled_groups_two.insert(GROUP_DB); | |
| 359 expected_enabled_groups_two.insert(GROUP_UI); | |
| 360 | |
| 361 EXPECT_EQ(expected_enabled_groups_one, one.GetEnabledGroups()); | |
| 362 EXPECT_EQ(expected_enabled_groups_two, two.GetEnabledGroups()); | |
| 363 | |
| 364 one.Coalesce(two); | |
| 365 | |
| 366 EXPECT_EQ(expected_enabled_groups_two, one.GetEnabledGroups()); | |
| 367 EXPECT_EQ(expected_enabled_groups_two, two.GetEnabledGroups()); | |
| 368 | |
| 369 EXPECT_EQ(two.source().updates_source, one.source().updates_source); | |
| 370 EXPECT_EQ(all_types, one.source().types); | |
| 371 std::vector<ModelSafeWorker*>::const_iterator it_db = | |
| 372 std::find(one.workers().begin(), one.workers().end(), db_worker); | |
| 373 std::vector<ModelSafeWorker*>::const_iterator it_ui = | |
| 374 std::find(one.workers().begin(), one.workers().end(), ui_worker); | |
| 375 EXPECT_NE(it_db, one.workers().end()); | |
| 376 EXPECT_NE(it_ui, one.workers().end()); | |
| 377 EXPECT_EQ(routes_two, one.routing_info()); | |
| 378 } | |
| 379 | |
| 380 TEST_F(SyncSessionTest, RebaseRoutingInfoWithLatestRemoveOneType) { | |
| 381 std::vector<ModelSafeWorker*> workers_one, workers_two; | |
| 382 ModelSafeRoutingInfo routes_one, routes_two; | |
| 383 syncable::ModelTypePayloadMap one_type = | |
| 384 syncable::ModelTypePayloadMapFromEnumSet( | |
| 385 ParamsMeaningJustOneEnabledType(), | |
| 386 std::string()); | |
| 387 syncable::ModelTypePayloadMap all_types = | |
| 388 syncable::ModelTypePayloadMapFromEnumSet( | |
| 389 ParamsMeaningAllEnabledTypes(), | |
| 390 std::string()); | |
| 391 SyncSourceInfo source_one(sync_pb::GetUpdatesCallerInfo::PERIODIC, one_type); | |
| 392 SyncSourceInfo source_two(sync_pb::GetUpdatesCallerInfo::LOCAL, all_types); | |
| 393 | |
| 394 scoped_refptr<ModelSafeWorker> passive_worker( | |
| 395 new FakeModelWorker(GROUP_PASSIVE)); | |
| 396 scoped_refptr<ModelSafeWorker> db_worker(new FakeModelWorker(GROUP_DB)); | |
| 397 scoped_refptr<ModelSafeWorker> ui_worker(new FakeModelWorker(GROUP_UI)); | |
| 398 workers_one.push_back(passive_worker); | |
| 399 workers_one.push_back(db_worker); | |
| 400 workers_two.push_back(passive_worker); | |
| 401 workers_two.push_back(db_worker); | |
| 402 workers_two.push_back(ui_worker); | |
| 403 routes_one[syncable::AUTOFILL] = GROUP_DB; | |
| 404 routes_two[syncable::AUTOFILL] = GROUP_DB; | |
| 405 routes_two[syncable::BOOKMARKS] = GROUP_UI; | |
| 406 SyncSession one(context_.get(), this, source_one, routes_one, workers_one); | |
| 407 SyncSession two(context_.get(), this, source_two, routes_two, workers_two); | |
| 408 | |
| 409 std::set<ModelSafeGroup> expected_enabled_groups_one; | |
| 410 expected_enabled_groups_one.insert(GROUP_PASSIVE); | |
| 411 expected_enabled_groups_one.insert(GROUP_DB); | |
| 412 | |
| 413 std::set<ModelSafeGroup> expected_enabled_groups_two; | |
| 414 expected_enabled_groups_two.insert(GROUP_PASSIVE); | |
| 415 expected_enabled_groups_two.insert(GROUP_DB); | |
| 416 expected_enabled_groups_two.insert(GROUP_UI); | |
| 417 | |
| 418 EXPECT_EQ(expected_enabled_groups_one, one.GetEnabledGroups()); | |
| 419 EXPECT_EQ(expected_enabled_groups_two, two.GetEnabledGroups()); | |
| 420 | |
| 421 two.RebaseRoutingInfoWithLatest(one); | |
| 422 | |
| 423 EXPECT_EQ(expected_enabled_groups_one, one.GetEnabledGroups()); | |
| 424 EXPECT_EQ(expected_enabled_groups_one, two.GetEnabledGroups()); | |
| 425 | |
| 426 // Make sure the source has not been touched. | |
| 427 EXPECT_EQ(two.source().updates_source, | |
| 428 sync_pb::GetUpdatesCallerInfo::LOCAL); | |
| 429 | |
| 430 // Make sure the payload is reduced to one. | |
| 431 EXPECT_EQ(one_type, two.source().types); | |
| 432 | |
| 433 // Make sure the workers are udpated. | |
| 434 std::vector<ModelSafeWorker*>::const_iterator it_db = | |
| 435 std::find(two.workers().begin(), two.workers().end(), db_worker); | |
| 436 std::vector<ModelSafeWorker*>::const_iterator it_ui = | |
| 437 std::find(two.workers().begin(), two.workers().end(), ui_worker); | |
| 438 EXPECT_NE(it_db, two.workers().end()); | |
| 439 EXPECT_EQ(it_ui, two.workers().end()); | |
| 440 EXPECT_EQ(two.workers().size(), 2U); | |
| 441 | |
| 442 // Make sure the model safe routing info is reduced to one type. | |
| 443 ModelSafeRoutingInfo::const_iterator it = | |
| 444 two.routing_info().find(syncable::AUTOFILL); | |
| 445 // Note that attempting to use EXPECT_NE would fail for an Android build due | |
| 446 // to seeming incompatibility with gtest and stlport. | |
| 447 EXPECT_TRUE(it != two.routing_info().end()); | |
| 448 EXPECT_EQ(it->second, GROUP_DB); | |
| 449 EXPECT_EQ(two.routing_info().size(), 1U); | |
| 450 } | |
| 451 | |
| 452 TEST_F(SyncSessionTest, RebaseRoutingInfoWithLatestWithSameType) { | |
| 453 std::vector<ModelSafeWorker*> workers_first, workers_second; | |
| 454 ModelSafeRoutingInfo routes_first, routes_second; | |
| 455 syncable::ModelTypePayloadMap all_types = | |
| 456 syncable::ModelTypePayloadMapFromEnumSet( | |
| 457 ParamsMeaningAllEnabledTypes(), | |
| 458 std::string()); | |
| 459 SyncSourceInfo source_first(sync_pb::GetUpdatesCallerInfo::PERIODIC, | |
| 460 all_types); | |
| 461 SyncSourceInfo source_second(sync_pb::GetUpdatesCallerInfo::LOCAL, | |
| 462 all_types); | |
| 463 | |
| 464 scoped_refptr<ModelSafeWorker> passive_worker( | |
| 465 new FakeModelWorker(GROUP_PASSIVE)); | |
| 466 scoped_refptr<FakeModelWorker> db_worker(new FakeModelWorker(GROUP_DB)); | |
| 467 scoped_refptr<FakeModelWorker> ui_worker(new FakeModelWorker(GROUP_UI)); | |
| 468 workers_first.push_back(passive_worker); | |
| 469 workers_first.push_back(db_worker); | |
| 470 workers_first.push_back(ui_worker); | |
| 471 workers_second.push_back(passive_worker); | |
| 472 workers_second.push_back(db_worker); | |
| 473 workers_second.push_back(ui_worker); | |
| 474 routes_first[syncable::AUTOFILL] = GROUP_DB; | |
| 475 routes_first[syncable::BOOKMARKS] = GROUP_UI; | |
| 476 routes_second[syncable::AUTOFILL] = GROUP_DB; | |
| 477 routes_second[syncable::BOOKMARKS] = GROUP_UI; | |
| 478 SyncSession first(context_.get(), this, source_first, routes_first, | |
| 479 workers_first); | |
| 480 SyncSession second(context_.get(), this, source_second, routes_second, | |
| 481 workers_second); | |
| 482 | |
| 483 std::set<ModelSafeGroup> expected_enabled_groups; | |
| 484 expected_enabled_groups.insert(GROUP_PASSIVE); | |
| 485 expected_enabled_groups.insert(GROUP_DB); | |
| 486 expected_enabled_groups.insert(GROUP_UI); | |
| 487 | |
| 488 EXPECT_EQ(expected_enabled_groups, first.GetEnabledGroups()); | |
| 489 EXPECT_EQ(expected_enabled_groups, second.GetEnabledGroups()); | |
| 490 | |
| 491 second.RebaseRoutingInfoWithLatest(first); | |
| 492 | |
| 493 EXPECT_EQ(expected_enabled_groups, first.GetEnabledGroups()); | |
| 494 EXPECT_EQ(expected_enabled_groups, second.GetEnabledGroups()); | |
| 495 | |
| 496 // Make sure the source has not been touched. | |
| 497 EXPECT_EQ(second.source().updates_source, | |
| 498 sync_pb::GetUpdatesCallerInfo::LOCAL); | |
| 499 | |
| 500 // Make sure our payload is still the same. | |
| 501 EXPECT_EQ(all_types, second.source().types); | |
| 502 | |
| 503 // Make sure the workers are still the same. | |
| 504 std::vector<ModelSafeWorker*>::const_iterator it_passive = | |
| 505 std::find(second.workers().begin(), second.workers().end(), | |
| 506 passive_worker); | |
| 507 std::vector<ModelSafeWorker*>::const_iterator it_db = | |
| 508 std::find(second.workers().begin(), second.workers().end(), db_worker); | |
| 509 std::vector<ModelSafeWorker*>::const_iterator it_ui = | |
| 510 std::find(second.workers().begin(), second.workers().end(), ui_worker); | |
| 511 EXPECT_NE(it_passive, second.workers().end()); | |
| 512 EXPECT_NE(it_db, second.workers().end()); | |
| 513 EXPECT_NE(it_ui, second.workers().end()); | |
| 514 EXPECT_EQ(second.workers().size(), 3U); | |
| 515 | |
| 516 // Make sure the model safe routing info is reduced to first type. | |
| 517 ModelSafeRoutingInfo::const_iterator it1 = | |
| 518 second.routing_info().find(syncable::AUTOFILL); | |
| 519 ModelSafeRoutingInfo::const_iterator it2 = | |
| 520 second.routing_info().find(syncable::BOOKMARKS); | |
| 521 | |
| 522 // Note that attempting to use EXPECT_NE would fail for an Android build due | |
| 523 // to seeming incompatibility with gtest and stlport. | |
| 524 EXPECT_TRUE(it1 != second.routing_info().end()); | |
| 525 EXPECT_EQ(it1->second, GROUP_DB); | |
| 526 | |
| 527 // Note that attempting to use EXPECT_NE would fail for an Android build due | |
| 528 // to seeming incompatibility with gtest and stlport. | |
| 529 EXPECT_TRUE(it2 != second.routing_info().end()); | |
| 530 EXPECT_EQ(it2->second, GROUP_UI); | |
| 531 EXPECT_EQ(second.routing_info().size(), 2U); | |
| 532 } | |
| 533 | |
| 534 | |
| 535 TEST_F(SyncSessionTest, MakeTypePayloadMapFromBitSet) { | |
| 536 syncable::ModelTypeSet types; | |
| 537 std::string payload = "test"; | |
| 538 syncable::ModelTypePayloadMap types_with_payloads = | |
| 539 syncable::ModelTypePayloadMapFromEnumSet(types, payload); | |
| 540 EXPECT_TRUE(types_with_payloads.empty()); | |
| 541 | |
| 542 types.Put(syncable::BOOKMARKS); | |
| 543 types.Put(syncable::PASSWORDS); | |
| 544 types.Put(syncable::AUTOFILL); | |
| 545 payload = "test2"; | |
| 546 types_with_payloads = | |
| 547 syncable::ModelTypePayloadMapFromEnumSet(types, payload); | |
| 548 | |
| 549 ASSERT_EQ(3U, types_with_payloads.size()); | |
| 550 EXPECT_EQ(types_with_payloads[syncable::BOOKMARKS], payload); | |
| 551 EXPECT_EQ(types_with_payloads[syncable::PASSWORDS], payload); | |
| 552 EXPECT_EQ(types_with_payloads[syncable::AUTOFILL], payload); | |
| 553 } | |
| 554 | |
| 555 TEST_F(SyncSessionTest, MakeTypePayloadMapFromRoutingInfo) { | |
| 556 std::string payload = "test"; | |
| 557 syncable::ModelTypePayloadMap types_with_payloads | |
| 558 = syncable::ModelTypePayloadMapFromRoutingInfo(routes_, payload); | |
| 559 ASSERT_EQ(routes_.size(), types_with_payloads.size()); | |
| 560 for (ModelSafeRoutingInfo::iterator iter = routes_.begin(); | |
| 561 iter != routes_.end(); | |
| 562 ++iter) { | |
| 563 EXPECT_EQ(payload, types_with_payloads[iter->first]); | |
| 564 } | |
| 565 } | |
| 566 | |
| 567 TEST_F(SyncSessionTest, CoalescePayloads) { | |
| 568 syncable::ModelTypePayloadMap original; | |
| 569 std::string empty_payload; | |
| 570 std::string payload1 = "payload1"; | |
| 571 std::string payload2 = "payload2"; | |
| 572 std::string payload3 = "payload3"; | |
| 573 original[syncable::BOOKMARKS] = empty_payload; | |
| 574 original[syncable::PASSWORDS] = payload1; | |
| 575 original[syncable::AUTOFILL] = payload2; | |
| 576 original[syncable::THEMES] = payload3; | |
| 577 | |
| 578 syncable::ModelTypePayloadMap update; | |
| 579 update[syncable::BOOKMARKS] = empty_payload; // Same. | |
| 580 update[syncable::PASSWORDS] = empty_payload; // Overwrite with empty. | |
| 581 update[syncable::AUTOFILL] = payload1; // Overwrite with non-empty. | |
| 582 update[syncable::SESSIONS] = payload2; // New. | |
| 583 // Themes untouched. | |
| 584 | |
| 585 CoalescePayloads(&original, update); | |
| 586 ASSERT_EQ(5U, original.size()); | |
| 587 EXPECT_EQ(empty_payload, original[syncable::BOOKMARKS]); | |
| 588 EXPECT_EQ(payload1, original[syncable::PASSWORDS]); | |
| 589 EXPECT_EQ(payload1, original[syncable::AUTOFILL]); | |
| 590 EXPECT_EQ(payload2, original[syncable::SESSIONS]); | |
| 591 EXPECT_EQ(payload3, original[syncable::THEMES]); | |
| 592 } | |
| 593 | |
| 594 } // namespace | |
| 595 } // namespace sessions | |
| 596 } // namespace browser_sync | |
| OLD | NEW |