1 // Copyright 2014 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/message_loop/message_loop.h" 6 #include "chrome/browser/sync/glue/local_device_info_provider_mock.h" 7 #include "components/sync_driver/device_info_sync_service.h" 8 #include "content/public/test/test_browser_thread_bundle.h" 9 #include "sync/api/sync_change.h" 10 #include "sync/api/sync_change_processor.h" 11 #include "sync/api/sync_change_processor_wrapper_for_test.h" 12 #include "sync/api/sync_error_factory_mock.h" 13 #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h" 14 #include "sync/util/time.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 using sync_driver::DeviceInfoSyncService; 18 using sync_driver::DeviceInfoTracker; 19 using syncer::AttachmentIdList; 20 using syncer::AttachmentServiceProxyForTest; 21 using syncer::ModelType; 22 using syncer::SyncChange; 23 using syncer::SyncChangeList; 24 using syncer::SyncChangeProcessor; 25 using syncer::SyncChangeProcessorWrapperForTest; 26 using syncer::SyncData; 27 using syncer::SyncDataList; 28 using syncer::SyncError; 29 using syncer::SyncErrorFactory; 30 using syncer::SyncErrorFactoryMock; 31 using syncer::SyncMergeResult; 32 33 namespace browser_sync { 34 35 namespace { 36 37 class TestChangeProcessor : public SyncChangeProcessor { 38 public: 39 TestChangeProcessor() {} 40 virtual ~TestChangeProcessor() {} 41 42 // SyncChangeProcessor implementation. 43 // Store a copy of all the changes passed in so we can examine them later. 44 virtual SyncError ProcessSyncChanges( 45 const tracked_objects::Location& from_here, 46 const SyncChangeList& change_list) OVERRIDE { 47 change_list_ = change_list; 48 return SyncError(); 49 } 50 51 // This method isn't used in these tests. 52 virtual SyncDataList GetAllSyncData(ModelType type) const OVERRIDE { 53 return SyncDataList(); 54 } 55 56 size_t change_list_size() const { return change_list_.size(); } 57 58 SyncChange::SyncChangeType change_type_at(size_t index) const { 59 CHECK_LT(index, change_list_size()); 60 return change_list_[index].change_type(); 61 } 62 63 const sync_pb::DeviceInfoSpecifics& device_info_at(size_t index) const { 64 CHECK_LT(index, change_list_size()); 65 return change_list_[index].sync_data().GetSpecifics().device_info(); 66 } 67 68 const std::string& cache_guid_at(size_t index) const { 69 return device_info_at(index).cache_guid(); 70 } 71 72 const std::string& client_name_at(size_t index) const { 73 return device_info_at(index).client_name(); 74 } 75 76 private: 77 SyncChangeList change_list_; 78 }; 79 80 class DeviceInfoSyncServiceTest : public testing::Test, 81 public DeviceInfoTracker::Observer { 82 public: 83 DeviceInfoSyncServiceTest() : num_device_info_changed_callbacks_(0) {} 84 virtual ~DeviceInfoSyncServiceTest() {} 85 86 virtual void SetUp() OVERRIDE { 87 local_device_.reset(new LocalDeviceInfoProviderMock( 88 "guid_1", 89 "client_1", 90 "Chromium 10k", 91 "Chrome 10k", 92 sync_pb::SyncEnums_DeviceType_TYPE_LINUX, 93 "device_id")); 94 sync_service_.reset(new DeviceInfoSyncService(local_device_.get())); 95 sync_processor_.reset(new TestChangeProcessor()); 96 // Register observer 97 sync_service_->AddObserver(this); 98 } 99 100 virtual void TearDown() OVERRIDE { 101 sync_service_->RemoveObserver(this); 102 } 103 104 virtual void OnDeviceInfoChange() OVERRIDE { 105 num_device_info_changed_callbacks_++; 106 } 107 108 scoped_ptr<SyncChangeProcessor> PassProcessor() { 109 return scoped_ptr<SyncChangeProcessor>( 110 new SyncChangeProcessorWrapperForTest(sync_processor_.get())); 111 } 112 113 scoped_ptr<SyncErrorFactory> CreateAndPassSyncErrorFactory() { 114 return scoped_ptr<SyncErrorFactory>(new SyncErrorFactoryMock()); 115 } 116 117 SyncData CreateRemoteData(const std::string& client_id, 118 const std::string& client_name, 119 int64 backup_timestamp = 0) { 120 sync_pb::EntitySpecifics entity; 121 sync_pb::DeviceInfoSpecifics& specifics = *entity.mutable_device_info(); 122 123 specifics.set_cache_guid(client_id); 124 specifics.set_client_name(client_name); 125 specifics.set_chrome_version("Chromium 10k"); 126 specifics.set_sync_user_agent("Chrome 10k"); 127 specifics.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_LINUX); 128 specifics.set_signin_scoped_device_id("device_id"); 129 130 if (backup_timestamp != 0) { 131 specifics.set_backup_timestamp(backup_timestamp); 132 } 133 134 return SyncData::CreateRemoteData(1, 135 entity, 136 base::Time(), 137 AttachmentIdList(), 138 AttachmentServiceProxyForTest::Create()); 139 } 140 141 void AddInitialData(SyncDataList& sync_data_list, 142 const std::string& client_id, 143 const std::string& client_name) { 144 SyncData sync_data = CreateRemoteData(client_id, client_name); 145 sync_data_list.push_back(sync_data); 146 } 147 148 void AddChange(SyncChangeList& change_list, 149 SyncChange::SyncChangeType change_type, 150 const std::string& client_id, 151 const std::string& client_name) { 152 SyncData sync_data = CreateRemoteData(client_id, client_name); 153 SyncChange sync_change(FROM_HERE, change_type, sync_data); 154 change_list.push_back(sync_change); 155 } 156 157 protected: 158 int num_device_info_changed_callbacks_; 159 scoped_ptr<LocalDeviceInfoProviderMock> local_device_; 160 scoped_ptr<DeviceInfoSyncService> sync_service_; 161 scoped_ptr<TestChangeProcessor> sync_processor_; 162 content::TestBrowserThreadBundle thread_bundle_; 163 }; 164 165 // Sync with empty initial data. 166 TEST_F(DeviceInfoSyncServiceTest, StartSyncEmptyInitialData) { 167 SyncMergeResult merge_result = 168 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 169 SyncDataList(), 170 PassProcessor(), 171 CreateAndPassSyncErrorFactory()); 172 173 EXPECT_EQ(0, merge_result.num_items_added()); 174 EXPECT_EQ(0, merge_result.num_items_modified()); 175 EXPECT_EQ(0, merge_result.num_items_deleted()); 176 EXPECT_EQ(1, merge_result.num_items_before_association()); 177 EXPECT_EQ(1, merge_result.num_items_after_association()); 178 EXPECT_EQ(SyncChange::ACTION_ADD, sync_processor_->change_type_at(0)); 179 180 EXPECT_EQ(1U, sync_processor_->change_list_size()); 181 EXPECT_EQ("guid_1", sync_processor_->cache_guid_at(0)); 182 183 // Should have one device info corresponding to local device info. 184 EXPECT_EQ(1U, sync_service_->GetAllSyncData(syncer::DEVICE_INFO).size()); 185 EXPECT_EQ(1U, sync_service_->GetAllDeviceInfo().size()); 186 EXPECT_TRUE(sync_service_->GetDeviceInfo("guid_1")); 187 EXPECT_FALSE(sync_service_->GetDeviceInfo("guid_0")); 188 } 189 190 // Sync with initial data matching the local device data. 191 TEST_F(DeviceInfoSyncServiceTest, StartSyncMatchingInitialData) { 192 SyncDataList sync_data; 193 AddInitialData(sync_data, "guid_1", "client_1"); 194 195 SyncMergeResult merge_result = 196 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 197 sync_data, 198 PassProcessor(), 199 CreateAndPassSyncErrorFactory()); 200 EXPECT_EQ(0, merge_result.num_items_added()); 201 EXPECT_EQ(0, merge_result.num_items_modified()); 202 EXPECT_EQ(0, merge_result.num_items_deleted()); 203 EXPECT_EQ(1, merge_result.num_items_before_association()); 204 EXPECT_EQ(1, merge_result.num_items_after_association()); 205 206 // No changes expected because the device info matches. 207 EXPECT_EQ(0U, sync_processor_->change_list_size()); 208 209 EXPECT_EQ(1U, sync_service_->GetAllSyncData(syncer::DEVICE_INFO).size()); 210 EXPECT_EQ(1U, sync_service_->GetAllDeviceInfo().size()); 211 EXPECT_TRUE(sync_service_->GetDeviceInfo("guid_1")); 212 EXPECT_FALSE(sync_service_->GetDeviceInfo("guid_0")); 213 } 214 215 // Sync with misc initial data. 216 TEST_F(DeviceInfoSyncServiceTest, StartSync) { 217 SyncDataList sync_data; 218 AddInitialData(sync_data, "guid_2", "foo"); 219 AddInitialData(sync_data, "guid_3", "bar"); 220 // This guid matches the local device but the client name is different. 221 AddInitialData(sync_data, "guid_1", "baz"); 222 223 SyncMergeResult merge_result = 224 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 225 sync_data, 226 PassProcessor(), 227 CreateAndPassSyncErrorFactory()); 228 229 EXPECT_EQ(2, merge_result.num_items_added()); 230 EXPECT_EQ(1, merge_result.num_items_modified()); 231 EXPECT_EQ(0, merge_result.num_items_deleted()); 232 EXPECT_EQ(1, merge_result.num_items_before_association()); 233 EXPECT_EQ(3, merge_result.num_items_after_association()); 234 235 EXPECT_EQ(1U, sync_processor_->change_list_size()); 236 EXPECT_EQ(SyncChange::ACTION_UPDATE, sync_processor_->change_type_at(0)); 237 EXPECT_EQ("client_1", sync_processor_->client_name_at(0)); 238 239 EXPECT_EQ(3U, sync_service_->GetAllSyncData(syncer::DEVICE_INFO).size()); 240 EXPECT_EQ(3U, sync_service_->GetAllDeviceInfo().size()); 241 EXPECT_TRUE(sync_service_->GetDeviceInfo("guid_1")); 242 EXPECT_TRUE(sync_service_->GetDeviceInfo("guid_2")); 243 EXPECT_TRUE(sync_service_->GetDeviceInfo("guid_3")); 244 EXPECT_FALSE(sync_service_->GetDeviceInfo("guid_0")); 245 } 246 247 // Process sync change with ACTION_ADD. 248 // Verify callback. 249 TEST_F(DeviceInfoSyncServiceTest, ProcessAddChange) { 250 EXPECT_EQ(0, num_device_info_changed_callbacks_); 251 252 // Start with an empty initial data. 253 SyncMergeResult merge_result = 254 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 255 SyncDataList(), 256 PassProcessor(), 257 CreateAndPassSyncErrorFactory()); 258 // There should be only one item corresponding to the local device 259 EXPECT_EQ(1, merge_result.num_items_after_association()); 260 EXPECT_EQ(1, num_device_info_changed_callbacks_); 261 262 // Add a new device info with a non-matching guid. 263 SyncChangeList change_list; 264 AddChange(change_list, SyncChange::ACTION_ADD, "guid_2", "foo"); 265 266 SyncError error = sync_service_->ProcessSyncChanges(FROM_HERE, change_list); 267 EXPECT_FALSE(error.IsSet()); 268 EXPECT_EQ(2, num_device_info_changed_callbacks_); 269 270 EXPECT_EQ(2U, sync_service_->GetAllDeviceInfo().size()); 271 272 EXPECT_TRUE(sync_service_->GetDeviceInfo("guid_1")); 273 EXPECT_TRUE(sync_service_->GetDeviceInfo("guid_2")); 274 EXPECT_FALSE(sync_service_->GetDeviceInfo("guid_0")); 275 } 276 277 // Process multiple sync change with ACTION_UPDATE and ACTION_ADD. 278 // Verify that callback is called multiple times. 279 TEST_F(DeviceInfoSyncServiceTest, ProcessMultipleChanges) { 280 SyncDataList sync_data; 281 AddInitialData(sync_data, "guid_2", "foo"); 282 AddInitialData(sync_data, "guid_3", "bar"); 283 284 SyncMergeResult merge_result = 285 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 286 sync_data, 287 PassProcessor(), 288 CreateAndPassSyncErrorFactory()); 289 EXPECT_EQ(3, merge_result.num_items_after_association()); 290 // reset callbacks counter 291 num_device_info_changed_callbacks_ = 0; 292 293 SyncChangeList change_list; 294 AddChange(change_list, SyncChange::ACTION_UPDATE, "guid_2", "foo_2"); 295 296 SyncError error = sync_service_->ProcessSyncChanges(FROM_HERE, change_list); 297 EXPECT_FALSE(error.IsSet()); 298 299 EXPECT_EQ(1, num_device_info_changed_callbacks_); 300 EXPECT_EQ(3U, sync_service_->GetAllDeviceInfo().size()); 301 EXPECT_EQ("foo_2", sync_service_->GetDeviceInfo("guid_2")->client_name()); 302 303 change_list.clear(); 304 AddChange(change_list, SyncChange::ACTION_UPDATE, "guid_3", "bar_3"); 305 AddChange(change_list, SyncChange::ACTION_ADD, "guid_4", "baz_4"); 306 307 error = sync_service_->ProcessSyncChanges(FROM_HERE, change_list); 308 EXPECT_FALSE(error.IsSet()); 309 310 EXPECT_EQ(2, num_device_info_changed_callbacks_); 311 EXPECT_EQ(4U, sync_service_->GetAllDeviceInfo().size()); 312 EXPECT_EQ("bar_3", sync_service_->GetDeviceInfo("guid_3")->client_name()); 313 EXPECT_EQ("baz_4", sync_service_->GetDeviceInfo("guid_4")->client_name()); 314 } 315 316 // Process update to the local device info and verify that it is ignored. 317 TEST_F(DeviceInfoSyncServiceTest, ProcessUpdateChangeMatchingLocalDevice) { 318 SyncMergeResult merge_result = 319 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 320 SyncDataList(), 321 PassProcessor(), 322 CreateAndPassSyncErrorFactory()); 323 EXPECT_EQ(1, merge_result.num_items_after_association()); 324 // reset callbacks counter 325 num_device_info_changed_callbacks_ = 0; 326 327 SyncChangeList change_list; 328 AddChange(change_list, SyncChange::ACTION_UPDATE, "guid_1", "foo_1"); 329 330 SyncError error = sync_service_->ProcessSyncChanges(FROM_HERE, change_list); 331 EXPECT_FALSE(error.IsSet()); 332 // Callback shouldn't be sent in this case. 333 EXPECT_EQ(0, num_device_info_changed_callbacks_); 334 // Should still have the old local device Info. 335 EXPECT_EQ(1U, sync_service_->GetAllDeviceInfo().size()); 336 EXPECT_EQ("client_1", sync_service_->GetDeviceInfo("guid_1")->client_name()); 337 } 338 339 // Process sync change with ACTION_DELETE. 340 TEST_F(DeviceInfoSyncServiceTest, ProcessDeleteChange) { 341 SyncDataList sync_data; 342 AddInitialData(sync_data, "guid_2", "foo"); 343 AddInitialData(sync_data, "guid_3", "bar"); 344 345 SyncMergeResult merge_result = 346 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 347 sync_data, 348 PassProcessor(), 349 CreateAndPassSyncErrorFactory()); 350 EXPECT_EQ(3, merge_result.num_items_after_association()); 351 // reset callbacks counter 352 num_device_info_changed_callbacks_ = 0; 353 354 SyncChangeList change_list; 355 AddChange(change_list, SyncChange::ACTION_DELETE, "guid_2", "foo_2"); 356 357 SyncError error = sync_service_->ProcessSyncChanges(FROM_HERE, change_list); 358 EXPECT_FALSE(error.IsSet()); 359 360 EXPECT_EQ(1, num_device_info_changed_callbacks_); 361 EXPECT_EQ(2U, sync_service_->GetAllDeviceInfo().size()); 362 EXPECT_FALSE(sync_service_->GetDeviceInfo("guid_2")); 363 } 364 365 // Process sync change with unexpected action. 366 TEST_F(DeviceInfoSyncServiceTest, ProcessInvalidChange) { 367 SyncMergeResult merge_result = 368 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 369 SyncDataList(), 370 PassProcessor(), 371 CreateAndPassSyncErrorFactory()); 372 EXPECT_EQ(1, merge_result.num_items_after_association()); 373 // reset callbacks counter 374 num_device_info_changed_callbacks_ = 0; 375 376 SyncChangeList change_list; 377 AddChange(change_list, (SyncChange::SyncChangeType)100, "guid_2", "foo_2"); 378 379 SyncError error = sync_service_->ProcessSyncChanges(FROM_HERE, change_list); 380 EXPECT_TRUE(error.IsSet()); 381 382 // The number of callback should still be zero. 383 EXPECT_EQ(0, num_device_info_changed_callbacks_); 384 EXPECT_EQ(1U, sync_service_->GetAllDeviceInfo().size()); 385 } 386 387 // Process sync change after unsubscribing from notifications. 388 TEST_F(DeviceInfoSyncServiceTest, ProcessChangesAfterUnsubscribing) { 389 SyncMergeResult merge_result = 390 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 391 SyncDataList(), 392 PassProcessor(), 393 CreateAndPassSyncErrorFactory()); 394 EXPECT_EQ(1, merge_result.num_items_after_association()); 395 // reset callbacks counter 396 num_device_info_changed_callbacks_ = 0; 397 398 SyncChangeList change_list; 399 AddChange(change_list, SyncChange::ACTION_ADD, "guid_2", "foo_2"); 400 401 // Unsubscribe observer before processing changes. 402 sync_service_->RemoveObserver(this); 403 404 SyncError error = sync_service_->ProcessSyncChanges(FROM_HERE, change_list); 405 EXPECT_FALSE(error.IsSet()); 406 407 // The number of callback should still be zero. 408 EXPECT_EQ(0, num_device_info_changed_callbacks_); 409 } 410 411 // Verifies setting backup timestamp after the initial sync. 412 TEST_F(DeviceInfoSyncServiceTest, UpdateLocalDeviceBackupTime) { 413 // Shouldn't have backuptime initially. 414 base::Time backup_time = sync_service_->GetLocalDeviceBackupTime(); 415 EXPECT_TRUE(backup_time.is_null()); 416 417 // Perform the initial sync with empty data. 418 SyncMergeResult merge_result = 419 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 420 SyncDataList(), 421 PassProcessor(), 422 CreateAndPassSyncErrorFactory()); 423 424 // Should have local device after the initial sync. 425 EXPECT_EQ(1U, sync_processor_->change_list_size()); 426 EXPECT_EQ(SyncChange::ACTION_ADD, sync_processor_->change_type_at(0)); 427 428 // Shouldn't have backup time initially. 429 EXPECT_EQ("guid_1", sync_processor_->cache_guid_at(0)); 430 EXPECT_FALSE(sync_processor_->device_info_at(0).has_backup_timestamp()); 431 432 sync_service_->UpdateLocalDeviceBackupTime(base::Time::FromTimeT(1000)); 433 434 // Should have local device info updated with the specified backup timestamp. 435 EXPECT_EQ(1U, sync_processor_->change_list_size()); 436 EXPECT_EQ(SyncChange::ACTION_UPDATE, sync_processor_->change_type_at(0)); 437 EXPECT_EQ("guid_1", sync_processor_->cache_guid_at(0)); 438 EXPECT_TRUE(sync_processor_->device_info_at(0).has_backup_timestamp()); 439 440 backup_time = syncer::ProtoTimeToTime( 441 sync_processor_->device_info_at(0).backup_timestamp()); 442 EXPECT_EQ(1000, backup_time.ToTimeT()); 443 444 // Also verify that we get the same backup time directly from the service. 445 backup_time = sync_service_->GetLocalDeviceBackupTime(); 446 EXPECT_EQ(1000, backup_time.ToTimeT()); 447 } 448 449 // Verifies setting backup timestamp prior to the initial sync. 450 TEST_F(DeviceInfoSyncServiceTest, UpdateLocalDeviceBackupTimeBeforeSync) { 451 // Set the backup timestamp. 452 sync_service_->UpdateLocalDeviceBackupTime(base::Time::FromTimeT(2000)); 453 // Verify that we get it back. 454 base::Time backup_time = sync_service_->GetLocalDeviceBackupTime(); 455 EXPECT_EQ(2000, backup_time.ToTimeT()); 456 457 // Now perform the initial sync with empty data. 458 SyncMergeResult merge_result = 459 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 460 SyncDataList(), 461 PassProcessor(), 462 CreateAndPassSyncErrorFactory()); 463 464 // Should have local device after the initial sync. 465 // Should have the backup timestamp set. 466 EXPECT_EQ(1U, sync_processor_->change_list_size()); 467 EXPECT_EQ(SyncChange::ACTION_ADD, sync_processor_->change_type_at(0)); 468 EXPECT_EQ("guid_1", sync_processor_->cache_guid_at(0)); 469 EXPECT_TRUE(sync_processor_->device_info_at(0).has_backup_timestamp()); 470 471 backup_time = syncer::ProtoTimeToTime( 472 sync_processor_->device_info_at(0).backup_timestamp()); 473 EXPECT_EQ(2000, backup_time.ToTimeT()); 474 } 475 476 // Verifies that the backup timestamp that comes in the intial sync data 477 // gets preserved when there are no changes to the local device. 478 TEST_F(DeviceInfoSyncServiceTest, PreserveBackupTimeWithMatchingLocalDevice) { 479 base::Time backup_time = base::Time::FromTimeT(3000); 480 SyncDataList sync_data; 481 sync_data.push_back(CreateRemoteData( 482 "guid_1", "client_1", syncer::TimeToProtoTime(backup_time))); 483 484 SyncMergeResult merge_result = 485 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 486 sync_data, 487 PassProcessor(), 488 CreateAndPassSyncErrorFactory()); 489 490 // Everything is matching so there should be no updates. 491 EXPECT_EQ(0U, sync_processor_->change_list_size()); 492 493 // Verify that we get back the same time. 494 backup_time = sync_service_->GetLocalDeviceBackupTime(); 495 EXPECT_EQ(3000, backup_time.ToTimeT()); 496 } 497 498 // Verifies that the backup timestamp that comes in the intial sync data 499 // gets merged with the local device data. 500 TEST_F(DeviceInfoSyncServiceTest, MergeBackupTimeWithMatchingLocalDevice) { 501 base::Time backup_time = base::Time::FromTimeT(4000); 502 SyncDataList sync_data; 503 sync_data.push_back(CreateRemoteData( 504 "guid_1", "foo_1", syncer::TimeToProtoTime(backup_time))); 505 506 SyncMergeResult merge_result = 507 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 508 sync_data, 509 PassProcessor(), 510 CreateAndPassSyncErrorFactory()); 511 512 // Should be one change because of the client name mismatch. 513 // However the backup time passed in the initial data should be merged into 514 // the change. 515 EXPECT_EQ(1U, sync_processor_->change_list_size()); 516 517 EXPECT_EQ(SyncChange::ACTION_UPDATE, sync_processor_->change_type_at(0)); 518 EXPECT_EQ("guid_1", sync_processor_->cache_guid_at(0)); 519 EXPECT_EQ("client_1", sync_processor_->client_name_at(0)); 520 521 backup_time = syncer::ProtoTimeToTime( 522 sync_processor_->device_info_at(0).backup_timestamp()); 523 EXPECT_EQ(4000, backup_time.ToTimeT()); 524 } 525 526 // Verifies that mismatching backup timestamp generates an update even 527 // when the rest of local device data is matching. 528 TEST_F(DeviceInfoSyncServiceTest, 529 MergeMismatchingBackupTimeWithMatchingLocalDevice) { 530 base::Time backup_time = base::Time::FromTimeT(5000); 531 SyncDataList sync_data; 532 sync_data.push_back(CreateRemoteData( 533 "guid_1", "client_1", syncer::TimeToProtoTime(backup_time))); 534 535 // Set the backup timestamp different than the one in the sync data. 536 sync_service_->UpdateLocalDeviceBackupTime(base::Time::FromTimeT(6000)); 537 538 SyncMergeResult merge_result = 539 sync_service_->MergeDataAndStartSyncing(syncer::DEVICE_INFO, 540 sync_data, 541 PassProcessor(), 542 CreateAndPassSyncErrorFactory()); 543 544 // Should generate and update due to timestamp mismatch. 545 // The locally set timestamp wins. 546 EXPECT_EQ(1U, sync_processor_->change_list_size()); 547 548 EXPECT_EQ(SyncChange::ACTION_UPDATE, sync_processor_->change_type_at(0)); 549 EXPECT_EQ("guid_1", sync_processor_->cache_guid_at(0)); 550 EXPECT_EQ("client_1", sync_processor_->client_name_at(0)); 551 552 backup_time = syncer::ProtoTimeToTime( 553 sync_processor_->device_info_at(0).backup_timestamp()); 554 EXPECT_EQ(6000, backup_time.ToTimeT()); 555 } 556 557 } // namespace 558 559 } // namespace browser_sync 560