| 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 "sync/engine/directory_update_handler.h" |
| 6 | 6 |
| 7 #include <stdint.h> |
| 8 |
| 7 #include <set> | 9 #include <set> |
| 8 #include <string> | 10 #include <string> |
| 9 #include <utility> | 11 #include <utility> |
| 10 | 12 |
| 11 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/macros.h" |
| 12 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 14 #include "sync/engine/syncer_proto_util.h" | 17 #include "sync/engine/syncer_proto_util.h" |
| 15 #include "sync/internal_api/public/base/attachment_id_proto.h" | 18 #include "sync/internal_api/public/base/attachment_id_proto.h" |
| 16 #include "sync/internal_api/public/base/model_type.h" | 19 #include "sync/internal_api/public/base/model_type.h" |
| 17 #include "sync/internal_api/public/test/test_entry_factory.h" | 20 #include "sync/internal_api/public/test/test_entry_factory.h" |
| 18 #include "sync/protocol/sync.pb.h" | 21 #include "sync/protocol/sync.pb.h" |
| 19 #include "sync/sessions/directory_type_debug_info_emitter.h" | 22 #include "sync/sessions/directory_type_debug_info_emitter.h" |
| 20 #include "sync/sessions/status_controller.h" | 23 #include "sync/sessions/status_controller.h" |
| 21 #include "sync/syncable/directory.h" | 24 #include "sync/syncable/directory.h" |
| 22 #include "sync/syncable/entry.h" | 25 #include "sync/syncable/entry.h" |
| 23 #include "sync/syncable/mutable_entry.h" | 26 #include "sync/syncable/mutable_entry.h" |
| 24 #include "sync/syncable/syncable_model_neutral_write_transaction.h" | 27 #include "sync/syncable/syncable_model_neutral_write_transaction.h" |
| 25 #include "sync/syncable/syncable_proto_util.h" | 28 #include "sync/syncable/syncable_proto_util.h" |
| 26 #include "sync/syncable/syncable_read_transaction.h" | 29 #include "sync/syncable/syncable_read_transaction.h" |
| 27 #include "sync/syncable/syncable_write_transaction.h" | 30 #include "sync/syncable/syncable_write_transaction.h" |
| 28 #include "sync/test/engine/fake_model_worker.h" | 31 #include "sync/test/engine/fake_model_worker.h" |
| 29 #include "sync/test/engine/test_directory_setter_upper.h" | 32 #include "sync/test/engine/test_directory_setter_upper.h" |
| 30 #include "sync/test/engine/test_id_factory.h" | 33 #include "sync/test/engine/test_id_factory.h" |
| 31 #include "sync/test/engine/test_syncable_utils.h" | 34 #include "sync/test/engine/test_syncable_utils.h" |
| 32 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
| 33 | 36 |
| 34 namespace syncer { | 37 namespace syncer { |
| 35 | 38 |
| 36 using syncable::Id; | 39 using syncable::Id; |
| 37 using syncable::UNITTEST; | 40 using syncable::UNITTEST; |
| 38 | 41 |
| 39 static const int64 kDefaultVersion = 1000; | 42 static const int64_t kDefaultVersion = 1000; |
| 40 | 43 |
| 41 // A test harness for tests that focus on processing updates. | 44 // A test harness for tests that focus on processing updates. |
| 42 // | 45 // |
| 43 // Update processing is what occurs when we first download updates. It converts | 46 // Update processing is what occurs when we first download updates. It converts |
| 44 // the received protobuf message into information in the syncable::Directory. | 47 // the received protobuf message into information in the syncable::Directory. |
| 45 // Any invalid or redundant updates will be dropped at this point. | 48 // Any invalid or redundant updates will be dropped at this point. |
| 46 class DirectoryUpdateHandlerProcessUpdateTest : public ::testing::Test { | 49 class DirectoryUpdateHandlerProcessUpdateTest : public ::testing::Test { |
| 47 public: | 50 public: |
| 48 DirectoryUpdateHandlerProcessUpdateTest() | 51 DirectoryUpdateHandlerProcessUpdateTest() |
| 49 : ui_worker_(new FakeModelWorker(GROUP_UI)) { | 52 : ui_worker_(new FakeModelWorker(GROUP_UI)) { |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 AddDefaultFieldValue(BOOKMARKS, &result); | 538 AddDefaultFieldValue(BOOKMARKS, &result); |
| 536 return result; | 539 return result; |
| 537 } | 540 } |
| 538 } // namespace | 541 } // namespace |
| 539 | 542 |
| 540 // Test update application for a few bookmark items. | 543 // Test update application for a few bookmark items. |
| 541 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SimpleBookmark) { | 544 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SimpleBookmark) { |
| 542 sessions::StatusController status; | 545 sessions::StatusController status; |
| 543 | 546 |
| 544 std::string root_server_id = Id::GetRoot().GetServerId(); | 547 std::string root_server_id = Id::GetRoot().GetServerId(); |
| 545 int64 parent_handle = | 548 int64_t parent_handle = |
| 546 entry_factory()->CreateUnappliedNewBookmarkItemWithParent( | 549 entry_factory()->CreateUnappliedNewBookmarkItemWithParent( |
| 547 "parent", DefaultBookmarkSpecifics(), root_server_id); | 550 "parent", DefaultBookmarkSpecifics(), root_server_id); |
| 548 int64 child_handle = | 551 int64_t child_handle = |
| 549 entry_factory()->CreateUnappliedNewBookmarkItemWithParent( | 552 entry_factory()->CreateUnappliedNewBookmarkItemWithParent( |
| 550 "child", DefaultBookmarkSpecifics(), "parent"); | 553 "child", DefaultBookmarkSpecifics(), "parent"); |
| 551 | 554 |
| 552 ApplyBookmarkUpdates(&status); | 555 ApplyBookmarkUpdates(&status); |
| 553 | 556 |
| 554 const UpdateCounters& counter = GetBookmarksUpdateCounters(); | 557 const UpdateCounters& counter = GetBookmarksUpdateCounters(); |
| 555 EXPECT_EQ(0, counter.num_encryption_conflict_application_failures) | 558 EXPECT_EQ(0, counter.num_encryption_conflict_application_failures) |
| 556 << "Simple update shouldn't result in conflicts"; | 559 << "Simple update shouldn't result in conflicts"; |
| 557 EXPECT_EQ(0, counter.num_hierarchy_conflict_application_failures) | 560 EXPECT_EQ(0, counter.num_hierarchy_conflict_application_failures) |
| 558 << "Simple update shouldn't result in conflicts"; | 561 << "Simple update shouldn't result in conflicts"; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 573 EXPECT_FALSE(child.GetIsUnsynced()); | 576 EXPECT_FALSE(child.GetIsUnsynced()); |
| 574 EXPECT_FALSE(child.GetIsUnappliedUpdate()); | 577 EXPECT_FALSE(child.GetIsUnappliedUpdate()); |
| 575 } | 578 } |
| 576 } | 579 } |
| 577 | 580 |
| 578 // Test that the applicator can handle updates delivered out of order. | 581 // Test that the applicator can handle updates delivered out of order. |
| 579 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 582 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, |
| 580 BookmarkChildrenBeforeParent) { | 583 BookmarkChildrenBeforeParent) { |
| 581 // Start with some bookmarks whose parents are unknown. | 584 // Start with some bookmarks whose parents are unknown. |
| 582 std::string root_server_id = Id::GetRoot().GetServerId(); | 585 std::string root_server_id = Id::GetRoot().GetServerId(); |
| 583 int64 a_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( | 586 int64_t a_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( |
| 584 "a_child_created_first", DefaultBookmarkSpecifics(), "parent"); | 587 "a_child_created_first", DefaultBookmarkSpecifics(), "parent"); |
| 585 int64 x_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( | 588 int64_t x_handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( |
| 586 "x_child_created_first", DefaultBookmarkSpecifics(), "parent"); | 589 "x_child_created_first", DefaultBookmarkSpecifics(), "parent"); |
| 587 | 590 |
| 588 // Update application will fail. | 591 // Update application will fail. |
| 589 sessions::StatusController status1; | 592 sessions::StatusController status1; |
| 590 ApplyBookmarkUpdates(&status1); | 593 ApplyBookmarkUpdates(&status1); |
| 591 EXPECT_EQ(0, status1.num_updates_applied()); | 594 EXPECT_EQ(0, status1.num_updates_applied()); |
| 592 EXPECT_EQ(2, status1.num_hierarchy_conflicts()); | 595 EXPECT_EQ(2, status1.num_hierarchy_conflicts()); |
| 593 | 596 |
| 594 { | 597 { |
| 595 syncable::ReadTransaction trans(FROM_HERE, directory()); | 598 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 ASSERT_TRUE(x.good()); | 631 ASSERT_TRUE(x.good()); |
| 629 | 632 |
| 630 EXPECT_FALSE(a.GetIsUnappliedUpdate()); | 633 EXPECT_FALSE(a.GetIsUnappliedUpdate()); |
| 631 EXPECT_FALSE(x.GetIsUnappliedUpdate()); | 634 EXPECT_FALSE(x.GetIsUnappliedUpdate()); |
| 632 } | 635 } |
| 633 } | 636 } |
| 634 | 637 |
| 635 // Try to apply changes on an item that is both IS_UNSYNCED and | 638 // Try to apply changes on an item that is both IS_UNSYNCED and |
| 636 // IS_UNAPPLIED_UPDATE. Conflict resolution should be performed. | 639 // IS_UNAPPLIED_UPDATE. Conflict resolution should be performed. |
| 637 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SimpleBookmarkConflict) { | 640 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SimpleBookmarkConflict) { |
| 638 int64 handle = entry_factory()->CreateUnappliedAndUnsyncedBookmarkItem("x"); | 641 int64_t handle = entry_factory()->CreateUnappliedAndUnsyncedBookmarkItem("x"); |
| 639 | 642 |
| 640 int original_server_version = -10; | 643 int original_server_version = -10; |
| 641 { | 644 { |
| 642 syncable::ReadTransaction trans(FROM_HERE, directory()); | 645 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 643 syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); | 646 syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); |
| 644 original_server_version = e.GetServerVersion(); | 647 original_server_version = e.GetServerVersion(); |
| 645 ASSERT_NE(original_server_version, e.GetBaseVersion()); | 648 ASSERT_NE(original_server_version, e.GetBaseVersion()); |
| 646 EXPECT_TRUE(e.GetIsUnsynced()); | 649 EXPECT_TRUE(e.GetIsUnsynced()); |
| 647 } | 650 } |
| 648 | 651 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 667 EXPECT_TRUE(e.GetIsUnsynced()); | 670 EXPECT_TRUE(e.GetIsUnsynced()); |
| 668 } | 671 } |
| 669 } | 672 } |
| 670 | 673 |
| 671 // Create a simple conflict that is also a hierarchy conflict. If we were to | 674 // Create a simple conflict that is also a hierarchy conflict. If we were to |
| 672 // follow the normal "server wins" logic, we'd end up violating hierarchy | 675 // follow the normal "server wins" logic, we'd end up violating hierarchy |
| 673 // constraints. The hierarchy conflict must take precedence. We can not allow | 676 // constraints. The hierarchy conflict must take precedence. We can not allow |
| 674 // the update to be applied. The item must remain in the conflict state. | 677 // the update to be applied. The item must remain in the conflict state. |
| 675 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, HierarchyAndSimpleConflict) { | 678 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, HierarchyAndSimpleConflict) { |
| 676 // Create a simply-conflicting item. It will start with valid parent ids. | 679 // Create a simply-conflicting item. It will start with valid parent ids. |
| 677 int64 handle = entry_factory()->CreateUnappliedAndUnsyncedBookmarkItem( | 680 int64_t handle = entry_factory()->CreateUnappliedAndUnsyncedBookmarkItem( |
| 678 "orphaned_by_server"); | 681 "orphaned_by_server"); |
| 679 { | 682 { |
| 680 // Manually set the SERVER_PARENT_ID to bad value. | 683 // Manually set the SERVER_PARENT_ID to bad value. |
| 681 // A bad parent indicates a hierarchy conflict. | 684 // A bad parent indicates a hierarchy conflict. |
| 682 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 685 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 683 syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); | 686 syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); |
| 684 ASSERT_TRUE(entry.good()); | 687 ASSERT_TRUE(entry.good()); |
| 685 | 688 |
| 686 entry.PutServerParentId(TestIdFactory::MakeServer("bogus_parent")); | 689 entry.PutServerParentId(TestIdFactory::MakeServer("bogus_parent")); |
| 687 } | 690 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 703 } | 706 } |
| 704 } | 707 } |
| 705 | 708 |
| 706 // Attempt to apply an udpate that would create a bookmark folder loop. This | 709 // Attempt to apply an udpate that would create a bookmark folder loop. This |
| 707 // application should fail. | 710 // application should fail. |
| 708 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, BookmarkFolderLoop) { | 711 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, BookmarkFolderLoop) { |
| 709 // Item 'X' locally has parent of 'root'. Server is updating it to have | 712 // Item 'X' locally has parent of 'root'. Server is updating it to have |
| 710 // parent of 'Y'. | 713 // parent of 'Y'. |
| 711 | 714 |
| 712 // Create it as a child of root node. | 715 // Create it as a child of root node. |
| 713 int64 handle = entry_factory()->CreateSyncedItem("X", BOOKMARKS, true); | 716 int64_t handle = entry_factory()->CreateSyncedItem("X", BOOKMARKS, true); |
| 714 | 717 |
| 715 { | 718 { |
| 716 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 719 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 717 syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); | 720 syncable::MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); |
| 718 ASSERT_TRUE(entry.good()); | 721 ASSERT_TRUE(entry.good()); |
| 719 | 722 |
| 720 // Re-parent from root to "Y" | 723 // Re-parent from root to "Y" |
| 721 entry.PutServerVersion(entry_factory()->GetNextRevision()); | 724 entry.PutServerVersion(entry_factory()->GetNextRevision()); |
| 722 entry.PutIsUnappliedUpdate(true); | 725 entry.PutIsUnappliedUpdate(true); |
| 723 entry.PutServerParentId(TestIdFactory::MakeServer("Y")); | 726 entry.PutServerParentId(TestIdFactory::MakeServer("Y")); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 747 EXPECT_TRUE(e.GetIsUnappliedUpdate()); | 750 EXPECT_TRUE(e.GetIsUnappliedUpdate()); |
| 748 EXPECT_FALSE(e.GetIsUnsynced()); | 751 EXPECT_FALSE(e.GetIsUnsynced()); |
| 749 } | 752 } |
| 750 } | 753 } |
| 751 | 754 |
| 752 // Test update application where the update has been orphaned by a local folder | 755 // Test update application where the update has been orphaned by a local folder |
| 753 // deletion. The update application attempt should fail. | 756 // deletion. The update application attempt should fail. |
| 754 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 757 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, |
| 755 HierarchyConflictDeletedParent) { | 758 HierarchyConflictDeletedParent) { |
| 756 // Create a locally deleted parent item. | 759 // Create a locally deleted parent item. |
| 757 int64 parent_handle; | 760 int64_t parent_handle; |
| 758 entry_factory()->CreateUnsyncedItem( | 761 entry_factory()->CreateUnsyncedItem( |
| 759 Id::CreateFromServerId("parent"), TestIdFactory::root(), | 762 Id::CreateFromServerId("parent"), TestIdFactory::root(), |
| 760 "parent", true, BOOKMARKS, &parent_handle); | 763 "parent", true, BOOKMARKS, &parent_handle); |
| 761 { | 764 { |
| 762 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 765 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 763 syncable::MutableEntry entry(&trans, | 766 syncable::MutableEntry entry(&trans, |
| 764 syncable::GET_BY_HANDLE, | 767 syncable::GET_BY_HANDLE, |
| 765 parent_handle); | 768 parent_handle); |
| 766 entry.PutIsDel(true); | 769 entry.PutIsDel(true); |
| 767 } | 770 } |
| 768 | 771 |
| 769 // Create an incoming child from the server. | 772 // Create an incoming child from the server. |
| 770 int64 child_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 773 int64_t child_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 771 "child", DefaultBookmarkSpecifics(), "parent"); | 774 "child", DefaultBookmarkSpecifics(), "parent"); |
| 772 | 775 |
| 773 // The server's update may seem valid to some other client, but on this client | 776 // The server's update may seem valid to some other client, but on this client |
| 774 // that new item's parent no longer exists. The update should not be applied | 777 // that new item's parent no longer exists. The update should not be applied |
| 775 // and the update applicator should indicate this is a hierarchy conflict. | 778 // and the update applicator should indicate this is a hierarchy conflict. |
| 776 | 779 |
| 777 sessions::StatusController status; | 780 sessions::StatusController status; |
| 778 ApplyBookmarkUpdates(&status); | 781 ApplyBookmarkUpdates(&status); |
| 779 const UpdateCounters& counters = GetBookmarksUpdateCounters(); | 782 const UpdateCounters& counters = GetBookmarksUpdateCounters(); |
| 780 EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); | 783 EXPECT_EQ(1, counters.num_hierarchy_conflict_application_failures); |
| 781 | 784 |
| 782 { | 785 { |
| 783 syncable::ReadTransaction trans(FROM_HERE, directory()); | 786 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 784 syncable::Entry child(&trans, syncable::GET_BY_HANDLE, child_handle); | 787 syncable::Entry child(&trans, syncable::GET_BY_HANDLE, child_handle); |
| 785 ASSERT_TRUE(child.good()); | 788 ASSERT_TRUE(child.good()); |
| 786 EXPECT_TRUE(child.GetIsUnappliedUpdate()); | 789 EXPECT_TRUE(child.GetIsUnappliedUpdate()); |
| 787 EXPECT_FALSE(child.GetIsUnsynced()); | 790 EXPECT_FALSE(child.GetIsUnsynced()); |
| 788 } | 791 } |
| 789 } | 792 } |
| 790 | 793 |
| 791 // Attempt to apply an update that deletes a folder where the folder has | 794 // Attempt to apply an update that deletes a folder where the folder has |
| 792 // locally-created children. The update application should fail. | 795 // locally-created children. The update application should fail. |
| 793 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 796 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, |
| 794 HierarchyConflictDeleteNonEmptyDirectory) { | 797 HierarchyConflictDeleteNonEmptyDirectory) { |
| 795 // Create a server-deleted folder as a child of root node. | 798 // Create a server-deleted folder as a child of root node. |
| 796 int64 parent_handle = | 799 int64_t parent_handle = |
| 797 entry_factory()->CreateSyncedItem("parent", BOOKMARKS, true); | 800 entry_factory()->CreateSyncedItem("parent", BOOKMARKS, true); |
| 798 { | 801 { |
| 799 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); | 802 syncable::WriteTransaction trans(FROM_HERE, UNITTEST, directory()); |
| 800 syncable::MutableEntry entry(&trans, | 803 syncable::MutableEntry entry(&trans, |
| 801 syncable::GET_BY_HANDLE, | 804 syncable::GET_BY_HANDLE, |
| 802 parent_handle); | 805 parent_handle); |
| 803 ASSERT_TRUE(entry.good()); | 806 ASSERT_TRUE(entry.good()); |
| 804 | 807 |
| 805 // Delete it on the server. | 808 // Delete it on the server. |
| 806 entry.PutServerVersion(entry_factory()->GetNextRevision()); | 809 entry.PutServerVersion(entry_factory()->GetNextRevision()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 831 EXPECT_TRUE(parent.GetIsUnappliedUpdate()); | 834 EXPECT_TRUE(parent.GetIsUnappliedUpdate()); |
| 832 EXPECT_FALSE(parent.GetIsUnsynced()); | 835 EXPECT_FALSE(parent.GetIsUnsynced()); |
| 833 } | 836 } |
| 834 } | 837 } |
| 835 | 838 |
| 836 // Attempt to apply updates where the updated item's parent is not known to this | 839 // Attempt to apply updates where the updated item's parent is not known to this |
| 837 // client. The update application attempt should fail. | 840 // client. The update application attempt should fail. |
| 838 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 841 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, |
| 839 HierarchyConflictUnknownParent) { | 842 HierarchyConflictUnknownParent) { |
| 840 // We shouldn't be able to do anything with either of these items. | 843 // We shouldn't be able to do anything with either of these items. |
| 841 int64 x_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 844 int64_t x_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 842 "some_item", DefaultBookmarkSpecifics(), "unknown_parent"); | 845 "some_item", DefaultBookmarkSpecifics(), "unknown_parent"); |
| 843 int64 y_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 846 int64_t y_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 844 "some_other_item", DefaultBookmarkSpecifics(), "some_item"); | 847 "some_other_item", DefaultBookmarkSpecifics(), "some_item"); |
| 845 | 848 |
| 846 sessions::StatusController status; | 849 sessions::StatusController status; |
| 847 ApplyBookmarkUpdates(&status); | 850 ApplyBookmarkUpdates(&status); |
| 848 | 851 |
| 849 const UpdateCounters& counters = GetBookmarksUpdateCounters(); | 852 const UpdateCounters& counters = GetBookmarksUpdateCounters(); |
| 850 EXPECT_EQ(2, counters.num_hierarchy_conflict_application_failures) | 853 EXPECT_EQ(2, counters.num_hierarchy_conflict_application_failures) |
| 851 << "All updates with an unknown ancestors should be in conflict"; | 854 << "All updates with an unknown ancestors should be in conflict"; |
| 852 EXPECT_EQ(0, counters.num_updates_applied) | 855 EXPECT_EQ(0, counters.num_updates_applied) |
| 853 << "No item with an unknown ancestor should be applied"; | 856 << "No item with an unknown ancestor should be applied"; |
| 854 | 857 |
| 855 { | 858 { |
| 856 syncable::ReadTransaction trans(FROM_HERE, directory()); | 859 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 857 syncable::Entry x(&trans, syncable::GET_BY_HANDLE, x_handle); | 860 syncable::Entry x(&trans, syncable::GET_BY_HANDLE, x_handle); |
| 858 syncable::Entry y(&trans, syncable::GET_BY_HANDLE, y_handle); | 861 syncable::Entry y(&trans, syncable::GET_BY_HANDLE, y_handle); |
| 859 ASSERT_TRUE(x.good()); | 862 ASSERT_TRUE(x.good()); |
| 860 ASSERT_TRUE(y.good()); | 863 ASSERT_TRUE(y.good()); |
| 861 EXPECT_TRUE(x.GetIsUnappliedUpdate()); | 864 EXPECT_TRUE(x.GetIsUnappliedUpdate()); |
| 862 EXPECT_TRUE(y.GetIsUnappliedUpdate()); | 865 EXPECT_TRUE(y.GetIsUnappliedUpdate()); |
| 863 EXPECT_FALSE(x.GetIsUnsynced()); | 866 EXPECT_FALSE(x.GetIsUnsynced()); |
| 864 EXPECT_FALSE(y.GetIsUnsynced()); | 867 EXPECT_FALSE(y.GetIsUnsynced()); |
| 865 } | 868 } |
| 866 } | 869 } |
| 867 | 870 |
| 868 // Attempt application of a mix of items. Some update application attempts will | 871 // Attempt application of a mix of items. Some update application attempts will |
| 869 // fail due to hierarchy conflicts. Others should succeed. | 872 // fail due to hierarchy conflicts. Others should succeed. |
| 870 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, ItemsBothKnownAndUnknown) { | 873 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, ItemsBothKnownAndUnknown) { |
| 871 // See what happens when there's a mixture of good and bad updates. | 874 // See what happens when there's a mixture of good and bad updates. |
| 872 std::string root_server_id = Id::GetRoot().GetServerId(); | 875 std::string root_server_id = Id::GetRoot().GetServerId(); |
| 873 int64 u1_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 876 int64_t u1_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 874 "first_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); | 877 "first_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); |
| 875 int64 k1_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 878 int64_t k1_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 876 "first_known_item", DefaultBookmarkSpecifics(), root_server_id); | 879 "first_known_item", DefaultBookmarkSpecifics(), root_server_id); |
| 877 int64 u2_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 880 int64_t u2_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 878 "second_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); | 881 "second_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); |
| 879 int64 k2_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 882 int64_t k2_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 880 "second_known_item", DefaultBookmarkSpecifics(), "first_known_item"); | 883 "second_known_item", DefaultBookmarkSpecifics(), "first_known_item"); |
| 881 int64 k3_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 884 int64_t k3_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 882 "third_known_item", DefaultBookmarkSpecifics(), "fourth_known_item"); | 885 "third_known_item", DefaultBookmarkSpecifics(), "fourth_known_item"); |
| 883 int64 k4_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 886 int64_t k4_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 884 "fourth_known_item", DefaultBookmarkSpecifics(), root_server_id); | 887 "fourth_known_item", DefaultBookmarkSpecifics(), root_server_id); |
| 885 | 888 |
| 886 sessions::StatusController status; | 889 sessions::StatusController status; |
| 887 ApplyBookmarkUpdates(&status); | 890 ApplyBookmarkUpdates(&status); |
| 888 | 891 |
| 889 const UpdateCounters& counters = GetBookmarksUpdateCounters(); | 892 const UpdateCounters& counters = GetBookmarksUpdateCounters(); |
| 890 EXPECT_EQ(2, counters.num_hierarchy_conflict_application_failures) | 893 EXPECT_EQ(2, counters.num_hierarchy_conflict_application_failures) |
| 891 << "The updates with unknown ancestors should be in conflict"; | 894 << "The updates with unknown ancestors should be in conflict"; |
| 892 EXPECT_EQ(4, counters.num_updates_applied) | 895 EXPECT_EQ(4, counters.num_updates_applied) |
| 893 << "The updates with known ancestors should be successfully applied"; | 896 << "The updates with known ancestors should be successfully applied"; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 | 931 |
| 929 KeyParams params = {"localhost", "dummy", "foobar"}; | 932 KeyParams params = {"localhost", "dummy", "foobar"}; |
| 930 cryptographer->AddKey(params); | 933 cryptographer->AddKey(params); |
| 931 | 934 |
| 932 sync_pb::EntitySpecifics specifics; | 935 sync_pb::EntitySpecifics specifics; |
| 933 sync_pb::PasswordSpecificsData data; | 936 sync_pb::PasswordSpecificsData data; |
| 934 data.set_origin("http://example.com"); | 937 data.set_origin("http://example.com"); |
| 935 | 938 |
| 936 cryptographer->Encrypt(data, | 939 cryptographer->Encrypt(data, |
| 937 specifics.mutable_password()->mutable_encrypted()); | 940 specifics.mutable_password()->mutable_encrypted()); |
| 938 int64 handle = | 941 int64_t handle = |
| 939 entry_factory()->CreateUnappliedNewItem("item", specifics, false); | 942 entry_factory()->CreateUnappliedNewItem("item", specifics, false); |
| 940 | 943 |
| 941 sessions::StatusController status; | 944 sessions::StatusController status; |
| 942 ApplyPasswordUpdates(&status); | 945 ApplyPasswordUpdates(&status); |
| 943 | 946 |
| 944 const UpdateCounters& counters = GetPasswordsUpdateCounters(); | 947 const UpdateCounters& counters = GetPasswordsUpdateCounters(); |
| 945 EXPECT_EQ(1, counters.num_updates_applied) | 948 EXPECT_EQ(1, counters.num_updates_applied) |
| 946 << "The updates that can be decrypted should be applied"; | 949 << "The updates that can be decrypted should be applied"; |
| 947 | 950 |
| 948 { | 951 { |
| 949 syncable::ReadTransaction trans(FROM_HERE, directory()); | 952 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 950 syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); | 953 syncable::Entry e(&trans, syncable::GET_BY_HANDLE, handle); |
| 951 ASSERT_TRUE(e.good()); | 954 ASSERT_TRUE(e.good()); |
| 952 EXPECT_FALSE(e.GetIsUnappliedUpdate()); | 955 EXPECT_FALSE(e.GetIsUnappliedUpdate()); |
| 953 EXPECT_FALSE(e.GetIsUnsynced()); | 956 EXPECT_FALSE(e.GetIsUnsynced()); |
| 954 } | 957 } |
| 955 } | 958 } |
| 956 | 959 |
| 957 // Attempt application of encrypted items when the passphrase is not known. | 960 // Attempt application of encrypted items when the passphrase is not known. |
| 958 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, UndecryptableData) { | 961 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, UndecryptableData) { |
| 959 // Undecryptable updates should not be applied. | 962 // Undecryptable updates should not be applied. |
| 960 sync_pb::EntitySpecifics encrypted_bookmark; | 963 sync_pb::EntitySpecifics encrypted_bookmark; |
| 961 encrypted_bookmark.mutable_encrypted(); | 964 encrypted_bookmark.mutable_encrypted(); |
| 962 AddDefaultFieldValue(BOOKMARKS, &encrypted_bookmark); | 965 AddDefaultFieldValue(BOOKMARKS, &encrypted_bookmark); |
| 963 std::string root_server_id = Id::GetRoot().GetServerId(); | 966 std::string root_server_id = Id::GetRoot().GetServerId(); |
| 964 int64 folder_handle = entry_factory()->CreateUnappliedNewItemWithParent( | 967 int64_t folder_handle = entry_factory()->CreateUnappliedNewItemWithParent( |
| 965 "folder", | 968 "folder", encrypted_bookmark, root_server_id); |
| 966 encrypted_bookmark, | 969 int64_t bookmark_handle = entry_factory()->CreateUnappliedNewItem( |
| 967 root_server_id); | 970 "item2", encrypted_bookmark, false); |
| 968 int64 bookmark_handle = entry_factory()->CreateUnappliedNewItem( | |
| 969 "item2", | |
| 970 encrypted_bookmark, | |
| 971 false); | |
| 972 sync_pb::EntitySpecifics encrypted_password; | 971 sync_pb::EntitySpecifics encrypted_password; |
| 973 encrypted_password.mutable_password(); | 972 encrypted_password.mutable_password(); |
| 974 int64 password_handle = entry_factory()->CreateUnappliedNewItem( | 973 int64_t password_handle = entry_factory()->CreateUnappliedNewItem( |
| 975 "item3", | 974 "item3", encrypted_password, false); |
| 976 encrypted_password, | |
| 977 false); | |
| 978 | 975 |
| 979 sessions::StatusController status; | 976 sessions::StatusController status; |
| 980 ApplyBookmarkUpdates(&status); | 977 ApplyBookmarkUpdates(&status); |
| 981 ApplyPasswordUpdates(&status); | 978 ApplyPasswordUpdates(&status); |
| 982 | 979 |
| 983 const UpdateCounters& bm_counters = GetBookmarksUpdateCounters(); | 980 const UpdateCounters& bm_counters = GetBookmarksUpdateCounters(); |
| 984 EXPECT_EQ(2, bm_counters.num_encryption_conflict_application_failures) | 981 EXPECT_EQ(2, bm_counters.num_encryption_conflict_application_failures) |
| 985 << "Updates that can't be decrypted should be in encryption conflict"; | 982 << "Updates that can't be decrypted should be in encryption conflict"; |
| 986 EXPECT_EQ(0, bm_counters.num_updates_applied) | 983 EXPECT_EQ(0, bm_counters.num_updates_applied) |
| 987 << "No update that can't be decrypted should be applied"; | 984 << "No update that can't be decrypted should be applied"; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1003 EXPECT_TRUE(folder.GetIsUnappliedUpdate()); | 1000 EXPECT_TRUE(folder.GetIsUnappliedUpdate()); |
| 1004 EXPECT_TRUE(bm.GetIsUnappliedUpdate()); | 1001 EXPECT_TRUE(bm.GetIsUnappliedUpdate()); |
| 1005 EXPECT_TRUE(pw.GetIsUnappliedUpdate()); | 1002 EXPECT_TRUE(pw.GetIsUnappliedUpdate()); |
| 1006 } | 1003 } |
| 1007 } | 1004 } |
| 1008 | 1005 |
| 1009 // Test a mix of decryptable and undecryptable updates. | 1006 // Test a mix of decryptable and undecryptable updates. |
| 1010 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SomeUndecryptablePassword) { | 1007 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, SomeUndecryptablePassword) { |
| 1011 Cryptographer* cryptographer; | 1008 Cryptographer* cryptographer; |
| 1012 | 1009 |
| 1013 int64 decryptable_handle = -1; | 1010 int64_t decryptable_handle = -1; |
| 1014 int64 undecryptable_handle = -1; | 1011 int64_t undecryptable_handle = -1; |
| 1015 | 1012 |
| 1016 // Only decryptable password updates should be applied. | 1013 // Only decryptable password updates should be applied. |
| 1017 { | 1014 { |
| 1018 sync_pb::EntitySpecifics specifics; | 1015 sync_pb::EntitySpecifics specifics; |
| 1019 sync_pb::PasswordSpecificsData data; | 1016 sync_pb::PasswordSpecificsData data; |
| 1020 data.set_origin("http://example.com/1"); | 1017 data.set_origin("http://example.com/1"); |
| 1021 { | 1018 { |
| 1022 syncable::ReadTransaction trans(FROM_HERE, directory()); | 1019 syncable::ReadTransaction trans(FROM_HERE, directory()); |
| 1023 cryptographer = directory()->GetCryptographer(&trans); | 1020 cryptographer = directory()->GetCryptographer(&trans); |
| 1024 | 1021 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1066 EXPECT_FALSE(e1.GetIsUnappliedUpdate()); | 1063 EXPECT_FALSE(e1.GetIsUnappliedUpdate()); |
| 1067 EXPECT_TRUE(e2.GetIsUnappliedUpdate()); | 1064 EXPECT_TRUE(e2.GetIsUnappliedUpdate()); |
| 1068 } | 1065 } |
| 1069 } | 1066 } |
| 1070 | 1067 |
| 1071 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 1068 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, |
| 1072 SimpleConflictDifferentAttachmentMetadata) { | 1069 SimpleConflictDifferentAttachmentMetadata) { |
| 1073 const bool is_folder = false; | 1070 const bool is_folder = false; |
| 1074 sync_pb::EntitySpecifics specifics; | 1071 sync_pb::EntitySpecifics specifics; |
| 1075 *specifics.mutable_article() = sync_pb::ArticleSpecifics(); | 1072 *specifics.mutable_article() = sync_pb::ArticleSpecifics(); |
| 1076 int64 handle = entry_factory()->CreateSyncedItem("art1", ARTICLES, is_folder); | 1073 int64_t handle = |
| 1074 entry_factory()->CreateSyncedItem("art1", ARTICLES, is_folder); |
| 1077 | 1075 |
| 1078 sync_pb::AttachmentIdProto local_attachment_id = | 1076 sync_pb::AttachmentIdProto local_attachment_id = |
| 1079 CreateAttachmentIdProto(0, 0); | 1077 CreateAttachmentIdProto(0, 0); |
| 1080 sync_pb::AttachmentIdProto server_attachment_id = | 1078 sync_pb::AttachmentIdProto server_attachment_id = |
| 1081 CreateAttachmentIdProto(0, 0); | 1079 CreateAttachmentIdProto(0, 0); |
| 1082 | 1080 |
| 1083 // Add an attachment to the local attachment metadata. | 1081 // Add an attachment to the local attachment metadata. |
| 1084 sync_pb::AttachmentMetadata local_metadata; | 1082 sync_pb::AttachmentMetadata local_metadata; |
| 1085 sync_pb::AttachmentMetadataRecord* local_record = local_metadata.add_record(); | 1083 sync_pb::AttachmentMetadataRecord* local_record = local_metadata.add_record(); |
| 1086 *local_record->mutable_id() = local_attachment_id; | 1084 *local_record->mutable_id() = local_attachment_id; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1110 local_metadata = entry_factory()->GetLocalAttachmentMetadataForItem(handle); | 1108 local_metadata = entry_factory()->GetLocalAttachmentMetadataForItem(handle); |
| 1111 EXPECT_EQ(server_metadata.SerializeAsString(), | 1109 EXPECT_EQ(server_metadata.SerializeAsString(), |
| 1112 local_metadata.SerializeAsString()); | 1110 local_metadata.SerializeAsString()); |
| 1113 } | 1111 } |
| 1114 | 1112 |
| 1115 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, | 1113 TEST_F(DirectoryUpdateHandlerApplyUpdateTest, |
| 1116 SimpleConflictSameAttachmentMetadataDifferentOrder) { | 1114 SimpleConflictSameAttachmentMetadataDifferentOrder) { |
| 1117 const bool is_folder = false; | 1115 const bool is_folder = false; |
| 1118 sync_pb::EntitySpecifics specifics; | 1116 sync_pb::EntitySpecifics specifics; |
| 1119 *specifics.mutable_article() = sync_pb::ArticleSpecifics(); | 1117 *specifics.mutable_article() = sync_pb::ArticleSpecifics(); |
| 1120 int64 handle = entry_factory()->CreateSyncedItem("art1", ARTICLES, is_folder); | 1118 int64_t handle = |
| 1119 entry_factory()->CreateSyncedItem("art1", ARTICLES, is_folder); |
| 1121 | 1120 |
| 1122 sync_pb::AttachmentIdProto id1 = CreateAttachmentIdProto(0, 0); | 1121 sync_pb::AttachmentIdProto id1 = CreateAttachmentIdProto(0, 0); |
| 1123 sync_pb::AttachmentIdProto id2 = CreateAttachmentIdProto(0, 0); | 1122 sync_pb::AttachmentIdProto id2 = CreateAttachmentIdProto(0, 0); |
| 1124 | 1123 |
| 1125 // Add id1, then id2 to the local attachment metadata. | 1124 // Add id1, then id2 to the local attachment metadata. |
| 1126 sync_pb::AttachmentMetadata local_metadata; | 1125 sync_pb::AttachmentMetadata local_metadata; |
| 1127 sync_pb::AttachmentMetadataRecord* record = local_metadata.add_record(); | 1126 sync_pb::AttachmentMetadataRecord* record = local_metadata.add_record(); |
| 1128 *record->mutable_id() = id1; | 1127 *record->mutable_id() = id1; |
| 1129 record->set_is_on_server(true); | 1128 record->set_is_on_server(true); |
| 1130 record = local_metadata.add_record(); | 1129 record = local_metadata.add_record(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1151 const UpdateCounters& counters = GetArticlesUpdateCounters(); | 1150 const UpdateCounters& counters = GetArticlesUpdateCounters(); |
| 1152 EXPECT_EQ(1, counters.num_updates_applied); | 1151 EXPECT_EQ(1, counters.num_updates_applied); |
| 1153 EXPECT_EQ(1, counters.num_local_overwrites); | 1152 EXPECT_EQ(1, counters.num_local_overwrites); |
| 1154 EXPECT_EQ(0, counters.num_server_overwrites); | 1153 EXPECT_EQ(0, counters.num_server_overwrites); |
| 1155 local_metadata = entry_factory()->GetLocalAttachmentMetadataForItem(handle); | 1154 local_metadata = entry_factory()->GetLocalAttachmentMetadataForItem(handle); |
| 1156 EXPECT_EQ(server_metadata.SerializeAsString(), | 1155 EXPECT_EQ(server_metadata.SerializeAsString(), |
| 1157 local_metadata.SerializeAsString()); | 1156 local_metadata.SerializeAsString()); |
| 1158 } | 1157 } |
| 1159 | 1158 |
| 1160 } // namespace syncer | 1159 } // namespace syncer |
| OLD | NEW |