OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "sync/engine/directory_update_handler.h" | 5 #include "components/sync/engine_impl/directory_update_handler.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <set> | 10 #include <set> |
11 #include <string> | 11 #include <string> |
12 #include <utility> | 12 #include <utility> |
13 | 13 |
14 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
17 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
18 #include "sync/engine/syncer_proto_util.h" | 18 #include "components/sync/base/attachment_id_proto.h" |
19 #include "sync/internal_api/public/base/attachment_id_proto.h" | 19 #include "components/sync/base/model_type.h" |
20 #include "sync/internal_api/public/base/model_type.h" | 20 #include "components/sync/core/test/test_entry_factory.h" |
21 #include "sync/internal_api/public/test/test_entry_factory.h" | 21 #include "components/sync/engine_impl/syncer_proto_util.h" |
22 #include "sync/protocol/sync.pb.h" | 22 #include "components/sync/protocol/sync.pb.h" |
23 #include "sync/sessions/directory_type_debug_info_emitter.h" | 23 #include "components/sync/sessions_impl/directory_type_debug_info_emitter.h" |
24 #include "sync/sessions/status_controller.h" | 24 #include "components/sync/sessions_impl/status_controller.h" |
25 #include "sync/syncable/directory.h" | 25 #include "components/sync/syncable/directory.h" |
26 #include "sync/syncable/entry.h" | 26 #include "components/sync/syncable/entry.h" |
27 #include "sync/syncable/mutable_entry.h" | 27 #include "components/sync/syncable/mutable_entry.h" |
28 #include "sync/syncable/syncable_model_neutral_write_transaction.h" | 28 #include "components/sync/syncable/syncable_model_neutral_write_transaction.h" |
29 #include "sync/syncable/syncable_proto_util.h" | 29 #include "components/sync/syncable/syncable_proto_util.h" |
30 #include "sync/syncable/syncable_read_transaction.h" | 30 #include "components/sync/syncable/syncable_read_transaction.h" |
31 #include "sync/syncable/syncable_write_transaction.h" | 31 #include "components/sync/syncable/syncable_write_transaction.h" |
32 #include "sync/test/engine/fake_model_worker.h" | 32 #include "components/sync/test/engine/fake_model_worker.h" |
33 #include "sync/test/engine/test_directory_setter_upper.h" | 33 #include "components/sync/test/engine/test_directory_setter_upper.h" |
34 #include "sync/test/engine/test_id_factory.h" | 34 #include "components/sync/test/engine/test_id_factory.h" |
35 #include "sync/test/engine/test_syncable_utils.h" | 35 #include "components/sync/test/engine/test_syncable_utils.h" |
36 #include "testing/gtest/include/gtest/gtest.h" | 36 #include "testing/gtest/include/gtest/gtest.h" |
37 | 37 |
38 namespace syncer { | 38 namespace syncer { |
39 | 39 |
40 using syncable::Id; | 40 using syncable::Id; |
41 using syncable::UNITTEST; | 41 using syncable::UNITTEST; |
42 | 42 |
43 static const int64_t kDefaultVersion = 1000; | 43 static const int64_t kDefaultVersion = 1000; |
44 | 44 |
45 // A test harness for tests that focus on processing updates. | 45 // A test harness for tests that focus on processing updates. |
46 // | 46 // |
47 // Update processing is what occurs when we first download updates. It converts | 47 // Update processing is what occurs when we first download updates. It converts |
48 // the received protobuf message into information in the syncable::Directory. | 48 // the received protobuf message into information in the syncable::Directory. |
49 // Any invalid or redundant updates will be dropped at this point. | 49 // Any invalid or redundant updates will be dropped at this point. |
50 class DirectoryUpdateHandlerProcessUpdateTest : public ::testing::Test { | 50 class DirectoryUpdateHandlerProcessUpdateTest : public ::testing::Test { |
51 public: | 51 public: |
52 DirectoryUpdateHandlerProcessUpdateTest() | 52 DirectoryUpdateHandlerProcessUpdateTest() |
53 : ui_worker_(new FakeModelWorker(GROUP_UI)) { | 53 : ui_worker_(new FakeModelWorker(GROUP_UI)) {} |
54 } | |
55 | 54 |
56 ~DirectoryUpdateHandlerProcessUpdateTest() override {} | 55 ~DirectoryUpdateHandlerProcessUpdateTest() override {} |
57 | 56 |
58 void SetUp() override { dir_maker_.SetUp(); } | 57 void SetUp() override { dir_maker_.SetUp(); } |
59 | 58 |
60 void TearDown() override { dir_maker_.TearDown(); } | 59 void TearDown() override { dir_maker_.TearDown(); } |
61 | 60 |
62 syncable::Directory* dir() { | 61 syncable::Directory* dir() { return dir_maker_.directory(); } |
63 return dir_maker_.directory(); | |
64 } | |
65 | 62 |
66 protected: | 63 protected: |
67 std::unique_ptr<sync_pb::SyncEntity> CreateUpdate(const std::string& id, | 64 std::unique_ptr<sync_pb::SyncEntity> CreateUpdate(const std::string& id, |
68 const std::string& parent, | 65 const std::string& parent, |
69 const ModelType& type); | 66 const ModelType& type); |
70 | 67 |
71 // This exists mostly to give tests access to the protected member function. | 68 // This exists mostly to give tests access to the protected member function. |
72 // Warning: This takes the syncable directory lock. | 69 // Warning: This takes the syncable directory lock. |
73 void UpdateSyncEntities( | 70 void UpdateSyncEntities(DirectoryUpdateHandler* handler, |
74 DirectoryUpdateHandler* handler, | 71 const SyncEntityList& applicable_updates, |
75 const SyncEntityList& applicable_updates, | 72 sessions::StatusController* status); |
76 sessions::StatusController* status); | |
77 | 73 |
78 // Another function to access private member functions. | 74 // Another function to access private member functions. |
79 void UpdateProgressMarkers( | 75 void UpdateProgressMarkers(DirectoryUpdateHandler* handler, |
80 DirectoryUpdateHandler* handler, | 76 const sync_pb::DataTypeProgressMarker& progress); |
81 const sync_pb::DataTypeProgressMarker& progress); | |
82 | 77 |
83 scoped_refptr<FakeModelWorker> ui_worker() { | 78 scoped_refptr<FakeModelWorker> ui_worker() { return ui_worker_; } |
84 return ui_worker_; | |
85 } | |
86 | 79 |
87 bool EntryExists(const std::string& id) { | 80 bool EntryExists(const std::string& id) { |
88 syncable::ReadTransaction trans(FROM_HERE, dir()); | 81 syncable::ReadTransaction trans(FROM_HERE, dir()); |
89 syncable::Entry e(&trans, syncable::GET_BY_ID, | 82 syncable::Entry e(&trans, syncable::GET_BY_ID, Id::CreateFromServerId(id)); |
90 Id::CreateFromServerId(id)); | |
91 return e.good() && !e.GetIsDel(); | 83 return e.good() && !e.GetIsDel(); |
92 } | 84 } |
93 | 85 |
94 bool TypeRootExists(ModelType model_type) { | 86 bool TypeRootExists(ModelType model_type) { |
95 return dir()->InitialSyncEndedForType(model_type); | 87 return dir()->InitialSyncEndedForType(model_type); |
96 } | 88 } |
97 | 89 |
98 protected: | 90 protected: |
99 // Used in the construction of DirectoryTypeDebugInfoEmitters. | 91 // Used in the construction of DirectoryTypeDebugInfoEmitters. |
100 base::ObserverList<TypeDebugInfoObserver> type_observers_; | 92 base::ObserverList<TypeDebugInfoObserver> type_observers_; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 DirectoryUpdateHandler handler(dir(), BOOKMARKS, ui_worker(), &emitter); | 133 DirectoryUpdateHandler handler(dir(), BOOKMARKS, ui_worker(), &emitter); |
142 sync_pb::GetUpdatesResponse gu_response; | 134 sync_pb::GetUpdatesResponse gu_response; |
143 sessions::StatusController status; | 135 sessions::StatusController status; |
144 | 136 |
145 // Add a bookmark item to the update message. | 137 // Add a bookmark item to the update message. |
146 std::string root = Id::GetRoot().GetServerId(); | 138 std::string root = Id::GetRoot().GetServerId(); |
147 Id server_id = Id::CreateFromServerId("b1"); | 139 Id server_id = Id::CreateFromServerId("b1"); |
148 std::unique_ptr<sync_pb::SyncEntity> e = | 140 std::unique_ptr<sync_pb::SyncEntity> e = |
149 CreateUpdate(SyncableIdToProto(server_id), root, BOOKMARKS); | 141 CreateUpdate(SyncableIdToProto(server_id), root, BOOKMARKS); |
150 e->set_originator_cache_guid( | 142 e->set_originator_cache_guid( |
151 std::string(kCacheGuid, arraysize(kCacheGuid)-1)); | 143 std::string(kCacheGuid, arraysize(kCacheGuid) - 1)); |
152 Id client_id = Id::CreateFromClientString("-2"); | 144 Id client_id = Id::CreateFromClientString("-2"); |
153 e->set_originator_client_item_id(client_id.GetServerId()); | 145 e->set_originator_client_item_id(client_id.GetServerId()); |
154 e->set_position_in_parent(0); | 146 e->set_position_in_parent(0); |
155 | 147 |
156 // Add it to the applicable updates list. | 148 // Add it to the applicable updates list. |
157 SyncEntityList bookmark_updates; | 149 SyncEntityList bookmark_updates; |
158 bookmark_updates.push_back(e.get()); | 150 bookmark_updates.push_back(e.get()); |
159 | 151 |
160 // Process the update. | 152 // Process the update. |
161 UpdateSyncEntities(&handler, bookmark_updates, &status); | 153 UpdateSyncEntities(&handler, bookmark_updates, &status); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 | 246 |
255 sync_pb::DataTypeProgressMarker saved; | 247 sync_pb::DataTypeProgressMarker saved; |
256 dir()->GetDownloadProgress(BOOKMARKS, &saved); | 248 dir()->GetDownloadProgress(BOOKMARKS, &saved); |
257 | 249 |
258 EXPECT_EQ(progress.token(), saved.token()); | 250 EXPECT_EQ(progress.token(), saved.token()); |
259 EXPECT_EQ(progress.data_type_id(), saved.data_type_id()); | 251 EXPECT_EQ(progress.data_type_id(), saved.data_type_id()); |
260 } | 252 } |
261 | 253 |
262 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByVersion) { | 254 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByVersion) { |
263 DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_); | 255 DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_); |
264 DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, | 256 DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(), |
265 ui_worker(), &emitter); | 257 &emitter); |
266 sessions::StatusController status; | 258 sessions::StatusController status; |
267 | 259 |
268 sync_pb::DataTypeProgressMarker progress; | 260 sync_pb::DataTypeProgressMarker progress; |
269 progress.set_data_type_id( | 261 progress.set_data_type_id( |
270 GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); | 262 GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); |
271 progress.set_token("token"); | 263 progress.set_token("token"); |
272 progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 10); | 264 progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 10); |
273 | 265 |
274 sync_pb::DataTypeContext context; | 266 sync_pb::DataTypeContext context; |
275 context.set_data_type_id( | 267 context.set_data_type_id( |
276 GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); | 268 GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); |
277 context.set_context("context"); | 269 context.set_context("context"); |
278 context.set_version(1); | 270 context.set_version(1); |
279 | 271 |
280 std::unique_ptr<sync_pb::SyncEntity> e1 = | 272 std::unique_ptr<sync_pb::SyncEntity> e1 = |
281 CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "", | 273 CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "", |
282 SYNCED_NOTIFICATIONS); | 274 SYNCED_NOTIFICATIONS); |
283 | 275 |
284 std::unique_ptr<sync_pb::SyncEntity> e2 = | 276 std::unique_ptr<sync_pb::SyncEntity> e2 = |
285 CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "", | 277 CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "", |
286 SYNCED_NOTIFICATIONS); | 278 SYNCED_NOTIFICATIONS); |
287 e2->set_version(kDefaultVersion + 100); | 279 e2->set_version(kDefaultVersion + 100); |
288 | 280 |
289 // Add to the applicable updates list. | 281 // Add to the applicable updates list. |
290 SyncEntityList updates; | 282 SyncEntityList updates; |
291 updates.push_back(e1.get()); | 283 updates.push_back(e1.get()); |
292 updates.push_back(e2.get()); | 284 updates.push_back(e2.get()); |
293 | 285 |
294 // Process and apply updates. | 286 // Process and apply updates. |
295 EXPECT_EQ( | 287 EXPECT_EQ(SYNCER_OK, handler.ProcessGetUpdatesResponse(progress, context, |
296 SYNCER_OK, | 288 updates, &status)); |
297 handler.ProcessGetUpdatesResponse(progress, context, updates, &status)); | |
298 handler.ApplyUpdates(&status); | 289 handler.ApplyUpdates(&status); |
299 | 290 |
300 // Verify none is deleted because they are unapplied during GC. | 291 // Verify none is deleted because they are unapplied during GC. |
301 EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS)); | 292 EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS)); |
302 EXPECT_TRUE(EntryExists(e1->id_string())); | 293 EXPECT_TRUE(EntryExists(e1->id_string())); |
303 EXPECT_TRUE(EntryExists(e2->id_string())); | 294 EXPECT_TRUE(EntryExists(e2->id_string())); |
304 | 295 |
305 // Process and apply again. Old entry is deleted but not root. | 296 // Process and apply again. Old entry is deleted but not root. |
306 progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 20); | 297 progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 20); |
307 EXPECT_EQ(SYNCER_OK, | 298 EXPECT_EQ(SYNCER_OK, handler.ProcessGetUpdatesResponse( |
308 handler.ProcessGetUpdatesResponse( | 299 progress, context, SyncEntityList(), &status)); |
309 progress, context, SyncEntityList(), &status)); | |
310 handler.ApplyUpdates(&status); | 300 handler.ApplyUpdates(&status); |
311 EXPECT_FALSE(EntryExists(e1->id_string())); | 301 EXPECT_FALSE(EntryExists(e1->id_string())); |
312 EXPECT_TRUE(EntryExists(e2->id_string())); | 302 EXPECT_TRUE(EntryExists(e2->id_string())); |
313 } | 303 } |
314 | 304 |
315 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ContextVersion) { | 305 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ContextVersion) { |
316 DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_); | 306 DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_); |
317 DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, | 307 DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(), |
318 ui_worker(), &emitter); | 308 &emitter); |
319 sessions::StatusController status; | 309 sessions::StatusController status; |
320 int field_number = GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS); | 310 int field_number = GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS); |
321 | 311 |
322 sync_pb::DataTypeProgressMarker progress; | 312 sync_pb::DataTypeProgressMarker progress; |
323 progress.set_data_type_id( | 313 progress.set_data_type_id( |
324 GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); | 314 GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS)); |
325 progress.set_token("token"); | 315 progress.set_token("token"); |
326 | 316 |
327 sync_pb::DataTypeContext old_context; | 317 sync_pb::DataTypeContext old_context; |
328 old_context.set_version(1); | 318 old_context.set_version(1); |
329 old_context.set_context("data"); | 319 old_context.set_context("data"); |
330 old_context.set_data_type_id(field_number); | 320 old_context.set_data_type_id(field_number); |
331 | 321 |
332 std::unique_ptr<sync_pb::SyncEntity> e1 = | 322 std::unique_ptr<sync_pb::SyncEntity> e1 = |
333 CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "", | 323 CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "", |
334 SYNCED_NOTIFICATIONS); | 324 SYNCED_NOTIFICATIONS); |
335 | 325 |
336 SyncEntityList updates; | 326 SyncEntityList updates; |
337 updates.push_back(e1.get()); | 327 updates.push_back(e1.get()); |
338 | 328 |
339 // The first response should be processed fine. | 329 // The first response should be processed fine. |
340 EXPECT_EQ(SYNCER_OK, | 330 EXPECT_EQ(SYNCER_OK, handler.ProcessGetUpdatesResponse(progress, old_context, |
341 handler.ProcessGetUpdatesResponse( | 331 updates, &status)); |
342 progress, old_context, updates, &status)); | |
343 handler.ApplyUpdates(&status); | 332 handler.ApplyUpdates(&status); |
344 | 333 |
345 // The PREFERENCES root should be auto-created. | 334 // The PREFERENCES root should be auto-created. |
346 EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS)); | 335 EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS)); |
347 | 336 |
348 EXPECT_TRUE(EntryExists(e1->id_string())); | 337 EXPECT_TRUE(EntryExists(e1->id_string())); |
349 | 338 |
350 { | 339 { |
351 sync_pb::DataTypeContext dir_context; | 340 sync_pb::DataTypeContext dir_context; |
352 syncable::ReadTransaction trans(FROM_HERE, dir()); | 341 syncable::ReadTransaction trans(FROM_HERE, dir()); |
353 trans.directory()->GetDataTypeContext( | 342 trans.directory()->GetDataTypeContext(&trans, SYNCED_NOTIFICATIONS, |
354 &trans, SYNCED_NOTIFICATIONS, &dir_context); | 343 &dir_context); |
355 EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString()); | 344 EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString()); |
356 } | 345 } |
357 | 346 |
358 sync_pb::DataTypeContext new_context; | 347 sync_pb::DataTypeContext new_context; |
359 new_context.set_version(0); | 348 new_context.set_version(0); |
360 new_context.set_context("old"); | 349 new_context.set_context("old"); |
361 new_context.set_data_type_id(field_number); | 350 new_context.set_data_type_id(field_number); |
362 | 351 |
363 std::unique_ptr<sync_pb::SyncEntity> e2 = | 352 std::unique_ptr<sync_pb::SyncEntity> e2 = |
364 CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "", | 353 CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "", |
365 SYNCED_NOTIFICATIONS); | 354 SYNCED_NOTIFICATIONS); |
366 updates.clear(); | 355 updates.clear(); |
367 updates.push_back(e2.get()); | 356 updates.push_back(e2.get()); |
368 | 357 |
369 // The second response, with an old context version, should result in an | 358 // The second response, with an old context version, should result in an |
370 // error and the updates should be dropped. | 359 // error and the updates should be dropped. |
371 EXPECT_EQ(DATATYPE_TRIGGERED_RETRY, | 360 EXPECT_EQ(DATATYPE_TRIGGERED_RETRY, |
372 handler.ProcessGetUpdatesResponse( | 361 handler.ProcessGetUpdatesResponse(progress, new_context, updates, |
373 progress, new_context, updates, &status)); | 362 &status)); |
374 handler.ApplyUpdates(&status); | 363 handler.ApplyUpdates(&status); |
375 | 364 |
376 EXPECT_FALSE(EntryExists(e2->id_string())); | 365 EXPECT_FALSE(EntryExists(e2->id_string())); |
377 | 366 |
378 { | 367 { |
379 sync_pb::DataTypeContext dir_context; | 368 sync_pb::DataTypeContext dir_context; |
380 syncable::ReadTransaction trans(FROM_HERE, dir()); | 369 syncable::ReadTransaction trans(FROM_HERE, dir()); |
381 trans.directory()->GetDataTypeContext( | 370 trans.directory()->GetDataTypeContext(&trans, SYNCED_NOTIFICATIONS, |
382 &trans, SYNCED_NOTIFICATIONS, &dir_context); | 371 &dir_context); |
383 EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString()); | 372 EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString()); |
384 } | 373 } |
385 } | 374 } |
386 | 375 |
387 // See that updates containing attachment metadata are applied | 376 // See that updates containing attachment metadata are applied |
388 // (i.e. server_attachment_metadata is copied to attachment_metadata). | 377 // (i.e. server_attachment_metadata is copied to attachment_metadata). |
389 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, | 378 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, |
390 ProcessAndApplyUpdatesWithAttachments) { | 379 ProcessAndApplyUpdatesWithAttachments) { |
391 DirectoryTypeDebugInfoEmitter emitter(ARTICLES, &type_observers_); | 380 DirectoryTypeDebugInfoEmitter emitter(ARTICLES, &type_observers_); |
392 DirectoryUpdateHandler handler(dir(), ARTICLES, ui_worker(), &emitter); | 381 DirectoryUpdateHandler handler(dir(), ARTICLES, ui_worker(), &emitter); |
(...skipping 11 matching lines...) Expand all Loading... |
404 | 393 |
405 std::unique_ptr<sync_pb::SyncEntity> e1 = CreateUpdate( | 394 std::unique_ptr<sync_pb::SyncEntity> e1 = CreateUpdate( |
406 SyncableIdToProto(Id::CreateFromServerId("e1")), "", ARTICLES); | 395 SyncableIdToProto(Id::CreateFromServerId("e1")), "", ARTICLES); |
407 sync_pb::AttachmentIdProto* attachment_id = e1->add_attachment_id(); | 396 sync_pb::AttachmentIdProto* attachment_id = e1->add_attachment_id(); |
408 *attachment_id = CreateAttachmentIdProto(0, 0); | 397 *attachment_id = CreateAttachmentIdProto(0, 0); |
409 | 398 |
410 SyncEntityList updates; | 399 SyncEntityList updates; |
411 updates.push_back(e1.get()); | 400 updates.push_back(e1.get()); |
412 | 401 |
413 // Process and apply updates. | 402 // Process and apply updates. |
414 EXPECT_EQ( | 403 EXPECT_EQ(SYNCER_OK, handler.ProcessGetUpdatesResponse(progress, context, |
415 SYNCER_OK, | 404 updates, &status)); |
416 handler.ProcessGetUpdatesResponse(progress, context, updates, &status)); | |
417 handler.ApplyUpdates(&status); | 405 handler.ApplyUpdates(&status); |
418 | 406 |
419 ASSERT_TRUE(TypeRootExists(ARTICLES)); | 407 ASSERT_TRUE(TypeRootExists(ARTICLES)); |
420 ASSERT_TRUE(EntryExists(e1->id_string())); | 408 ASSERT_TRUE(EntryExists(e1->id_string())); |
421 { | 409 { |
422 syncable::ReadTransaction trans(FROM_HERE, dir()); | 410 syncable::ReadTransaction trans(FROM_HERE, dir()); |
423 syncable::Entry e(&trans, | 411 syncable::Entry e(&trans, syncable::GET_BY_ID, |
424 syncable::GET_BY_ID, | |
425 Id::CreateFromServerId(e1->id_string())); | 412 Id::CreateFromServerId(e1->id_string())); |
426 | 413 |
427 // See that the attachment_metadata is correct. | 414 // See that the attachment_metadata is correct. |
428 sync_pb::AttachmentMetadata attachment_metadata = e.GetAttachmentMetadata(); | 415 sync_pb::AttachmentMetadata attachment_metadata = e.GetAttachmentMetadata(); |
429 ASSERT_EQ(1, attachment_metadata.record_size()); | 416 ASSERT_EQ(1, attachment_metadata.record_size()); |
430 ASSERT_EQ(attachment_id->SerializeAsString(), | 417 ASSERT_EQ(attachment_id->SerializeAsString(), |
431 attachment_metadata.record(0).id().SerializeAsString()); | 418 attachment_metadata.record(0).id().SerializeAsString()); |
432 ASSERT_TRUE(attachment_metadata.record(0).is_on_server()); | 419 ASSERT_TRUE(attachment_metadata.record(0).is_on_server()); |
433 | 420 |
434 // See that attachment_metadata and server_attachment_metadata are equal. | 421 // See that attachment_metadata and server_attachment_metadata are equal. |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 } | 515 } |
529 | 516 |
530 void ApplyPasswordUpdates(sessions::StatusController* status) { | 517 void ApplyPasswordUpdates(sessions::StatusController* status) { |
531 update_handler_map_.find(PASSWORDS)->second->ApplyUpdates(status); | 518 update_handler_map_.find(PASSWORDS)->second->ApplyUpdates(status); |
532 } | 519 } |
533 | 520 |
534 void ApplyArticlesUpdates(sessions::StatusController* status) { | 521 void ApplyArticlesUpdates(sessions::StatusController* status) { |
535 update_handler_map_.find(ARTICLES)->second->ApplyUpdates(status); | 522 update_handler_map_.find(ARTICLES)->second->ApplyUpdates(status); |
536 } | 523 } |
537 | 524 |
538 TestEntryFactory* entry_factory() { | 525 TestEntryFactory* entry_factory() { return entry_factory_.get(); } |
539 return entry_factory_.get(); | |
540 } | |
541 | 526 |
542 syncable::Directory* directory() { | 527 syncable::Directory* directory() { return dir_maker_.directory(); } |
543 return dir_maker_.directory(); | |
544 } | |
545 | 528 |
546 private: | 529 private: |
547 base::MessageLoop loop_; // Needed to initialize the directory. | 530 base::MessageLoop loop_; // Needed to initialize the directory. |
548 TestDirectorySetterUpper dir_maker_; | 531 TestDirectorySetterUpper dir_maker_; |
549 std::unique_ptr<TestEntryFactory> entry_factory_; | 532 std::unique_ptr<TestEntryFactory> entry_factory_; |
550 | 533 |
551 scoped_refptr<FakeModelWorker> ui_worker_; | 534 scoped_refptr<FakeModelWorker> ui_worker_; |
552 scoped_refptr<FakeModelWorker> password_worker_; | 535 scoped_refptr<FakeModelWorker> password_worker_; |
553 scoped_refptr<FakeModelWorker> passive_worker_; | 536 scoped_refptr<FakeModelWorker> passive_worker_; |
554 | 537 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 ASSERT_TRUE(child.good()); | 583 ASSERT_TRUE(child.good()); |
601 | 584 |
602 EXPECT_FALSE(parent.GetIsUnsynced()); | 585 EXPECT_FALSE(parent.GetIsUnsynced()); |
603 EXPECT_FALSE(parent.GetIsUnappliedUpdate()); | 586 EXPECT_FALSE(parent.GetIsUnappliedUpdate()); |
604 EXPECT_FALSE(child.GetIsUnsynced()); | 587 EXPECT_FALSE(child.GetIsUnsynced()); |
605 EXPECT_FALSE(child.GetIsUnappliedUpdate()); | 588 EXPECT_FALSE(child.GetIsUnappliedUpdate()); |
606 } | 589 } |
607 } | 590 } |
608 | 591 |
609 // Test that the applicator can handle updates delivered out of order. | 592 // Test that the applicator can handle updates delivered out of order. |
610 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 593 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, BookmarkChildrenBeforeParent) { |
611 BookmarkChildrenBeforeParent) { | |
612 // Start with some bookmarks whose parents are unknown. | 594 // Start with some bookmarks whose parents are unknown. |
613 std::string root_server_id = Id::GetRoot().GetServerId(); | 595 std::string root_server_id = Id::GetRoot().GetServerId(); |
614 int64_t a_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( | 596 int64_t a_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( |
615 "a_child_created_first", DefaultBookmarkSpecifics(), "parent"); | 597 "a_child_created_first", DefaultBookmarkSpecifics(), "parent"); |
616 int64_t x_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( | 598 int64_t x_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( |
617 "x_child_created_first", DefaultBookmarkSpecifics(), "parent"); | 599 "x_child_created_first", DefaultBookmarkSpecifics(), "parent"); |
618 | 600 |
619 // Update application will fail. | 601 // Update application will fail. |
620 sessions::StatusController status1; | 602 sessions::StatusController status1; |
621 ApplyBookmarkUpdates(&status1); | 603 ApplyBookmarkUpdates(&status1); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); | 730 syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); |
749 ASSERT_TRUE(entry.good()); | 731 ASSERT_TRUE(entry.good()); |
750 | 732 |
751 // Re-parent from root to "Y" | 733 // Re-parent from root to "Y" |
752 entry.PutServerVersion(entry_factory()->GetNextRevision()); | 734 entry.PutServerVersion(entry_factory()->GetNextRevision()); |
753 entry.PutIsUnappliedUpdate(true); | 735 entry.PutIsUnappliedUpdate(true); |
754 entry.PutServerParentId(TestIdFactory::MakeServer("Y")); | 736 entry.PutServerParentId(TestIdFactory::MakeServer("Y")); |
755 } | 737 } |
756 | 738 |
757 // Item 'Y' is child of 'X'. | 739 // Item 'Y' is child of 'X'. |
758 entry_factory()->CreateUnsyncedItem( | 740 entry_factory()->CreateUnsyncedItem(TestIdFactory::MakeServer("Y"), |
759 TestIdFactory::MakeServer("Y"), TestIdFactory::MakeServer("X"), "Y", true, | 741 TestIdFactory::MakeServer("X"), "Y", true, |
760 BOOKMARKS, NULL); | 742 BOOKMARKS, NULL); |
761 | 743 |
762 // If the server's update were applied, we would have X be a child of Y, and Y | 744 // If the server's update were applied, we would have X be a child of Y, and Y |
763 // as a child of X. That's a directory loop. The UpdateApplicator should | 745 // as a child of X. That's a directory loop. The UpdateApplicator should |
764 // prevent the update from being applied and note that this is a hierarchy | 746 // prevent the update from being applied and note that this is a hierarchy |
765 // conflict. | 747 // conflict. |
766 | 748 |
767 sessions::StatusController status; | 749 sessions::StatusController status; |
768 ApplyBookmarkUpdates(&status); | 750 ApplyBookmarkUpdates(&status); |
769 | 751 |
770 // This should count as a hierarchy conflict. | 752 // This should count as a hierarchy conflict. |
771 const UpdateCounters& counters = GetBookmarksUpdateCounters(); | 753 const UpdateCounters& counters = GetBookmarksUpdateCounters(); |
772 EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); | 754 EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); |
773 | 755 |
774 { | 756 { |
775 syncable::ReadTransaction trans(FROM_HERE, directory()); | 757 syncable::ReadTransaction trans(FROM_HERE, directory()); |
776 syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); | 758 syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); |
777 ASSERT_TRUE(e.good()); | 759 ASSERT_TRUE(e.good()); |
778 EXPECT_TRUE(e.GetIsUnappliedUpdate()); | 760 EXPECT_TRUE(e.GetIsUnappliedUpdate()); |
779 EXPECT_FALSE(e.GetIsUnsynced()); | 761 EXPECT_FALSE(e.GetIsUnsynced()); |
780 } | 762 } |
781 } | 763 } |
782 | 764 |
783 // Test update application where the update has been orphaned by a local folder | 765 // Test update application where the update has been orphaned by a local folder |
784 // deletion. The update application attempt should fail. | 766 // deletion. The update application attempt should fail. |
785 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 767 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, HierarchyConflictDeletedParent) { |
786 HierarchyConflictDeletedParent) { | |
787 // Create a locally deleted parent item. | 768 // Create a locally deleted parent item. |
788 int64_t parent_handle; | 769 int64_t parent_handle; |
789 entry_factory()->CreateUnsyncedItem( | 770 entry_factory()->CreateUnsyncedItem(Id::CreateFromServerId("parent"), |
790 Id::CreateFromServerId("parent"), TestIdFactory::root(), | 771 TestIdFactory::root(), "parent", true, |
791 "parent", true, BOOKMARKS, &parent_handle); | 772 BOOKMARKS, &parent_handle); |
792 { | 773 { |
793 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 774 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
794 syncable::MutableEntry entry(&trans, | 775 syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, |
795 syncable::GET_BY_HANDLE, | |
796 parent_handle); | 776 parent_handle); |
797 entry.PutIsDel(true); | 777 entry.PutIsDel(true); |
798 } | 778 } |
799 | 779 |
800 // Create an incoming child from the server. | 780 // Create an incoming child from the server. |
801 int64_t child_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 781 int64_t child_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
802 "child", DefaultBookmarkSpecifics(), "parent"); | 782 "child", DefaultBookmarkSpecifics(), "parent"); |
803 | 783 |
804 // The server's update may seem valid to some other client, but on this client | 784 // The server's update may seem valid to some other client, but on this client |
805 // that new item's parent no longer exists. The update should not be applied | 785 // that new item's parent no longer exists. The update should not be applied |
(...skipping 15 matching lines...) Expand all Loading... |
821 | 801 |
822 // Attempt to apply an update that deletes a folder where the folder has | 802 // Attempt to apply an update that deletes a folder where the folder has |
823 // locally-created children. The update application should fail. | 803 // locally-created children. The update application should fail. |
824 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 804 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, |
825 HierarchyConflictDeleteNonEmptyDirectory) { | 805 HierarchyConflictDeleteNonEmptyDirectory) { |
826 // Create a server-deleted folder as a child of root node. | 806 // Create a server-deleted folder as a child of root node. |
827 int64_t parent_handle = | 807 int64_t parent_handle = |
828 entry_factory()->CreateSyncedItem("parent", BOOKMARKS, true); | 808 entry_factory()->CreateSyncedItem("parent", BOOKMARKS, true); |
829 { | 809 { |
830 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 810 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
831 syncable::MutableEntry entry(&trans, | 811 syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, |
832 syncable::GET_BY_HANDLE, | |
833 parent_handle); | 812 parent_handle); |
834 ASSERT_TRUE(entry.good()); | 813 ASSERT_TRUE(entry.good()); |
835 | 814 |
836 // Delete it on the server. | 815 // Delete it on the server. |
837 entry.PutServerVersion(entry_factory()->GetNextRevision()); | 816 entry.PutServerVersion(entry_factory()->GetNextRevision()); |
838 entry.PutIsUnappliedUpdate(true); | 817 entry.PutIsUnappliedUpdate(true); |
839 entry.PutServerParentId(TestIdFactory::root()); | 818 entry.PutServerParentId(TestIdFactory::root()); |
840 entry.PutServerIsDel(true); | 819 entry.PutServerIsDel(true); |
841 } | 820 } |
842 | 821 |
843 // Create a local child of the server-deleted directory. | 822 // Create a local child of the server-deleted directory. |
844 entry_factory()->CreateUnsyncedItem( | 823 entry_factory()->CreateUnsyncedItem(TestIdFactory::MakeServer("child"), |
845 TestIdFactory::MakeServer("child"), TestIdFactory::MakeServer("parent"), | 824 TestIdFactory::MakeServer("parent"), |
846 "child", false, BOOKMARKS, NULL); | 825 "child", false, BOOKMARKS, NULL); |
847 | 826 |
848 // The server's request to delete the directory must be ignored, otherwise our | 827 // The server's request to delete the directory must be ignored, otherwise our |
849 // unsynced new child would be orphaned. This is a hierarchy conflict. | 828 // unsynced new child would be orphaned. This is a hierarchy conflict. |
850 | 829 |
851 sessions::StatusController status; | 830 sessions::StatusController status; |
852 ApplyBookmarkUpdates(&status); | 831 ApplyBookmarkUpdates(&status); |
853 | 832 |
854 // This should count as a hierarchy conflict. | 833 // This should count as a hierarchy conflict. |
855 const UpdateCounters& counters = GetBookmarksUpdateCounters(); | 834 const UpdateCounters& counters = GetBookmarksUpdateCounters(); |
856 EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); | 835 EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); |
857 | 836 |
858 { | 837 { |
859 syncable::ReadTransaction trans(FROM_HERE, directory()); | 838 syncable::ReadTransaction trans(FROM_HERE, directory()); |
860 syncable::Entry parent(&trans, syncable::GET_BY_HANDLE, parent_handle); | 839 syncable::Entry parent(&trans, syncable::GET_BY_HANDLE, parent_handle); |
861 ASSERT_TRUE(parent.good()); | 840 ASSERT_TRUE(parent.good()); |
862 EXPECT_TRUE(parent.GetIsUnappliedUpdate()); | 841 EXPECT_TRUE(parent.GetIsUnappliedUpdate()); |
863 EXPECT_FALSE(parent.GetIsUnsynced()); | 842 EXPECT_FALSE(parent.GetIsUnsynced()); |
864 } | 843 } |
865 } | 844 } |
866 | 845 |
867 // Attempt to apply updates where the updated item's parent is not known to this | 846 // Attempt to apply updates where the updated item's parent is not known to this |
868 // client. The update application attempt should fail. | 847 // client. The update application attempt should fail. |
869 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 848 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, HierarchyConflictUnknownParent) { |
870 HierarchyConflictUnknownParent) { | |
871 // We shouldn't be able to do anything with either of these items. | 849 // We shouldn't be able to do anything with either of these items. |
872 int64_t x_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 850 int64_t x_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
873 "some_item", DefaultBookmarkSpecifics(), "unknown_parent"); | 851 "some_item", DefaultBookmarkSpecifics(), "unknown_parent"); |
874 int64_t y_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 852 int64_t y_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
875 "some_other_item", DefaultBookmarkSpecifics(), "some_item"); | 853 "some_other_item", DefaultBookmarkSpecifics(), "some_item"); |
876 | 854 |
877 sessions::StatusController status; | 855 sessions::StatusController status; |
878 ApplyBookmarkUpdates(&status); | 856 ApplyBookmarkUpdates(&status); |
879 | 857 |
880 const UpdateCounters& counters = GetBookmarksUpdateCounters(); | 858 const UpdateCounters& counters = GetBookmarksUpdateCounters(); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1044 sync_pb::PasswordSpecificsData data; | 1022 sync_pb::PasswordSpecificsData data; |
1045 data.set_origin("http://example.com/1"); | 1023 data.set_origin("http://example.com/1"); |
1046 { | 1024 { |
1047 syncable::ReadTransaction trans(FROM_HERE, directory()); | 1025 syncable::ReadTransaction trans(FROM_HERE, directory()); |
1048 cryptographer = directory()->GetCryptographer(&trans); | 1026 cryptographer = directory()->GetCryptographer(&trans); |
1049 | 1027 |
1050 KeyParams params = {"localhost", "dummy", "foobar"}; | 1028 KeyParams params = {"localhost", "dummy", "foobar"}; |
1051 cryptographer->AddKey(params); | 1029 cryptographer->AddKey(params); |
1052 | 1030 |
1053 cryptographer->Encrypt(data, | 1031 cryptographer->Encrypt(data, |
1054 specifics.mutable_password()->mutable_encrypted()); | 1032 specifics.mutable_password()->mutable_encrypted()); |
1055 } | 1033 } |
1056 decryptable_handle = | 1034 decryptable_handle = |
1057 entry_factory()->CreateUnappliedNewItem("item1", specifics, false); | 1035 entry_factory()->CreateUnappliedNewItem("item1", specifics, false); |
1058 } | 1036 } |
1059 { | 1037 { |
1060 // Create a new cryptographer, independent of the one in the session. | 1038 // Create a new cryptographer, independent of the one in the session. |
1061 Cryptographer other_cryptographer(cryptographer->encryptor()); | 1039 Cryptographer other_cryptographer(cryptographer->encryptor()); |
1062 KeyParams params = {"localhost", "dummy", "bazqux"}; | 1040 KeyParams params = {"localhost", "dummy", "bazqux"}; |
1063 other_cryptographer.AddKey(params); | 1041 other_cryptographer.AddKey(params); |
1064 | 1042 |
1065 sync_pb::EntitySpecifics specifics; | 1043 sync_pb::EntitySpecifics specifics; |
1066 sync_pb::PasswordSpecificsData data; | 1044 sync_pb::PasswordSpecificsData data; |
1067 data.set_origin("http://example.com/2"); | 1045 data.set_origin("http://example.com/2"); |
1068 | 1046 |
1069 other_cryptographer.Encrypt(data, | 1047 other_cryptographer.Encrypt( |
1070 specifics.mutable_password()->mutable_encrypted()); | 1048 data, specifics.mutable_password()->mutable_encrypted()); |
1071 undecryptable_handle = | 1049 undecryptable_handle = |
1072 entry_factory()->CreateUnappliedNewItem("item2", specifics, false); | 1050 entry_factory()->CreateUnappliedNewItem("item2", specifics, false); |
1073 } | 1051 } |
1074 | 1052 |
1075 sessions::StatusController status; | 1053 sessions::StatusController status; |
1076 ApplyPasswordUpdates(&status); | 1054 ApplyPasswordUpdates(&status); |
1077 | 1055 |
1078 const UpdateCounters& counters = GetPasswordsUpdateCounters(); | 1056 const UpdateCounters& counters = GetPasswordsUpdateCounters(); |
1079 EXPECT_EQ(1, counters.num_encryption_conflict_application_failures) | 1057 EXPECT_EQ(1, counters.num_encryption_conflict_application_failures) |
1080 << "The updates that can't be decrypted should be in encryption " | 1058 << "The updates that can't be decrypted should be in encryption " |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 const UpdateCounters& counters = GetArticlesUpdateCounters(); | 1156 const UpdateCounters& counters = GetArticlesUpdateCounters(); |
1179 EXPECT_EQ(1, counters.num_updates_applied); | 1157 EXPECT_EQ(1, counters.num_updates_applied); |
1180 EXPECT_EQ(1, counters.num_local_overwrites); | 1158 EXPECT_EQ(1, counters.num_local_overwrites); |
1181 EXPECT_EQ(0, counters.num_server_overwrites); | 1159 EXPECT_EQ(0, counters.num_server_overwrites); |
1182 local_metadata = entry_factory()->GetLocalAttachmentMetadataForItem(handle); | 1160 local_metadata = entry_factory()->GetLocalAttachmentMetadataForItem(handle); |
1183 EXPECT_EQ(server_metadata.SerializeAsString(), | 1161 EXPECT_EQ(server_metadata.SerializeAsString(), |
1184 local_metadata.SerializeAsString()); | 1162 local_metadata.SerializeAsString()); |
1185 } | 1163 } |
1186 | 1164 |
1187 } // namespace syncer | 1165 } // namespace syncer |
OLD | NEW |