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

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

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

Powered by Google App Engine
This is Rietveld 408576698