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::EntityDataMap; |
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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 expected.find(pair.first); | 92 expected.find(pair.first); |
91 ASSERT_NE(iter, expected.end()); | 93 ASSERT_NE(iter, expected.end()); |
92 AssertEqual(iter->second, pair.second->specifics.device_info()); | 94 AssertEqual(iter->second, pair.second->specifics.device_info()); |
93 // Removing allows us to verify we don't see the same item multiple times, | 95 // Removing allows us to verify we don't see the same item multiple times, |
94 // and that we saw everything we expected. | 96 // and that we saw everything we expected. |
95 expected.erase(iter); | 97 expected.erase(iter); |
96 } | 98 } |
97 ASSERT_TRUE(expected.empty()); | 99 ASSERT_TRUE(expected.empty()); |
98 } | 100 } |
99 | 101 |
| 102 // Creats an EntityData/EntityDataPtr around a copy of the given specifics. |
| 103 EntityDataPtr SpecificsToEntity(const DeviceInfoSpecifics& specifics) { |
| 104 EntityData data; |
| 105 // These tests do not care about the tag hash, but EntityData and friends |
| 106 // cannot differentiate between the default EntityData object if the hash |
| 107 // is unset, which causes pass/copy operations to no-op and things start to |
| 108 // break, so we throw in a junk value and forget about it. |
| 109 data.client_tag_hash = "junk"; |
| 110 *data.specifics.mutable_device_info() = specifics; |
| 111 return data.PassToPtr(); |
| 112 } |
| 113 |
100 // Instead of actually processing anything, simply accumulates all instructions | 114 // Instead of actually processing anything, simply accumulates all instructions |
101 // in members that can then be accessed. TODO(skym): If this ends up being | 115 // in members that can then be accessed. TODO(skym): If this ends up being |
102 // useful for other model type unittests it should be moved out to a shared | 116 // useful for other model type unittests it should be moved out to a shared |
103 // location. | 117 // location. |
104 class FakeModelTypeChangeProcessor : public ModelTypeChangeProcessor { | 118 class FakeModelTypeChangeProcessor : public ModelTypeChangeProcessor { |
105 public: | 119 public: |
106 FakeModelTypeChangeProcessor() {} | 120 FakeModelTypeChangeProcessor() {} |
107 ~FakeModelTypeChangeProcessor() override {} | 121 ~FakeModelTypeChangeProcessor() override {} |
108 | 122 |
109 void Put(const std::string& client_tag, | 123 void Put(const std::string& client_tag, |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 specifics.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_LINUX); | 213 specifics.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_LINUX); |
200 specifics.set_sync_user_agent( | 214 specifics.set_sync_user_agent( |
201 base::StringPrintf("sync user agent %d", label)); | 215 base::StringPrintf("sync user agent %d", label)); |
202 specifics.set_chrome_version( | 216 specifics.set_chrome_version( |
203 base::StringPrintf("chrome version %d", label)); | 217 base::StringPrintf("chrome version %d", label)); |
204 specifics.set_signin_scoped_device_id( | 218 specifics.set_signin_scoped_device_id( |
205 base::StringPrintf("signin scoped device id %d", label)); | 219 base::StringPrintf("signin scoped device id %d", label)); |
206 return specifics; | 220 return specifics; |
207 } | 221 } |
208 | 222 |
| 223 // Override to allow specific cache guids. |
| 224 DeviceInfoSpecifics GenerateTestSpecifics(const std::string& guid) { |
| 225 DeviceInfoSpecifics specifics(GenerateTestSpecifics()); |
| 226 specifics.set_cache_guid(guid); |
| 227 return specifics; |
| 228 } |
| 229 |
209 // Helper method to reduce duplicated code between tests. Wraps the given | 230 // Helper method to reduce duplicated code between tests. Wraps the given |
210 // specifics object in an EntityData and EntityChange of type ACTION_ADD, and | 231 // specifics object in an EntityData and EntityChange of type ACTION_ADD, and |
211 // pushes them onto the given change list. The corresponding client tag the | 232 // pushes them onto the given change list. The corresponding client tag the |
212 // service determines is returned. Instance method because we need access to | 233 // service determines is returned. Instance method because we need access to |
213 // service to generate the tag. | 234 // service to generate the tag. |
214 std::string PushBackEntityChangeAdd(const DeviceInfoSpecifics& specifics, | 235 std::string PushBackEntityChangeAdd(const DeviceInfoSpecifics& specifics, |
215 EntityChangeList* changes) { | 236 EntityChangeList* changes) { |
216 EntityData data; | 237 EntityDataPtr ptr = SpecificsToEntity(specifics); |
217 // These tests do not care about the tag hash, but EntityData and friends | 238 const std::string tag = service()->GetClientTag(ptr.value()); |
218 // cannot differentiate between the default EntityData object if the hash | 239 changes->push_back(EntityChange::CreateAdd(tag, ptr)); |
219 // is unset, which causes pass/copy operations to no-op and things start to | |
220 // break, so we throw in a junk value and forget about it. | |
221 data.client_tag_hash = "junk"; | |
222 *data.specifics.mutable_device_info() = specifics; | |
223 const std::string tag = service()->GetClientTag(data); | |
224 changes->push_back(EntityChange::CreateAdd(tag, data.PassToPtr())); | |
225 return tag; | 240 return tag; |
226 } | 241 } |
227 | 242 |
228 // Allows access to the store before that will ultimately be used to | 243 // Allows access to the store before that will ultimately be used to |
229 // initialize the service. | 244 // initialize the service. |
230 ModelTypeStore* store() { | 245 ModelTypeStore* store() { |
231 EXPECT_TRUE(store_); | 246 EXPECT_TRUE(store_); |
232 return store_.get(); | 247 return store_.get(); |
233 } | 248 } |
234 | 249 |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 // EXPECT_EQ(state.encryption_key_name(), | 545 // EXPECT_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 EXPECT_FALSE(error.IsSet()); | 563 EXPECT_FALSE(error.IsSet()); |
549 EXPECT_FALSE(service()->GetDeviceInfo(tag)); | 564 EXPECT_FALSE(service()->GetDeviceInfo(tag)); |
550 EXPECT_EQ(0, change_count()); | 565 EXPECT_EQ(0, change_count()); |
551 } | 566 } |
552 | 567 |
553 TEST_F(DeviceInfoServiceTest, ApplyDeleteNonexistent) { | 568 TEST_F(DeviceInfoServiceTest, ApplyDeleteNonexistent) { |
554 InitializeAndPump(); | 569 InitializeAndPump(); |
555 EntityChangeList delete_changes; | 570 EntityChangeList delete_changes; |
556 delete_changes.push_back(EntityChange::CreateDelete("tag")); | 571 delete_changes.push_back(EntityChange::CreateDelete("tag")); |
557 const SyncError error = service()->ApplySyncChanges( | 572 const SyncError error = service()->ApplySyncChanges( |
558 service()->CreateMetadataChangeList(), delete_changes); | 573 service()->CreateMetadataChangeList(), delete_changes); |
559 EXPECT_FALSE(error.IsSet()); | 574 EXPECT_FALSE(error.IsSet()); |
560 EXPECT_EQ(0, change_count()); | 575 EXPECT_EQ(0, change_count()); |
561 } | 576 } |
562 | 577 |
| 578 TEST_F(DeviceInfoServiceTest, MergeBeforeInit) { |
| 579 InitializeService(); |
| 580 const SyncError error = service()->MergeSyncData( |
| 581 service()->CreateMetadataChangeList(), EntityDataMap()); |
| 582 EXPECT_TRUE(error.IsSet()); |
| 583 EXPECT_EQ(0, change_count()); |
| 584 } |
| 585 |
| 586 TEST_F(DeviceInfoServiceTest, MergeEmpty) { |
| 587 InitializeAndPump(); |
| 588 SetProcessorAndPump(); |
| 589 const SyncError error = service()->MergeSyncData( |
| 590 service()->CreateMetadataChangeList(), EntityDataMap()); |
| 591 EXPECT_FALSE(error.IsSet()); |
| 592 EXPECT_EQ(0, change_count()); |
| 593 } |
| 594 |
| 595 TEST_F(DeviceInfoServiceTest, MergeWithData) { |
| 596 const DeviceInfoSpecifics unique_local(GenerateTestSpecifics("unique_local")); |
| 597 const DeviceInfoSpecifics conflict_local(GenerateTestSpecifics("conflict")); |
| 598 DeviceInfoSpecifics conflict_remote(GenerateTestSpecifics("conflict")); |
| 599 DeviceInfoSpecifics unique_remote(GenerateTestSpecifics("unique_remote")); |
| 600 |
| 601 scoped_ptr<WriteBatch> batch = store()->CreateWriteBatch(); |
| 602 store()->WriteData(batch.get(), unique_local.cache_guid(), |
| 603 unique_local.SerializeAsString()); |
| 604 store()->WriteData(batch.get(), conflict_local.cache_guid(), |
| 605 conflict_local.SerializeAsString()); |
| 606 store()->CommitWriteBatch(std::move(batch), |
| 607 base::Bind(&AssertResultIsSuccess)); |
| 608 |
| 609 InitializeAndPump(); |
| 610 SetProcessorAndPump(); |
| 611 |
| 612 EntityDataMap remote_input; |
| 613 remote_input[conflict_remote.cache_guid()] = |
| 614 SpecificsToEntity(conflict_remote); |
| 615 remote_input[unique_remote.cache_guid()] = SpecificsToEntity(unique_remote); |
| 616 |
| 617 DataTypeState state; |
| 618 state.set_encryption_key_name("ekn"); |
| 619 scoped_ptr<MetadataChangeList> metadata_changes( |
| 620 service()->CreateMetadataChangeList()); |
| 621 metadata_changes->UpdateDataTypeState(state); |
| 622 |
| 623 const SyncError error = |
| 624 service()->MergeSyncData(std::move(metadata_changes), remote_input); |
| 625 EXPECT_FALSE(error.IsSet()); |
| 626 EXPECT_EQ(1, change_count()); |
| 627 |
| 628 // The remote should beat the local in conflict. |
| 629 EXPECT_EQ(3u, service()->GetAllDeviceInfo().size()); |
| 630 AssertEqual(unique_local, *service()->GetDeviceInfo("unique_local").get()); |
| 631 AssertEqual(unique_remote, *service()->GetDeviceInfo("unique_remote").get()); |
| 632 AssertEqual(conflict_remote, *service()->GetDeviceInfo("conflict").get()); |
| 633 |
| 634 // Service should have told the processor about the existance of unique_local. |
| 635 EXPECT_TRUE(processor()->delete_set().empty()); |
| 636 EXPECT_EQ(1u, processor()->put_map().size()); |
| 637 const auto& it = processor()->put_map().find("unique_local"); |
| 638 ASSERT_NE(processor()->put_map().end(), it); |
| 639 AssertEqual(unique_local, it->second->specifics.device_info()); |
| 640 |
| 641 // TODO(skym): Uncomment once SimpleMetadataChangeList::TransferChanges is |
| 642 // implemented. |
| 643 // ASSERT_EQ(state.encryption_key_name(), |
| 644 // processor()->metadata()->GetDataTypeState().encryption_key_name()); |
| 645 } |
| 646 |
| 647 TEST_F(DeviceInfoServiceTest, MergeLocalGuid) { |
| 648 InitializeAndPump(); |
| 649 SetProcessorAndPump(); |
| 650 |
| 651 // Service should ignore this because it uses the local device's guid. |
| 652 DeviceInfoSpecifics specifics( |
| 653 GenerateTestSpecifics(local_device()->GetLocalDeviceInfo()->guid())); |
| 654 EntityDataMap remote_input; |
| 655 remote_input[specifics.cache_guid()] = SpecificsToEntity(specifics); |
| 656 |
| 657 const SyncError error = service()->MergeSyncData( |
| 658 service()->CreateMetadataChangeList(), remote_input); |
| 659 EXPECT_FALSE(error.IsSet()); |
| 660 EXPECT_EQ(0, change_count()); |
| 661 EXPECT_TRUE(service()->GetAllDeviceInfo().empty()); |
| 662 EXPECT_TRUE(processor()->delete_set().empty()); |
| 663 EXPECT_TRUE(processor()->put_map().empty()); |
| 664 } |
| 665 |
563 } // namespace | 666 } // namespace |
564 | 667 |
565 } // namespace sync_driver_v2 | 668 } // namespace sync_driver_v2 |
OLD | NEW |