Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/sync_driver/device_info_service.h" | 5 #include "components/sync_driver/device_info_service.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 15 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
| 16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 17 #include "components/sync_driver/local_device_info_provider_mock.h" | 17 #include "components/sync_driver/local_device_info_provider_mock.h" |
| 18 #include "sync/api/data_batch.h" | 18 #include "sync/api/data_batch.h" |
| 19 #include "sync/api/entity_data.h" | |
| 19 #include "sync/api/metadata_batch.h" | 20 #include "sync/api/metadata_batch.h" |
| 20 #include "sync/api/model_type_store.h" | 21 #include "sync/api/model_type_store.h" |
| 21 #include "sync/internal_api/public/test/model_type_store_test_util.h" | 22 #include "sync/internal_api/public/test/model_type_store_test_util.h" |
| 22 #include "sync/protocol/data_type_state.pb.h" | 23 #include "sync/protocol/data_type_state.pb.h" |
| 23 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 24 | 25 |
| 25 namespace sync_driver_v2 { | 26 namespace sync_driver_v2 { |
| 26 | 27 |
| 27 using syncer::SyncError; | 28 using syncer::SyncError; |
| 28 using syncer_v2::DataBatch; | 29 using syncer_v2::DataBatch; |
| 29 using syncer_v2::EntityChange; | 30 using syncer_v2::EntityChange; |
| 30 using syncer_v2::EntityChangeList; | 31 using syncer_v2::EntityChangeList; |
| 31 using syncer_v2::EntityData; | 32 using syncer_v2::EntityData; |
| 33 using syncer_v2::EntityDataList; | |
| 32 using syncer_v2::EntityDataPtr; | 34 using syncer_v2::EntityDataPtr; |
| 33 using syncer_v2::MetadataBatch; | 35 using syncer_v2::MetadataBatch; |
| 34 using syncer_v2::MetadataChangeList; | 36 using syncer_v2::MetadataChangeList; |
| 35 using syncer_v2::ModelTypeChangeProcessor; | 37 using syncer_v2::ModelTypeChangeProcessor; |
| 36 using syncer_v2::ModelTypeService; | 38 using syncer_v2::ModelTypeService; |
| 37 using syncer_v2::ModelTypeStore; | 39 using syncer_v2::ModelTypeStore; |
| 38 using syncer_v2::ModelTypeStoreTestUtil; | 40 using syncer_v2::ModelTypeStoreTestUtil; |
| 39 using syncer_v2::TagAndData; | 41 using syncer_v2::TagAndData; |
| 40 using sync_driver::DeviceInfo; | 42 using sync_driver::DeviceInfo; |
| 41 using sync_driver::DeviceInfoTracker; | 43 using sync_driver::DeviceInfoTracker; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 expected.find(pair.first); | 93 expected.find(pair.first); |
| 92 ASSERT_NE(iter, expected.end()); | 94 ASSERT_NE(iter, expected.end()); |
| 93 AssertEqual(iter->second, pair.second->specifics.device_info()); | 95 AssertEqual(iter->second, pair.second->specifics.device_info()); |
| 94 // Removing allows us to verify we don't see the same item multiple times, | 96 // Removing allows us to verify we don't see the same item multiple times, |
| 95 // and that we saw everything we expected. | 97 // and that we saw everything we expected. |
| 96 expected.erase(iter); | 98 expected.erase(iter); |
| 97 } | 99 } |
| 98 ASSERT_TRUE(expected.empty()); | 100 ASSERT_TRUE(expected.empty()); |
| 99 } | 101 } |
| 100 | 102 |
| 103 // Creats an EntityData/EntityDataPtr around a copy of the given specifics. | |
| 104 EntityDataPtr SpecificsToEntity(const DeviceInfoSpecifics& specifics) { | |
| 105 EntityData data; | |
| 106 // These tests do not care about the tag hash, but EntityData and friends | |
| 107 // cannot differentiate between the default EntityData object if the hash | |
| 108 // is unset, which causes pass/copy operations to no-op and things start to | |
| 109 // break, so we throw in a junk value and forget about it. | |
| 110 data.client_tag_hash = "junk"; | |
| 111 *data.specifics.mutable_device_info() = specifics; | |
| 112 return data.PassToPtr(); | |
| 113 } | |
| 114 | |
| 101 // Instead of actually processing anything, simply accumulates all instructions | 115 // Instead of actually processing anything, simply accumulates all instructions |
| 102 // in members that can then be accessed. TODO(skym): If this ends up being | 116 // in members that can then be accessed. TODO(skym): If this ends up being |
| 103 // useful for other model type unittests it should be moved out to a shared | 117 // useful for other model type unittests it should be moved out to a shared |
| 104 // location. | 118 // location. |
| 105 class FakeModelTypeChangeProcessor : public ModelTypeChangeProcessor { | 119 class FakeModelTypeChangeProcessor : public ModelTypeChangeProcessor { |
| 106 public: | 120 public: |
| 107 FakeModelTypeChangeProcessor() {} | 121 FakeModelTypeChangeProcessor() {} |
| 108 ~FakeModelTypeChangeProcessor() override {} | 122 ~FakeModelTypeChangeProcessor() override {} |
| 109 | 123 |
| 110 void Put(const std::string& client_tag, | 124 void Put(const std::string& client_tag, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 specifics.set_sync_user_agent( | 215 specifics.set_sync_user_agent( |
| 202 base::StringPrintf("sync user agent %d", label)); | 216 base::StringPrintf("sync user agent %d", label)); |
| 203 specifics.set_chrome_version( | 217 specifics.set_chrome_version( |
| 204 base::StringPrintf("chrome version %d", label)); | 218 base::StringPrintf("chrome version %d", label)); |
| 205 specifics.set_backup_timestamp(label); | 219 specifics.set_backup_timestamp(label); |
| 206 specifics.set_signin_scoped_device_id( | 220 specifics.set_signin_scoped_device_id( |
| 207 base::StringPrintf("signin scoped device id %d", label)); | 221 base::StringPrintf("signin scoped device id %d", label)); |
| 208 return specifics; | 222 return specifics; |
| 209 } | 223 } |
| 210 | 224 |
| 225 // Override to allow specific cache guids. | |
| 226 DeviceInfoSpecifics GenerateTestSpecifics(const std::string& guid) { | |
| 227 DeviceInfoSpecifics specifics(GenerateTestSpecifics()); | |
| 228 specifics.set_cache_guid(guid); | |
| 229 return specifics; | |
| 230 } | |
| 231 | |
| 211 // Helper method to reduce duplicated code between tests. Wraps the given | 232 // Helper method to reduce duplicated code between tests. Wraps the given |
| 212 // specifics object in an EntityData and EntityChange of type ACTION_ADD, and | 233 // specifics object in an EntityData and EntityChange of type ACTION_ADD, and |
| 213 // pushes them onto the given change list. The corresponding client tag the | 234 // pushes them onto the given change list. The corresponding client tag the |
| 214 // service determines is returned. Instance method because we need access to | 235 // service determines is returned. Instance method because we need access to |
| 215 // service to generate the tag. | 236 // service to generate the tag. |
| 216 std::string PushBackEntityChangeAdd(const DeviceInfoSpecifics& specifics, | 237 std::string PushBackEntityChangeAdd(const DeviceInfoSpecifics& specifics, |
| 217 EntityChangeList* changes) { | 238 EntityChangeList* changes) { |
| 218 EntityData data; | 239 EntityDataPtr ptr = SpecificsToEntity(specifics); |
| 219 // These tests do not care about the tag hash, but EntityData and friends | 240 const std::string tag = service()->GetClientTag(ptr.value()); |
| 220 // cannot differentiate between the default EntityData object if the hash | 241 changes->push_back(EntityChange::CreateAdd(tag, ptr)); |
| 221 // is unset, which causes pass/copy operations to no-op and things start to | |
| 222 // break, so we throw in a junk value and forget about it. | |
| 223 data.client_tag_hash = "junk"; | |
| 224 *data.specifics.mutable_device_info() = specifics; | |
| 225 const std::string tag = service()->GetClientTag(data); | |
| 226 changes->push_back(EntityChange::CreateAdd(tag, data.PassToPtr())); | |
| 227 return tag; | 242 return tag; |
| 228 } | 243 } |
| 229 | 244 |
| 230 // Allows access to the store before that will ultimately be used to | 245 // Allows access to the store before that will ultimately be used to |
| 231 // initialize the service. | 246 // initialize the service. |
| 232 ModelTypeStore* store() { | 247 ModelTypeStore* store() { |
| 233 EXPECT_TRUE(store_); | 248 EXPECT_TRUE(store_); |
| 234 return store_.get(); | 249 return store_.get(); |
| 235 } | 250 } |
| 236 | 251 |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 530 // ASSERT_EQ(state.encryption_key_name(), | 545 // ASSERT_EQ(state.encryption_key_name(), |
| 531 // processor()->metadata()->GetDataTypeState().encryption_key_name()); | 546 // processor()->metadata()->GetDataTypeState().encryption_key_name()); |
| 532 } | 547 } |
| 533 | 548 |
| 534 TEST_F(DeviceInfoServiceTest, ApplySyncChangesWithLocalGuid) { | 549 TEST_F(DeviceInfoServiceTest, ApplySyncChangesWithLocalGuid) { |
| 535 InitializeAndPump(); | 550 InitializeAndPump(); |
| 536 | 551 |
| 537 // The point of this test is to try to apply remote changes that have the same | 552 // The point of this test is to try to apply remote changes that have the same |
| 538 // cache guid as the local device. The service should ignore these changes | 553 // cache guid as the local device. The service should ignore these changes |
| 539 // since only it should be performing writes on its data. | 554 // since only it should be performing writes on its data. |
| 540 DeviceInfoSpecifics specifics = GenerateTestSpecifics(); | 555 DeviceInfoSpecifics specifics = |
| 541 specifics.set_cache_guid(local_device()->GetLocalDeviceInfo()->guid()); | 556 GenerateTestSpecifics(local_device()->GetLocalDeviceInfo()->guid()); |
| 542 | 557 |
| 543 EntityChangeList data_changes; | 558 EntityChangeList data_changes; |
| 544 const std::string tag = PushBackEntityChangeAdd(specifics, &data_changes); | 559 const std::string tag = PushBackEntityChangeAdd(specifics, &data_changes); |
| 545 const SyncError error = service()->ApplySyncChanges( | 560 const SyncError error = service()->ApplySyncChanges( |
| 546 service()->CreateMetadataChangeList(), data_changes); | 561 service()->CreateMetadataChangeList(), data_changes); |
| 547 | 562 |
| 548 ASSERT_FALSE(error.IsSet()); | 563 ASSERT_FALSE(error.IsSet()); |
| 549 ASSERT_FALSE(service()->GetDeviceInfo(tag)); | 564 ASSERT_FALSE(service()->GetDeviceInfo(tag)); |
| 550 } | 565 } |
| 551 | 566 |
| 552 TEST_F(DeviceInfoServiceTest, ApplyDeleteNonexistent) { | 567 TEST_F(DeviceInfoServiceTest, ApplyDeleteNonexistent) { |
| 553 InitializeAndPump(); | 568 InitializeAndPump(); |
| 554 EntityChangeList delete_changes; | 569 EntityChangeList delete_changes; |
| 555 delete_changes.push_back(EntityChange::CreateDelete("tag")); | 570 delete_changes.push_back(EntityChange::CreateDelete("tag")); |
| 556 const SyncError error = service()->ApplySyncChanges( | 571 const SyncError error = service()->ApplySyncChanges( |
| 557 service()->CreateMetadataChangeList(), delete_changes); | 572 service()->CreateMetadataChangeList(), delete_changes); |
| 558 ASSERT_FALSE(error.IsSet()); | 573 ASSERT_FALSE(error.IsSet()); |
| 559 } | 574 } |
| 560 | 575 |
| 576 TEST_F(DeviceInfoServiceTest, MergeBeforeInit) { | |
| 577 InitializeService(); | |
| 578 const SyncError error = service()->MergeSyncData( | |
| 579 service()->CreateMetadataChangeList(), EntityDataList()); | |
| 580 ASSERT_TRUE(error.IsSet()); | |
| 581 } | |
| 582 | |
| 583 TEST_F(DeviceInfoServiceTest, MergeEmpty) { | |
| 584 InitializeAndPump(); | |
| 585 SetProcessorAndPump(); | |
| 586 const SyncError error = service()->MergeSyncData( | |
| 587 service()->CreateMetadataChangeList(), EntityDataList()); | |
| 588 ASSERT_FALSE(error.IsSet()); | |
| 589 } | |
| 590 | |
| 591 TEST_F(DeviceInfoServiceTest, MergeWithData) { | |
| 592 const DeviceInfoSpecifics unique_local(GenerateTestSpecifics("unique_local")); | |
| 593 const DeviceInfoSpecifics conflict_local(GenerateTestSpecifics("conflict")); | |
| 594 DeviceInfoSpecifics conflict_remote(GenerateTestSpecifics("conflict")); | |
| 595 DeviceInfoSpecifics unique_remote(GenerateTestSpecifics("unique_remote")); | |
| 596 | |
| 597 scoped_ptr<WriteBatch> batch = store()->CreateWriteBatch(); | |
| 598 store()->WriteData(batch.get(), unique_local.cache_guid(), | |
| 599 unique_local.SerializeAsString()); | |
| 600 store()->WriteData(batch.get(), conflict_local.cache_guid(), | |
| 601 conflict_local.SerializeAsString()); | |
| 602 store()->CommitWriteBatch(std::move(batch), | |
| 603 base::Bind(&AssertResultIsSuccess)); | |
| 604 | |
| 605 InitializeAndPump(); | |
| 606 SetProcessorAndPump(); | |
| 607 | |
| 608 EntityDataList remote_input; | |
| 609 remote_input.push_back(SpecificsToEntity(conflict_remote)); | |
| 610 remote_input.push_back(SpecificsToEntity(unique_remote)); | |
| 611 | |
| 612 DataTypeState state; | |
| 613 state.set_encryption_key_name("ekn"); | |
| 614 scoped_ptr<MetadataChangeList> metadata_changes( | |
| 615 service()->CreateMetadataChangeList()); | |
| 616 metadata_changes->UpdateDataTypeState(state); | |
| 617 | |
|
maxbogue
2016/02/23 01:04:02
Add a TODO here to actually commit |metadata_chang
skym
2016/03/04 20:28:10
Whoopps, it should be getting passed into MergeSyn
| |
| 618 const SyncError error = service()->MergeSyncData( | |
| 619 service()->CreateMetadataChangeList(), remote_input); | |
| 620 ASSERT_FALSE(error.IsSet()); | |
| 621 | |
| 622 // The remote should beat the local in conflict. | |
| 623 ASSERT_EQ(3u, service()->GetAllDeviceInfo().size()); | |
| 624 AssertEqual(unique_local, *service()->GetDeviceInfo("unique_local").get()); | |
| 625 AssertEqual(unique_remote, *service()->GetDeviceInfo("unique_remote").get()); | |
| 626 AssertEqual(conflict_remote, *service()->GetDeviceInfo("conflict").get()); | |
| 627 | |
| 628 // Service should have told the processor about the existance of unique_local. | |
| 629 ASSERT_TRUE(processor()->delete_set().empty()); | |
| 630 ASSERT_EQ(1u, processor()->put_map().size()); | |
| 631 auto it = processor()->put_map().find("unique_local"); | |
| 632 ASSERT_NE(processor()->put_map().end(), it); | |
| 633 AssertEqual(unique_local, it->second->specifics.device_info()); | |
| 634 | |
| 635 // TODO(skym): Uncomment once SimpleMetadataChangeList::TransferChanges is | |
| 636 // implemented. | |
| 637 // ASSERT_EQ(state.encryption_key_name(), | |
| 638 // processor()->metadata()->GetDataTypeState().encryption_key_name()); | |
| 639 } | |
| 640 | |
| 641 TEST_F(DeviceInfoServiceTest, MergeLocalGuid) { | |
| 642 InitializeAndPump(); | |
| 643 SetProcessorAndPump(); | |
| 644 | |
| 645 // Service should ignore this because it uses the local device's guid. | |
| 646 DeviceInfoSpecifics specifics( | |
| 647 GenerateTestSpecifics(local_device()->GetLocalDeviceInfo()->guid())); | |
| 648 EntityDataList remote_input; | |
| 649 remote_input.push_back(SpecificsToEntity(specifics)); | |
| 650 | |
| 651 const SyncError error = service()->MergeSyncData( | |
| 652 service()->CreateMetadataChangeList(), remote_input); | |
| 653 ASSERT_FALSE(error.IsSet()); | |
| 654 ASSERT_TRUE(service()->GetAllDeviceInfo().empty()); | |
| 655 ASSERT_TRUE(processor()->delete_set().empty()); | |
| 656 ASSERT_TRUE(processor()->put_map().empty()); | |
| 657 } | |
| 658 | |
| 561 } // namespace | 659 } // namespace |
| 562 | 660 |
| 563 } // namespace sync_driver_v2 | 661 } // namespace sync_driver_v2 |
| OLD | NEW |