Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: components/sync_driver/device_info_service_unittest.cc

Issue 1991023002: [Sync] USS: Fix race condition in DeviceInfoService + add error handling (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <memory> 8 #include <memory>
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 using sync_pb::EntitySpecifics; 53 using sync_pb::EntitySpecifics;
54 54
55 using ClientTagList = ModelTypeService::ClientTagList; 55 using ClientTagList = ModelTypeService::ClientTagList;
56 using RecordList = ModelTypeStore::RecordList; 56 using RecordList = ModelTypeStore::RecordList;
57 using Result = ModelTypeStore::Result; 57 using Result = ModelTypeStore::Result;
58 using StartCallback = ModelTypeChangeProcessor::StartCallback; 58 using StartCallback = ModelTypeChangeProcessor::StartCallback;
59 using WriteBatch = ModelTypeStore::WriteBatch; 59 using WriteBatch = ModelTypeStore::WriteBatch;
60 60
61 namespace { 61 namespace {
62 62
63 std::unique_ptr<DeviceInfo> CreateDeviceInfo() {
64 return base::MakeUnique<DeviceInfo>(
65 "guid_1", "client_1", "Chromium 10k", "Chrome 10k",
66 sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id");
67 }
68
63 void AssertResultIsSuccess(Result result) { 69 void AssertResultIsSuccess(Result result) {
64 ASSERT_EQ(Result::SUCCESS, result); 70 ASSERT_EQ(Result::SUCCESS, result);
65 } 71 }
66 72
67 void AssertEqual(const DeviceInfoSpecifics& s1, const DeviceInfoSpecifics& s2) { 73 void AssertEqual(const DeviceInfoSpecifics& s1, const DeviceInfoSpecifics& s2) {
68 ASSERT_EQ(s1.cache_guid(), s2.cache_guid()); 74 ASSERT_EQ(s1.cache_guid(), s2.cache_guid());
69 ASSERT_EQ(s1.client_name(), s2.client_name()); 75 ASSERT_EQ(s1.client_name(), s2.client_name());
70 ASSERT_EQ(s1.device_type(), s2.device_type()); 76 ASSERT_EQ(s1.device_type(), s2.device_type());
71 ASSERT_EQ(s1.sync_user_agent(), s2.sync_user_agent()); 77 ASSERT_EQ(s1.sync_user_agent(), s2.sync_user_agent());
72 ASSERT_EQ(s1.chrome_version(), s2.chrome_version()); 78 ASSERT_EQ(s1.chrome_version(), s2.chrome_version());
73 ASSERT_EQ(s1.signin_scoped_device_id(), s2.signin_scoped_device_id()); 79 ASSERT_EQ(s1.signin_scoped_device_id(), s2.signin_scoped_device_id());
74 } 80 }
75 81
76 void AssertEqual(const DeviceInfoSpecifics& specifics, 82 void AssertEqual(const DeviceInfoSpecifics& specifics,
77 const DeviceInfo& model) { 83 const DeviceInfo& model) {
78 ASSERT_EQ(specifics.cache_guid(), model.guid()); 84 ASSERT_EQ(specifics.cache_guid(), model.guid());
79 ASSERT_EQ(specifics.client_name(), model.client_name()); 85 ASSERT_EQ(specifics.client_name(), model.client_name());
80 ASSERT_EQ(specifics.device_type(), model.device_type()); 86 ASSERT_EQ(specifics.device_type(), model.device_type());
81 ASSERT_EQ(specifics.sync_user_agent(), model.sync_user_agent()); 87 ASSERT_EQ(specifics.sync_user_agent(), model.sync_user_agent());
82 ASSERT_EQ(specifics.chrome_version(), model.chrome_version()); 88 ASSERT_EQ(specifics.chrome_version(), model.chrome_version());
83 ASSERT_EQ(specifics.signin_scoped_device_id(), 89 ASSERT_EQ(specifics.signin_scoped_device_id(),
84 model.signin_scoped_device_id()); 90 model.signin_scoped_device_id());
85 } 91 }
86 92
87 void AssertErrorFromDataBatch(SyncError error,
88 std::unique_ptr<DataBatch> batch) {
89 ASSERT_TRUE(error.IsSet());
90 }
91
92 void AssertExpectedFromDataBatch( 93 void AssertExpectedFromDataBatch(
93 std::map<std::string, DeviceInfoSpecifics> expected, 94 std::map<std::string, DeviceInfoSpecifics> expected,
94 SyncError error, 95 SyncError error,
95 std::unique_ptr<DataBatch> batch) { 96 std::unique_ptr<DataBatch> batch) {
96 ASSERT_FALSE(error.IsSet()); 97 ASSERT_FALSE(error.IsSet());
97 while (batch->HasNext()) { 98 while (batch->HasNext()) {
98 const TagAndData& pair = batch->Next(); 99 const TagAndData& pair = batch->Next();
99 std::map<std::string, DeviceInfoSpecifics>::iterator iter = 100 std::map<std::string, DeviceInfoSpecifics>::iterator iter =
100 expected.find(pair.first); 101 expected.find(pair.first);
101 ASSERT_NE(iter, expected.end()); 102 ASSERT_NE(iter, expected.end());
102 AssertEqual(iter->second, pair.second->specifics.device_info()); 103 AssertEqual(iter->second, pair.second->specifics.device_info());
103 // Removing allows us to verify we don't see the same item multiple times, 104 // Removing allows us to verify we don't see the same item multiple times,
104 // and that we saw everything we expected. 105 // and that we saw everything we expected.
105 expected.erase(iter); 106 expected.erase(iter);
106 } 107 }
107 ASSERT_TRUE(expected.empty()); 108 ASSERT_TRUE(expected.empty());
108 } 109 }
109 110
110 // Creats an EntityData/EntityDataPtr around a copy of the given specifics. 111 // Creates an EntityData/EntityDataPtr around a copy of the given specifics.
111 EntityDataPtr SpecificsToEntity(const DeviceInfoSpecifics& specifics) { 112 EntityDataPtr SpecificsToEntity(const DeviceInfoSpecifics& specifics) {
112 EntityData data; 113 EntityData data;
113 // These tests do not care about the tag hash, but EntityData and friends 114 // These tests do not care about the tag hash, but EntityData and friends
114 // cannot differentiate between the default EntityData object if the hash 115 // cannot differentiate between the default EntityData object if the hash
115 // is unset, which causes pass/copy operations to no-op and things start to 116 // is unset, which causes pass/copy operations to no-op and things start to
116 // break, so we throw in a junk value and forget about it. 117 // break, so we throw in a junk value and forget about it.
117 data.client_tag_hash = "junk"; 118 data.client_tag_hash = "junk";
118 *data.specifics.mutable_device_info() = specifics; 119 *data.specifics.mutable_device_info() = specifics;
119 return data.PassToPtr(); 120 return data.PassToPtr();
120 } 121 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 }; 163 };
163 164
164 } // namespace 165 } // namespace
165 166
166 class DeviceInfoServiceTest : public testing::Test, 167 class DeviceInfoServiceTest : public testing::Test,
167 public DeviceInfoTracker::Observer { 168 public DeviceInfoTracker::Observer {
168 protected: 169 protected:
169 DeviceInfoServiceTest() 170 DeviceInfoServiceTest()
170 : change_count_(0), 171 : change_count_(0),
171 store_(ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()), 172 store_(ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()),
172 local_device_(new LocalDeviceInfoProviderMock( 173 local_device_(new LocalDeviceInfoProviderMock()) {
173 "guid_1", 174 local_device_->Initialize(CreateDeviceInfo());
174 "client_1", 175 }
175 "Chromium 10k",
176 "Chrome 10k",
177 sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
178 "device_id")) {}
179 176
180 ~DeviceInfoServiceTest() override { 177 ~DeviceInfoServiceTest() override {
181 // Some tests may never initialize the service. 178 // Some tests may never initialize the service.
182 if (service_) 179 if (service_)
183 service_->RemoveObserver(this); 180 service_->RemoveObserver(this);
184 181
185 // Force all remaining (store) tasks to execute so we don't leak memory. 182 // Force all remaining (store) tasks to execute so we don't leak memory.
186 base::RunLoop().RunUntilIdle(); 183 base::RunLoop().RunUntilIdle();
187 } 184 }
188 185
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 base::RunLoop().RunUntilIdle(); 360 base::RunLoop().RunUntilIdle();
364 ScopedVector<DeviceInfo> all_device_info(service()->GetAllDeviceInfo()); 361 ScopedVector<DeviceInfo> all_device_info(service()->GetAllDeviceInfo());
365 ASSERT_EQ(1u, all_device_info.size()); 362 ASSERT_EQ(1u, all_device_info.size());
366 ASSERT_TRUE( 363 ASSERT_TRUE(
367 local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0])); 364 local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0]));
368 } 365 }
369 366
370 TEST_F(DeviceInfoServiceTest, LocalProviderSubscription) { 367 TEST_F(DeviceInfoServiceTest, LocalProviderSubscription) {
371 set_local_device(base::WrapUnique(new LocalDeviceInfoProviderMock())); 368 set_local_device(base::WrapUnique(new LocalDeviceInfoProviderMock()));
372 InitializeAndPumpAndStart(); 369 InitializeAndPumpAndStart();
370
373 ASSERT_EQ(0u, service()->GetAllDeviceInfo().size()); 371 ASSERT_EQ(0u, service()->GetAllDeviceInfo().size());
374 local_device()->Initialize(base::WrapUnique( 372 local_device()->Initialize(CreateDeviceInfo());
375 new DeviceInfo("guid_1", "client_1", "Chromium 10k", "Chrome 10k", 373 base::RunLoop().RunUntilIdle();
376 sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id"))); 374
377 ScopedVector<DeviceInfo> all_device_info(service()->GetAllDeviceInfo()); 375 ScopedVector<DeviceInfo> all_device_info(service()->GetAllDeviceInfo());
378 ASSERT_EQ(1u, all_device_info.size()); 376 ASSERT_EQ(1u, all_device_info.size());
379 ASSERT_TRUE( 377 ASSERT_TRUE(
380 local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0])); 378 local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0]));
381 } 379 }
382 380
381 // Metadata shouldn't be loaded before the provider is initialized.
382 TEST_F(DeviceInfoServiceTest, LocalProviderInitRace) {
383 set_local_device(base::WrapUnique(new LocalDeviceInfoProviderMock()));
384 InitializeAndPump();
385 OnSyncStarting();
386 EXPECT_FALSE(processor()->metadata());
387
388 ASSERT_EQ(0u, service()->GetAllDeviceInfo().size());
389 local_device()->Initialize(CreateDeviceInfo());
390 base::RunLoop().RunUntilIdle();
391
392 ScopedVector<DeviceInfo> all_device_info(service()->GetAllDeviceInfo());
393 ASSERT_EQ(1u, all_device_info.size());
394 ASSERT_TRUE(
395 local_device()->GetLocalDeviceInfo()->Equals(*all_device_info[0]));
396
397 EXPECT_TRUE(processor()->metadata());
398 }
399
383 TEST_F(DeviceInfoServiceTest, GetClientTagNormal) { 400 TEST_F(DeviceInfoServiceTest, GetClientTagNormal) {
384 InitializeService(); 401 InitializeService();
385 const std::string guid = "abc"; 402 const std::string guid = "abc";
386 EntitySpecifics entity_specifics; 403 EntitySpecifics entity_specifics;
387 entity_specifics.mutable_device_info()->set_cache_guid(guid); 404 entity_specifics.mutable_device_info()->set_cache_guid(guid);
388 EntityData entity_data; 405 EntityData entity_data;
389 entity_data.specifics = entity_specifics; 406 entity_data.specifics = entity_specifics;
390 EXPECT_EQ(CacheGuidToTag(guid), service()->GetClientTag(entity_data)); 407 EXPECT_EQ(CacheGuidToTag(guid), service()->GetClientTag(entity_data));
391 } 408 }
392 409
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 498
482 TEST_F(DeviceInfoServiceTest, GetDataMissing) { 499 TEST_F(DeviceInfoServiceTest, GetDataMissing) {
483 InitializeAndPump(); 500 InitializeAndPump();
484 std::map<std::string, DeviceInfoSpecifics> expected; 501 std::map<std::string, DeviceInfoSpecifics> expected;
485 ClientTagList client_tags; 502 ClientTagList client_tags;
486 client_tags.push_back(CacheGuidToTag("tag1")); 503 client_tags.push_back(CacheGuidToTag("tag1"));
487 service()->GetData(client_tags, 504 service()->GetData(client_tags,
488 base::Bind(&AssertExpectedFromDataBatch, expected)); 505 base::Bind(&AssertExpectedFromDataBatch, expected));
489 } 506 }
490 507
491 TEST_F(DeviceInfoServiceTest, GetDataNotInitialized) {
492 InitializeService();
493 ClientTagList client_tags;
494 service()->GetData(client_tags, base::Bind(&AssertErrorFromDataBatch));
495 }
496
497 TEST_F(DeviceInfoServiceTest, GetAllData) { 508 TEST_F(DeviceInfoServiceTest, GetAllData) {
498 std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch(); 509 std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch();
499 DeviceInfoSpecifics specifics1(GenerateTestSpecifics()); 510 DeviceInfoSpecifics specifics1(GenerateTestSpecifics());
500 DeviceInfoSpecifics specifics2(GenerateTestSpecifics()); 511 DeviceInfoSpecifics specifics2(GenerateTestSpecifics());
501 const std::string& tag1 = CacheGuidToTag(specifics1.cache_guid()); 512 const std::string& tag1 = CacheGuidToTag(specifics1.cache_guid());
502 const std::string& tag2 = CacheGuidToTag(specifics2.cache_guid()); 513 const std::string& tag2 = CacheGuidToTag(specifics2.cache_guid());
503 store()->WriteData(batch.get(), specifics1.cache_guid(), 514 store()->WriteData(batch.get(), specifics1.cache_guid(),
504 specifics1.SerializeAsString()); 515 specifics1.SerializeAsString());
505 store()->WriteData(batch.get(), specifics2.cache_guid(), 516 store()->WriteData(batch.get(), specifics2.cache_guid(),
506 specifics2.SerializeAsString()); 517 specifics2.SerializeAsString());
507 store()->CommitWriteBatch(std::move(batch), 518 store()->CommitWriteBatch(std::move(batch),
508 base::Bind(&AssertResultIsSuccess)); 519 base::Bind(&AssertResultIsSuccess));
509 520
510 InitializeAndPump(); 521 InitializeAndPump();
511 522
512 std::map<std::string, DeviceInfoSpecifics> expected; 523 std::map<std::string, DeviceInfoSpecifics> expected;
513 expected[tag1] = specifics1; 524 expected[tag1] = specifics1;
514 expected[tag2] = specifics2; 525 expected[tag2] = specifics2;
515 ClientTagList client_tags; 526 ClientTagList client_tags;
516 client_tags.push_back(tag1); 527 client_tags.push_back(tag1);
517 client_tags.push_back(tag2); 528 client_tags.push_back(tag2);
518 service()->GetData(client_tags, 529 service()->GetData(client_tags,
519 base::Bind(&AssertExpectedFromDataBatch, expected)); 530 base::Bind(&AssertExpectedFromDataBatch, expected));
520 } 531 }
521 532
522 TEST_F(DeviceInfoServiceTest, GetAllDataNotInitialized) {
523 InitializeService();
524 service()->GetAllData(base::Bind(&AssertErrorFromDataBatch));
525 }
526
527 TEST_F(DeviceInfoServiceTest, ApplySyncChangesBeforeInit) {
528 InitializeService();
529 const SyncError error = service()->ApplySyncChanges(
530 service()->CreateMetadataChangeList(), EntityChangeList());
531 EXPECT_TRUE(error.IsSet());
532 EXPECT_EQ(0, change_count());
533 }
534
535 TEST_F(DeviceInfoServiceTest, ApplySyncChangesEmpty) { 533 TEST_F(DeviceInfoServiceTest, ApplySyncChangesEmpty) {
536 InitializeAndPump(); 534 InitializeAndPump();
537 const SyncError error = service()->ApplySyncChanges( 535 const SyncError error = service()->ApplySyncChanges(
538 service()->CreateMetadataChangeList(), EntityChangeList()); 536 service()->CreateMetadataChangeList(), EntityChangeList());
539 EXPECT_FALSE(error.IsSet()); 537 EXPECT_FALSE(error.IsSet());
540 EXPECT_EQ(0, change_count()); 538 EXPECT_EQ(0, change_count());
541 } 539 }
542 540
543 TEST_F(DeviceInfoServiceTest, ApplySyncChangesInMemory) { 541 TEST_F(DeviceInfoServiceTest, ApplySyncChangesInMemory) {
544 InitializeAndPump(); 542 InitializeAndPump();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 InitializeAndPumpAndStart(); 637 InitializeAndPumpAndStart();
640 EXPECT_EQ(1, change_count()); 638 EXPECT_EQ(1, change_count());
641 EntityChangeList delete_changes; 639 EntityChangeList delete_changes;
642 delete_changes.push_back(EntityChange::CreateDelete(CacheGuidToTag("tag"))); 640 delete_changes.push_back(EntityChange::CreateDelete(CacheGuidToTag("tag")));
643 const SyncError error = service()->ApplySyncChanges( 641 const SyncError error = service()->ApplySyncChanges(
644 service()->CreateMetadataChangeList(), delete_changes); 642 service()->CreateMetadataChangeList(), delete_changes);
645 EXPECT_FALSE(error.IsSet()); 643 EXPECT_FALSE(error.IsSet());
646 EXPECT_EQ(1, change_count()); 644 EXPECT_EQ(1, change_count());
647 } 645 }
648 646
649 TEST_F(DeviceInfoServiceTest, MergeWithoutProcessor) {
650 InitializeService();
651 const SyncError error = service()->MergeSyncData(
652 service()->CreateMetadataChangeList(), EntityDataMap());
653 EXPECT_TRUE(error.IsSet());
654 EXPECT_EQ(0, change_count());
655 }
656
657 TEST_F(DeviceInfoServiceTest, MergeEmpty) { 647 TEST_F(DeviceInfoServiceTest, MergeEmpty) {
658 InitializeAndPumpAndStart(); 648 InitializeAndPumpAndStart();
659 EXPECT_EQ(1, change_count()); 649 EXPECT_EQ(1, change_count());
660 const SyncError error = service()->MergeSyncData( 650 const SyncError error = service()->MergeSyncData(
661 service()->CreateMetadataChangeList(), EntityDataMap()); 651 service()->CreateMetadataChangeList(), EntityDataMap());
662 EXPECT_FALSE(error.IsSet()); 652 EXPECT_FALSE(error.IsSet());
663 EXPECT_EQ(1, change_count()); 653 EXPECT_EQ(1, change_count());
664 EXPECT_EQ(1u, processor()->put_map().size()); 654 EXPECT_EQ(1u, processor()->put_map().size());
665 EXPECT_EQ(0u, processor()->delete_set().size()); 655 EXPECT_EQ(0u, processor()->delete_set().size());
666 } 656 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 specifics.set_cache_guid("non-local"); 767 specifics.set_cache_guid("non-local");
778 PushBackEntityChangeAdd(specifics, &change_list); 768 PushBackEntityChangeAdd(specifics, &change_list);
779 service()->ApplySyncChanges(service()->CreateMetadataChangeList(), 769 service()->ApplySyncChanges(service()->CreateMetadataChangeList(),
780 change_list); 770 change_list);
781 EXPECT_EQ(1, service()->CountActiveDevices()); 771 EXPECT_EQ(1, service()->CountActiveDevices());
782 } 772 }
783 773
784 } // namespace 774 } // namespace
785 775
786 } // namespace sync_driver_v2 776 } // namespace sync_driver_v2
OLDNEW
« no previous file with comments | « components/sync_driver/device_info_service.cc ('k') | sync/api/fake_model_type_change_processor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698