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

Side by Side Diff: components/sync/device_info/device_info_service_unittest.cc

Issue 2460903003: [Sync] Rename DeviceInfoService to DeviceInfoSyncBridge. (Closed)
Patch Set: Updating nullptr to null in comment. Created 4 years, 1 month 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/sync/device_info/device_info_service.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/run_loop.h"
15 #include "base/strings/stringprintf.h"
16 #include "components/sync/base/time.h"
17 #include "components/sync/device_info/local_device_info_provider_mock.h"
18 #include "components/sync/model/data_batch.h"
19 #include "components/sync/model/data_type_error_handler_mock.h"
20 #include "components/sync/model/entity_data.h"
21 #include "components/sync/model/fake_model_type_change_processor.h"
22 #include "components/sync/model/metadata_batch.h"
23 #include "components/sync/model/model_type_store_test_util.h"
24 #include "components/sync/protocol/model_type_state.pb.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 namespace syncer {
28
29 using base::Time;
30 using base::TimeDelta;
31 using sync_pb::DeviceInfoSpecifics;
32 using sync_pb::EntitySpecifics;
33 using sync_pb::ModelTypeState;
34
35 using DeviceInfoList = std::vector<std::unique_ptr<DeviceInfo>>;
36 using StorageKeyList = ModelTypeSyncBridge::StorageKeyList;
37 using RecordList = ModelTypeStore::RecordList;
38 using Result = ModelTypeStore::Result;
39 using StartCallback = ModelTypeChangeProcessor::StartCallback;
40 using WriteBatch = ModelTypeStore::WriteBatch;
41
42 namespace {
43
44 const char kGuidFormat[] = "cache guid %d";
45 const char kClientNameFormat[] = "client name %d";
46 const char kChromeVersionFormat[] = "chrome version %d";
47 const char kSyncUserAgentFormat[] = "sync user agent %d";
48 const char kSigninScopedDeviceIdFormat[] = "signin scoped device id %d";
49 const sync_pb::SyncEnums::DeviceType kDeviceType =
50 sync_pb::SyncEnums_DeviceType_TYPE_LINUX;
51
52 // The |provider_| is first initialized with a model object created with this
53 // suffix. Local suffix can be changed by setting the provider and then
54 // initializing. Remote data should use other suffixes.
55 const int kDefaultLocalSuffix = 0;
56
57 DeviceInfoSpecifics CreateSpecifics(int suffix) {
58 DeviceInfoSpecifics specifics;
59 specifics.set_cache_guid(base::StringPrintf(kGuidFormat, suffix));
60 specifics.set_client_name(base::StringPrintf(kClientNameFormat, suffix));
61 specifics.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
62 specifics.set_sync_user_agent(
63 base::StringPrintf(kSyncUserAgentFormat, suffix));
64 specifics.set_chrome_version(
65 base::StringPrintf(kChromeVersionFormat, suffix));
66 specifics.set_signin_scoped_device_id(
67 base::StringPrintf(kSigninScopedDeviceIdFormat, suffix));
68 return specifics;
69 }
70
71 std::unique_ptr<DeviceInfo> CreateModel(int suffix) {
72 return base::MakeUnique<DeviceInfo>(
73 base::StringPrintf(kGuidFormat, suffix),
74 base::StringPrintf(kClientNameFormat, suffix),
75 base::StringPrintf(kChromeVersionFormat, suffix),
76 base::StringPrintf(kSyncUserAgentFormat, suffix), kDeviceType,
77 base::StringPrintf(kSigninScopedDeviceIdFormat, suffix));
78 }
79
80 void VerifyResultIsSuccess(Result result) {
81 EXPECT_EQ(Result::SUCCESS, result);
82 }
83
84 void VerifyEqual(const DeviceInfoSpecifics& s1, const DeviceInfoSpecifics& s2) {
85 EXPECT_EQ(s1.cache_guid(), s2.cache_guid());
86 EXPECT_EQ(s1.client_name(), s2.client_name());
87 EXPECT_EQ(s1.device_type(), s2.device_type());
88 EXPECT_EQ(s1.sync_user_agent(), s2.sync_user_agent());
89 EXPECT_EQ(s1.chrome_version(), s2.chrome_version());
90 EXPECT_EQ(s1.signin_scoped_device_id(), s2.signin_scoped_device_id());
91 }
92
93 void VerifyEqual(const DeviceInfoSpecifics& specifics,
94 const DeviceInfo& model) {
95 EXPECT_EQ(specifics.cache_guid(), model.guid());
96 EXPECT_EQ(specifics.client_name(), model.client_name());
97 EXPECT_EQ(specifics.device_type(), model.device_type());
98 EXPECT_EQ(specifics.sync_user_agent(), model.sync_user_agent());
99 EXPECT_EQ(specifics.chrome_version(), model.chrome_version());
100 EXPECT_EQ(specifics.signin_scoped_device_id(),
101 model.signin_scoped_device_id());
102 }
103
104 void VerifyDataBatch(std::map<std::string, DeviceInfoSpecifics> expected,
105 SyncError error,
106 std::unique_ptr<DataBatch> batch) {
107 EXPECT_FALSE(error.IsSet());
108 while (batch->HasNext()) {
109 const KeyAndData& pair = batch->Next();
110 auto iter = expected.find(pair.first);
111 ASSERT_NE(iter, expected.end());
112 VerifyEqual(iter->second, pair.second->specifics.device_info());
113 // Removing allows us to verify we don't see the same item multiple times,
114 // and that we saw everything we expected.
115 expected.erase(iter);
116 }
117 EXPECT_TRUE(expected.empty());
118 }
119
120 // Creates an EntityData/EntityDataPtr around a copy of the given specifics.
121 EntityDataPtr SpecificsToEntity(const DeviceInfoSpecifics& specifics) {
122 EntityData data;
123 // These tests do not care about the tag hash, but EntityData and friends
124 // cannot differentiate between the default EntityData object if the hash
125 // is unset, which causes pass/copy operations to no-op and things start to
126 // break, so we throw in a junk value and forget about it.
127 data.client_tag_hash = "junk";
128 *data.specifics.mutable_device_info() = specifics;
129 return data.PassToPtr();
130 }
131
132 std::string CacheGuidToTag(const std::string& guid) {
133 return "DeviceInfo_" + guid;
134 }
135
136 // Helper method to reduce duplicated code between tests. Wraps the given
137 // specifics objects in an EntityData and EntityChange of type ACTION_ADD, and
138 // returns an EntityChangeList containing them all. Order is maintained.
139 EntityChangeList EntityAddList(
140 std::vector<DeviceInfoSpecifics> specifics_list) {
141 EntityChangeList changes;
142 for (const auto& specifics : specifics_list) {
143 changes.push_back(EntityChange::CreateAdd(specifics.cache_guid(),
144 SpecificsToEntity(specifics)));
145 }
146 return changes;
147 }
148
149 // Instead of actually processing anything, simply accumulates all instructions
150 // in members that can then be accessed. TODO(skym): If this ends up being
151 // useful for other model type unittests it should be moved out to a shared
152 // location.
153 class RecordingModelTypeChangeProcessor : public FakeModelTypeChangeProcessor {
154 public:
155 RecordingModelTypeChangeProcessor() {}
156 ~RecordingModelTypeChangeProcessor() override {}
157
158 void Put(const std::string& storage_key,
159 std::unique_ptr<EntityData> entity_data,
160 MetadataChangeList* metadata_changes) override {
161 put_multimap_.insert(std::make_pair(storage_key, std::move(entity_data)));
162 }
163
164 void Delete(const std::string& storage_key,
165 MetadataChangeList* metadata_changes) override {
166 delete_set_.insert(storage_key);
167 }
168
169 void OnMetadataLoaded(SyncError error,
170 std::unique_ptr<MetadataBatch> batch) override {
171 std::swap(metadata_, batch);
172 }
173
174 const std::multimap<std::string, std::unique_ptr<EntityData>>& put_multimap()
175 const {
176 return put_multimap_;
177 }
178 const std::set<std::string>& delete_set() const { return delete_set_; }
179 const MetadataBatch* metadata() const { return metadata_.get(); }
180
181 private:
182 std::multimap<std::string, std::unique_ptr<EntityData>> put_multimap_;
183 std::set<std::string> delete_set_;
184 std::unique_ptr<MetadataBatch> metadata_;
185 };
186
187 } // namespace
188
189 class DeviceInfoServiceTest : public testing::Test,
190 public DeviceInfoTracker::Observer {
191 protected:
192 DeviceInfoServiceTest()
193 : store_(ModelTypeStoreTestUtil::CreateInMemoryStoreForTest()),
194 provider_(new LocalDeviceInfoProviderMock()) {
195 provider_->Initialize(CreateModel(kDefaultLocalSuffix));
196 }
197
198 ~DeviceInfoServiceTest() override {
199 // Some tests may never initialize the service.
200 if (service_)
201 service_->RemoveObserver(this);
202
203 // Force all remaining (store) tasks to execute so we don't leak memory.
204 base::RunLoop().RunUntilIdle();
205 }
206
207 void OnDeviceInfoChange() override { change_count_++; }
208
209 std::unique_ptr<ModelTypeChangeProcessor> CreateModelTypeChangeProcessor(
210 ModelType type,
211 ModelTypeSyncBridge* bridge) {
212 auto processor = base::MakeUnique<RecordingModelTypeChangeProcessor>();
213 processor_ = processor.get();
214 return std::move(processor);
215 }
216
217 // Initialized the service based on the current local device and store. Can
218 // only be called once per run, as it passes |store_|.
219 void InitializeService() {
220 ASSERT_TRUE(store_);
221 service_ = base::MakeUnique<DeviceInfoService>(
222 provider_.get(),
223 base::Bind(&ModelTypeStoreTestUtil::MoveStoreToCallback,
224 base::Passed(&store_)),
225 base::Bind(&DeviceInfoServiceTest::CreateModelTypeChangeProcessor,
226 base::Unretained(this)));
227 service_->AddObserver(this);
228 }
229
230 // Creates the service and runs any outstanding tasks. This will typically
231 // cause all initialization callbacks between the sevice and store to fire.
232 void InitializeAndPump() {
233 InitializeService();
234 base::RunLoop().RunUntilIdle();
235 }
236
237 // Allows access to the store before that will ultimately be used to
238 // initialize the service.
239 ModelTypeStore* store() {
240 EXPECT_TRUE(store_);
241 return store_.get();
242 }
243
244 // Get the number of times the service notifies observers of changes.
245 int change_count() { return change_count_; }
246
247 // Allows overriding the provider before the service is initialized.
248 void set_provider(std::unique_ptr<LocalDeviceInfoProviderMock> provider) {
249 ASSERT_FALSE(service_);
250 std::swap(provider_, provider);
251 }
252 LocalDeviceInfoProviderMock* local_device() { return provider_.get(); }
253
254 // Allows access to the service after InitializeService() is called.
255 DeviceInfoService* service() {
256 EXPECT_TRUE(service_);
257 return service_.get();
258 }
259
260 RecordingModelTypeChangeProcessor* processor() {
261 EXPECT_TRUE(processor_);
262 return processor_;
263 }
264
265 // Should only be called after the service has been initialized. Will first
266 // recover the service's store, so another can be initialized later, and then
267 // deletes the service.
268 void PumpAndShutdown() {
269 ASSERT_TRUE(service_);
270 base::RunLoop().RunUntilIdle();
271 std::swap(store_, service_->store_);
272 service_->RemoveObserver(this);
273 service_.reset();
274 }
275
276 void RestartService() {
277 PumpAndShutdown();
278 InitializeAndPump();
279 }
280
281 void ForcePulse() { service()->SendLocalData(); }
282
283 private:
284 int change_count_ = 0;
285
286 // In memory model type store needs a MessageLoop.
287 base::MessageLoop message_loop_;
288
289 // Holds the store while the service is not initialized.
290 std::unique_ptr<ModelTypeStore> store_;
291
292 // Provides information about the local device. Is initialized in each case's
293 // constructor with a model object created from |kDefaultLocalSuffix|.
294 std::unique_ptr<LocalDeviceInfoProviderMock> provider_;
295
296 // Not initialized immediately (upon test's constructor). This allows each
297 // test case to modify the dependencies the service will be constructed with.
298 std::unique_ptr<DeviceInfoService> service_;
299
300 // A non-owning pointer to the processor given to the service. Will be nullptr
301 // before being given to the service, to make ownership easier.
302 RecordingModelTypeChangeProcessor* processor_ = nullptr;
303 };
304
305 namespace {
306
307 TEST_F(DeviceInfoServiceTest, EmptyDataReconciliation) {
308 InitializeAndPump();
309 DeviceInfoList devices = service()->GetAllDeviceInfo();
310 ASSERT_EQ(1u, devices.size());
311 EXPECT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0]));
312 }
313
314 TEST_F(DeviceInfoServiceTest, EmptyDataReconciliationSlowLoad) {
315 InitializeService();
316 EXPECT_EQ(0u, service()->GetAllDeviceInfo().size());
317 base::RunLoop().RunUntilIdle();
318 DeviceInfoList devices = service()->GetAllDeviceInfo();
319 ASSERT_EQ(1u, devices.size());
320 EXPECT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0]));
321 }
322
323 TEST_F(DeviceInfoServiceTest, LocalProviderSubscription) {
324 set_provider(base::MakeUnique<LocalDeviceInfoProviderMock>());
325 InitializeAndPump();
326
327 EXPECT_EQ(0u, service()->GetAllDeviceInfo().size());
328 local_device()->Initialize(CreateModel(1));
329 base::RunLoop().RunUntilIdle();
330
331 DeviceInfoList devices = service()->GetAllDeviceInfo();
332 ASSERT_EQ(1u, devices.size());
333 EXPECT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0]));
334 }
335
336 // Metadata shouldn't be loaded before the provider is initialized.
337 TEST_F(DeviceInfoServiceTest, LocalProviderInitRace) {
338 set_provider(base::MakeUnique<LocalDeviceInfoProviderMock>());
339 InitializeAndPump();
340 EXPECT_FALSE(processor()->metadata());
341
342 EXPECT_EQ(0u, service()->GetAllDeviceInfo().size());
343 local_device()->Initialize(CreateModel(1));
344 base::RunLoop().RunUntilIdle();
345
346 DeviceInfoList devices = service()->GetAllDeviceInfo();
347 ASSERT_EQ(1u, devices.size());
348 EXPECT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0]));
349
350 EXPECT_TRUE(processor()->metadata());
351 }
352
353 TEST_F(DeviceInfoServiceTest, GetClientTagNormal) {
354 InitializeService();
355 const std::string guid = "abc";
356 EntitySpecifics entity_specifics;
357 entity_specifics.mutable_device_info()->set_cache_guid(guid);
358 EntityData entity_data;
359 entity_data.specifics = entity_specifics;
360 EXPECT_EQ(CacheGuidToTag(guid), service()->GetClientTag(entity_data));
361 }
362
363 TEST_F(DeviceInfoServiceTest, GetClientTagEmpty) {
364 InitializeService();
365 EntitySpecifics entity_specifics;
366 entity_specifics.mutable_device_info();
367 EntityData entity_data;
368 entity_data.specifics = entity_specifics;
369 EXPECT_EQ(CacheGuidToTag(""), service()->GetClientTag(entity_data));
370 }
371
372 TEST_F(DeviceInfoServiceTest, TestWithLocalData) {
373 std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch();
374 DeviceInfoSpecifics specifics = CreateSpecifics(1);
375 store()->WriteData(batch.get(), specifics.cache_guid(),
376 specifics.SerializeAsString());
377 store()->CommitWriteBatch(std::move(batch),
378 base::Bind(&VerifyResultIsSuccess));
379
380 InitializeAndPump();
381
382 ASSERT_EQ(2u, service()->GetAllDeviceInfo().size());
383 VerifyEqual(specifics,
384 *service()->GetDeviceInfo(specifics.cache_guid()).get());
385 }
386
387 TEST_F(DeviceInfoServiceTest, TestWithLocalMetadata) {
388 std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch();
389 ModelTypeState state;
390 state.set_encryption_key_name("ekn");
391 store()->WriteGlobalMetadata(batch.get(), state.SerializeAsString());
392 store()->CommitWriteBatch(std::move(batch),
393 base::Bind(&VerifyResultIsSuccess));
394 InitializeAndPump();
395 DeviceInfoList devices = service()->GetAllDeviceInfo();
396 ASSERT_EQ(1u, devices.size());
397 EXPECT_TRUE(local_device()->GetLocalDeviceInfo()->Equals(*devices[0]));
398 EXPECT_EQ(1u, processor()->put_multimap().size());
399 }
400
401 TEST_F(DeviceInfoServiceTest, TestWithLocalDataAndMetadata) {
402 std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch();
403 DeviceInfoSpecifics specifics = CreateSpecifics(1);
404 store()->WriteData(batch.get(), specifics.cache_guid(),
405 specifics.SerializeAsString());
406 ModelTypeState state;
407 state.set_encryption_key_name("ekn");
408 store()->WriteGlobalMetadata(batch.get(), state.SerializeAsString());
409 store()->CommitWriteBatch(std::move(batch),
410 base::Bind(&VerifyResultIsSuccess));
411
412 InitializeAndPump();
413
414 ASSERT_EQ(2u, service()->GetAllDeviceInfo().size());
415 VerifyEqual(specifics,
416 *service()->GetDeviceInfo(specifics.cache_guid()).get());
417 EXPECT_TRUE(processor()->metadata());
418 EXPECT_EQ(state.encryption_key_name(),
419 processor()->metadata()->GetModelTypeState().encryption_key_name());
420 }
421
422 TEST_F(DeviceInfoServiceTest, GetData) {
423 std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch();
424 DeviceInfoSpecifics specifics1 = CreateSpecifics(1);
425 DeviceInfoSpecifics specifics2 = CreateSpecifics(2);
426 DeviceInfoSpecifics specifics3 = CreateSpecifics(3);
427 store()->WriteData(batch.get(), specifics1.cache_guid(),
428 specifics1.SerializeAsString());
429 store()->WriteData(batch.get(), specifics2.cache_guid(),
430 specifics2.SerializeAsString());
431 store()->WriteData(batch.get(), specifics3.cache_guid(),
432 specifics3.SerializeAsString());
433 store()->CommitWriteBatch(std::move(batch),
434 base::Bind(&VerifyResultIsSuccess));
435
436 InitializeAndPump();
437
438 std::map<std::string, DeviceInfoSpecifics> expected{
439 {specifics1.cache_guid(), specifics1},
440 {specifics3.cache_guid(), specifics3}};
441 service()->GetData({specifics1.cache_guid(), specifics3.cache_guid()},
442 base::Bind(&VerifyDataBatch, expected));
443 }
444
445 TEST_F(DeviceInfoServiceTest, GetDataMissing) {
446 InitializeAndPump();
447 service()->GetData({"does_not_exist"},
448 base::Bind(&VerifyDataBatch,
449 std::map<std::string, DeviceInfoSpecifics>()));
450 }
451
452 TEST_F(DeviceInfoServiceTest, GetAllData) {
453 std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch();
454 DeviceInfoSpecifics specifics1 = CreateSpecifics(1);
455 DeviceInfoSpecifics specifics2 = CreateSpecifics(2);
456 const std::string& guid1 = specifics1.cache_guid();
457 const std::string& guid2 = specifics2.cache_guid();
458 store()->WriteData(batch.get(), specifics1.cache_guid(),
459 specifics1.SerializeAsString());
460 store()->WriteData(batch.get(), specifics2.cache_guid(),
461 specifics2.SerializeAsString());
462 store()->CommitWriteBatch(std::move(batch),
463 base::Bind(&VerifyResultIsSuccess));
464
465 InitializeAndPump();
466
467 std::map<std::string, DeviceInfoSpecifics> expected{{guid1, specifics1},
468 {guid2, specifics2}};
469 service()->GetData({guid1, guid2}, base::Bind(&VerifyDataBatch, expected));
470 }
471
472 TEST_F(DeviceInfoServiceTest, ApplySyncChangesEmpty) {
473 InitializeAndPump();
474 EXPECT_EQ(1, change_count());
475 const SyncError error = service()->ApplySyncChanges(
476 service()->CreateMetadataChangeList(), EntityChangeList());
477 EXPECT_FALSE(error.IsSet());
478 EXPECT_EQ(1, change_count());
479 }
480
481 TEST_F(DeviceInfoServiceTest, ApplySyncChangesInMemory) {
482 InitializeAndPump();
483 EXPECT_EQ(1, change_count());
484
485 DeviceInfoSpecifics specifics = CreateSpecifics(1);
486 const SyncError error_on_add = service()->ApplySyncChanges(
487 service()->CreateMetadataChangeList(), EntityAddList({specifics}));
488
489 EXPECT_FALSE(error_on_add.IsSet());
490 std::unique_ptr<DeviceInfo> info =
491 service()->GetDeviceInfo(specifics.cache_guid());
492 ASSERT_TRUE(info);
493 VerifyEqual(specifics, *info.get());
494 EXPECT_EQ(2, change_count());
495
496 const SyncError error_on_delete = service()->ApplySyncChanges(
497 service()->CreateMetadataChangeList(),
498 {EntityChange::CreateDelete(specifics.cache_guid())});
499
500 EXPECT_FALSE(error_on_delete.IsSet());
501 EXPECT_FALSE(service()->GetDeviceInfo(specifics.cache_guid()));
502 EXPECT_EQ(3, change_count());
503 }
504
505 TEST_F(DeviceInfoServiceTest, ApplySyncChangesStore) {
506 InitializeAndPump();
507 EXPECT_EQ(1, change_count());
508
509 DeviceInfoSpecifics specifics = CreateSpecifics(1);
510 ModelTypeState state;
511 state.set_encryption_key_name("ekn");
512 std::unique_ptr<MetadataChangeList> metadata_changes =
513 service()->CreateMetadataChangeList();
514 metadata_changes->UpdateModelTypeState(state);
515
516 const SyncError error = service()->ApplySyncChanges(
517 std::move(metadata_changes), EntityAddList({specifics}));
518 EXPECT_FALSE(error.IsSet());
519 EXPECT_EQ(2, change_count());
520
521 RestartService();
522
523 std::unique_ptr<DeviceInfo> info =
524 service()->GetDeviceInfo(specifics.cache_guid());
525 ASSERT_TRUE(info);
526 VerifyEqual(specifics, *info.get());
527
528 EXPECT_TRUE(processor()->metadata());
529 EXPECT_EQ(state.encryption_key_name(),
530 processor()->metadata()->GetModelTypeState().encryption_key_name());
531 }
532
533 TEST_F(DeviceInfoServiceTest, ApplySyncChangesWithLocalGuid) {
534 InitializeAndPump();
535
536 // The service should ignore these changes using this specifics because its
537 // guid will match the local device.
538 DeviceInfoSpecifics specifics = CreateSpecifics(kDefaultLocalSuffix);
539
540 // Should have a single change from reconciliation.
541 EXPECT_TRUE(
542 service()->GetDeviceInfo(local_device()->GetLocalDeviceInfo()->guid()));
543 EXPECT_EQ(1, change_count());
544 // Ensure |last_updated| is about now, plus or minus a little bit.
545 Time last_updated(ProtoTimeToTime(processor()
546 ->put_multimap()
547 .begin()
548 ->second->specifics.device_info()
549 .last_updated_timestamp()));
550 EXPECT_LT(Time::Now() - TimeDelta::FromMinutes(1), last_updated);
551 EXPECT_GT(Time::Now() + TimeDelta::FromMinutes(1), last_updated);
552
553 const SyncError error_on_add = service()->ApplySyncChanges(
554 service()->CreateMetadataChangeList(), EntityAddList({specifics}));
555 EXPECT_FALSE(error_on_add.IsSet());
556 EXPECT_EQ(1, change_count());
557
558 const SyncError error_on_delete = service()->ApplySyncChanges(
559 service()->CreateMetadataChangeList(),
560 {EntityChange::CreateDelete(specifics.cache_guid())});
561 EXPECT_FALSE(error_on_delete.IsSet());
562 EXPECT_EQ(1, change_count());
563 }
564
565 TEST_F(DeviceInfoServiceTest, ApplyDeleteNonexistent) {
566 InitializeAndPump();
567 EXPECT_EQ(1, change_count());
568 const SyncError error =
569 service()->ApplySyncChanges(service()->CreateMetadataChangeList(),
570 {EntityChange::CreateDelete("guid")});
571 EXPECT_FALSE(error.IsSet());
572 EXPECT_EQ(1, change_count());
573 }
574
575 TEST_F(DeviceInfoServiceTest, MergeEmpty) {
576 InitializeAndPump();
577 EXPECT_EQ(1, change_count());
578 const SyncError error = service()->MergeSyncData(
579 service()->CreateMetadataChangeList(), EntityDataMap());
580 EXPECT_FALSE(error.IsSet());
581 EXPECT_EQ(1, change_count());
582 // TODO(skym): Stop sending local twice. The first of the two puts will
583 // probably happen before the processor is tracking metadata yet, and so there
584 // should not be much overhead.
585 EXPECT_EQ(2u, processor()->put_multimap().size());
586 EXPECT_EQ(2u, processor()->put_multimap().count(
587 local_device()->GetLocalDeviceInfo()->guid()));
588 EXPECT_EQ(0u, processor()->delete_set().size());
589 }
590
591 TEST_F(DeviceInfoServiceTest, MergeWithData) {
592 const DeviceInfoSpecifics unique_local = CreateSpecifics(1);
593 DeviceInfoSpecifics conflict_local = CreateSpecifics(2);
594 DeviceInfoSpecifics conflict_remote = CreateSpecifics(3);
595 const DeviceInfoSpecifics unique_remote = CreateSpecifics(4);
596
597 const std::string conflict_guid = "conflict_guid";
598 conflict_local.set_cache_guid(conflict_guid);
599 conflict_remote.set_cache_guid(conflict_guid);
600
601 std::unique_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(&VerifyResultIsSuccess));
608
609 InitializeAndPump();
610 EXPECT_EQ(1, change_count());
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 ModelTypeState state;
618 state.set_encryption_key_name("ekn");
619 std::unique_ptr<MetadataChangeList> metadata_changes =
620 service()->CreateMetadataChangeList();
621 metadata_changes->UpdateModelTypeState(state);
622
623 const SyncError error =
624 service()->MergeSyncData(std::move(metadata_changes), remote_input);
625 EXPECT_FALSE(error.IsSet());
626 EXPECT_EQ(2, change_count());
627
628 // The remote should beat the local in conflict.
629 EXPECT_EQ(4u, service()->GetAllDeviceInfo().size());
630 VerifyEqual(unique_local,
631 *service()->GetDeviceInfo(unique_local.cache_guid()).get());
632 VerifyEqual(unique_remote,
633 *service()->GetDeviceInfo(unique_remote.cache_guid()).get());
634 VerifyEqual(conflict_remote, *service()->GetDeviceInfo(conflict_guid).get());
635
636 // Service should have told the processor about the existance of unique_local.
637 EXPECT_TRUE(processor()->delete_set().empty());
638 EXPECT_EQ(3u, processor()->put_multimap().size());
639 EXPECT_EQ(1u, processor()->put_multimap().count(unique_local.cache_guid()));
640 const auto& it = processor()->put_multimap().find(unique_local.cache_guid());
641 ASSERT_NE(processor()->put_multimap().end(), it);
642 VerifyEqual(unique_local, it->second->specifics.device_info());
643
644 RestartService();
645 EXPECT_EQ(state.encryption_key_name(),
646 processor()->metadata()->GetModelTypeState().encryption_key_name());
647 }
648
649 TEST_F(DeviceInfoServiceTest, MergeLocalGuid) {
650 const DeviceInfo* provider_info = local_device()->GetLocalDeviceInfo();
651 auto specifics = base::MakeUnique<DeviceInfoSpecifics>(CreateSpecifics(0));
652 specifics->set_last_updated_timestamp(TimeToProtoTime(Time::Now()));
653 const std::string guid = provider_info->guid();
654
655 std::unique_ptr<WriteBatch> batch = store()->CreateWriteBatch();
656 store()->WriteData(batch.get(), guid, specifics->SerializeAsString());
657 store()->CommitWriteBatch(std::move(batch),
658 base::Bind(&VerifyResultIsSuccess));
659
660 InitializeAndPump();
661
662 EntityDataMap remote_input;
663 remote_input[guid] = SpecificsToEntity(*specifics);
664
665 const SyncError error = service()->MergeSyncData(
666 service()->CreateMetadataChangeList(), remote_input);
667 EXPECT_FALSE(error.IsSet());
668 EXPECT_EQ(0, change_count());
669 EXPECT_EQ(1u, service()->GetAllDeviceInfo().size());
670 EXPECT_TRUE(processor()->delete_set().empty());
671 EXPECT_TRUE(processor()->put_multimap().empty());
672 }
673
674 TEST_F(DeviceInfoServiceTest, CountActiveDevices) {
675 InitializeAndPump();
676 EXPECT_EQ(1, service()->CountActiveDevices());
677
678 DeviceInfoSpecifics specifics = CreateSpecifics(0);
679 service()->ApplySyncChanges(service()->CreateMetadataChangeList(),
680 EntityAddList({specifics}));
681 EXPECT_EQ(1, service()->CountActiveDevices());
682
683 specifics.set_last_updated_timestamp(TimeToProtoTime(Time::Now()));
684 service()->ApplySyncChanges(service()->CreateMetadataChangeList(),
685 EntityAddList({specifics}));
686 EXPECT_EQ(1, service()->CountActiveDevices());
687
688 specifics.set_cache_guid("non-local");
689 service()->ApplySyncChanges(service()->CreateMetadataChangeList(),
690 EntityAddList({specifics}));
691 EXPECT_EQ(2, service()->CountActiveDevices());
692
693 // Now set time to long ago in the past, it should not be active anymore.
694 specifics.set_last_updated_timestamp(TimeToProtoTime(Time()));
695 service()->ApplySyncChanges(service()->CreateMetadataChangeList(),
696 EntityAddList({specifics}));
697 EXPECT_EQ(1, service()->CountActiveDevices());
698 }
699
700 TEST_F(DeviceInfoServiceTest, MultipleOnProviderInitialized) {
701 set_provider(base::MakeUnique<LocalDeviceInfoProviderMock>());
702 InitializeAndPump();
703 EXPECT_EQ(nullptr, processor()->metadata());
704
705 // Verify the processor was given metadata.
706 local_device()->Initialize(CreateModel(0));
707 base::RunLoop().RunUntilIdle();
708 const MetadataBatch* metadata = processor()->metadata();
709 EXPECT_NE(nullptr, metadata);
710
711 // Pointer address of metadata should remain constant because the processor
712 // should not have been given new metadata.
713 local_device()->Initialize(CreateModel(0));
714 base::RunLoop().RunUntilIdle();
715 EXPECT_EQ(metadata, processor()->metadata());
716 }
717
718 TEST_F(DeviceInfoServiceTest, SendLocalData) {
719 InitializeAndPump();
720 EXPECT_EQ(1, change_count());
721 EXPECT_EQ(1u, processor()->put_multimap().size());
722
723 ForcePulse();
724 EXPECT_EQ(2, change_count());
725 EXPECT_EQ(2u, processor()->put_multimap().size());
726
727 // After clearing, pulsing should no-op and not result in a processor put or
728 // a notification to observers.
729 local_device()->Clear();
730 ForcePulse();
731 EXPECT_EQ(2, change_count());
732 EXPECT_EQ(2u, processor()->put_multimap().size());
733 }
734
735 TEST_F(DeviceInfoServiceTest, DisableSync) {
736 InitializeAndPump();
737 EXPECT_EQ(1u, service()->GetAllDeviceInfo().size());
738 EXPECT_EQ(1, change_count());
739
740 DeviceInfoSpecifics specifics = CreateSpecifics(1);
741 const SyncError error = service()->ApplySyncChanges(
742 service()->CreateMetadataChangeList(), EntityAddList({specifics}));
743
744 EXPECT_FALSE(error.IsSet());
745 EXPECT_EQ(2u, service()->GetAllDeviceInfo().size());
746 EXPECT_EQ(2, change_count());
747
748 // Should clear out all local data and notify observers.
749 service()->DisableSync();
750 EXPECT_EQ(0u, service()->GetAllDeviceInfo().size());
751 EXPECT_EQ(3, change_count());
752
753 // Reloading from storage shouldn't contain remote data.
754 RestartService();
755 EXPECT_EQ(1u, service()->GetAllDeviceInfo().size());
756 EXPECT_EQ(4, change_count());
757 }
758
759 } // namespace
760
761 } // namespace syncer
OLDNEW
« no previous file with comments | « components/sync/device_info/device_info_service.cc ('k') | components/sync/device_info/device_info_sync_bridge.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698