OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2006-2009 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 "chrome/browser/sync/engine/apply_updates_command.h" |
| 6 #include "chrome/browser/sync/engine/sync_cycle_state.h" |
| 7 #include "chrome/browser/sync/engine/sync_process_state.h" |
| 8 #include "chrome/browser/sync/engine/syncer_session.h" |
| 9 #include "chrome/browser/sync/syncable/directory_manager.h" |
| 10 #include "chrome/browser/sync/syncable/syncable.h" |
| 11 #include "chrome/browser/sync/syncable/syncable_id.h" |
| 12 #include "chrome/browser/sync/util/character_set_converters.h" |
| 13 #include "chrome/test/sync/engine/test_directory_setter_upper.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 |
| 16 using std::string; |
| 17 using syncable::ScopedDirLookup; |
| 18 using syncable::WriteTransaction; |
| 19 using syncable::ReadTransaction; |
| 20 using syncable::MutableEntry; |
| 21 using syncable::Entry; |
| 22 using syncable::Id; |
| 23 using syncable::UNITTEST; |
| 24 |
| 25 namespace browser_sync { |
| 26 |
| 27 // A test fixture for tests exercising ApplyUpdatesCommand. |
| 28 class ApplyUpdatesCommandTest : public testing::Test { |
| 29 protected: |
| 30 ApplyUpdatesCommandTest() : next_revision_(1) {} |
| 31 virtual ~ApplyUpdatesCommandTest() {} |
| 32 virtual void SetUp() { |
| 33 syncdb_.SetUp(); |
| 34 } |
| 35 virtual void TearDown() { |
| 36 syncdb_.TearDown(); |
| 37 } |
| 38 |
| 39 protected: |
| 40 // Create a new unapplied update. |
| 41 void CreateUnappliedNewItemWithParent(const string& item_id, |
| 42 const string& parent_id) { |
| 43 ScopedDirLookup dir(syncdb_.manager(), syncdb_.name()); |
| 44 ASSERT_TRUE(dir.good()); |
| 45 WriteTransaction trans(dir, UNITTEST, __FILE__, __LINE__); |
| 46 MutableEntry entry(&trans, syncable::CREATE_NEW_UPDATE_ITEM, |
| 47 Id::CreateFromServerId(item_id)); |
| 48 ASSERT_TRUE(entry.good()); |
| 49 PathString name; |
| 50 AppendUTF8ToPathString(item_id, &name); |
| 51 entry.Put(syncable::SERVER_VERSION, next_revision_++); |
| 52 entry.Put(syncable::IS_UNAPPLIED_UPDATE, true); |
| 53 entry.Put(syncable::SERVER_NAME, name); |
| 54 entry.Put(syncable::SERVER_NON_UNIQUE_NAME, name); |
| 55 entry.Put(syncable::SERVER_PARENT_ID, Id::CreateFromServerId(parent_id)); |
| 56 entry.Put(syncable::SERVER_IS_DIR, true); |
| 57 } |
| 58 |
| 59 TestDirectorySetterUpper syncdb_; |
| 60 ApplyUpdatesCommand apply_updates_command_; |
| 61 |
| 62 private: |
| 63 int64 next_revision_; |
| 64 DISALLOW_COPY_AND_ASSIGN(ApplyUpdatesCommandTest); |
| 65 }; |
| 66 |
| 67 TEST_F(ApplyUpdatesCommandTest, Simple) { |
| 68 string root_server_id = syncable::kNullId.GetServerId(); |
| 69 CreateUnappliedNewItemWithParent("parent", root_server_id); |
| 70 CreateUnappliedNewItemWithParent("child", "parent"); |
| 71 |
| 72 SyncCycleState cycle_state; |
| 73 SyncProcessState process_state(syncdb_.manager(), syncdb_.name(), |
| 74 NULL, NULL, NULL, NULL); |
| 75 SyncerSession session(&cycle_state, &process_state); |
| 76 |
| 77 apply_updates_command_.ModelChangingExecuteImpl(&session); |
| 78 |
| 79 EXPECT_EQ(2, cycle_state.AppliedUpdatesSize()) |
| 80 << "All updates should have been attempted"; |
| 81 EXPECT_EQ(0, process_state.ConflictingItemsSize()) |
| 82 << "Simple update shouldn't result in conflicts"; |
| 83 EXPECT_EQ(0, process_state.BlockedItemsSize()) |
| 84 << "Blocked items shouldn't be possible under any circumstances"; |
| 85 EXPECT_EQ(2, cycle_state.SuccessfullyAppliedUpdateCount()) |
| 86 << "All items should have been successfully applied"; |
| 87 } |
| 88 |
| 89 TEST_F(ApplyUpdatesCommandTest, UpdateWithChildrenBeforeParents) { |
| 90 // Set a bunch of updates which are difficult to apply in the order |
| 91 // they're received due to dependencies on other unseen items. |
| 92 string root_server_id = syncable::kNullId.GetServerId(); |
| 93 CreateUnappliedNewItemWithParent("a_child_created_first", "parent"); |
| 94 CreateUnappliedNewItemWithParent("x_child_created_first", "parent"); |
| 95 CreateUnappliedNewItemWithParent("parent", root_server_id); |
| 96 CreateUnappliedNewItemWithParent("a_child_created_second", "parent"); |
| 97 CreateUnappliedNewItemWithParent("x_child_created_second", "parent"); |
| 98 |
| 99 SyncCycleState cycle_state; |
| 100 SyncProcessState process_state(syncdb_.manager(), syncdb_.name(), |
| 101 NULL, NULL, NULL, NULL); |
| 102 SyncerSession session(&cycle_state, &process_state); |
| 103 |
| 104 apply_updates_command_.ModelChangingExecuteImpl(&session); |
| 105 |
| 106 EXPECT_EQ(5, cycle_state.AppliedUpdatesSize()) |
| 107 << "All updates should have been attempted"; |
| 108 EXPECT_EQ(0, process_state.ConflictingItemsSize()) |
| 109 << "Simple update shouldn't result in conflicts, even if out-of-order"; |
| 110 EXPECT_EQ(0, process_state.BlockedItemsSize()) |
| 111 << "Blocked items shouldn't be possible under any circumstances"; |
| 112 EXPECT_EQ(5, cycle_state.SuccessfullyAppliedUpdateCount()) |
| 113 << "All updates should have been successfully applied"; |
| 114 } |
| 115 |
| 116 TEST_F(ApplyUpdatesCommandTest, NestedItemsWithUnknownParent) { |
| 117 // We shouldn't be able to do anything with either of these items. |
| 118 CreateUnappliedNewItemWithParent("some_item", "unknown_parent"); |
| 119 CreateUnappliedNewItemWithParent("some_other_item", "some_item"); |
| 120 |
| 121 SyncCycleState cycle_state; |
| 122 SyncProcessState process_state(syncdb_.manager(), syncdb_.name(), |
| 123 NULL, NULL, NULL, NULL); |
| 124 SyncerSession session(&cycle_state, &process_state); |
| 125 |
| 126 apply_updates_command_.ModelChangingExecuteImpl(&session); |
| 127 |
| 128 EXPECT_EQ(2, cycle_state.AppliedUpdatesSize()) |
| 129 << "All updates should have been attempted"; |
| 130 EXPECT_EQ(2, process_state.ConflictingItemsSize()) |
| 131 << "All updates with an unknown ancestors should be in conflict"; |
| 132 EXPECT_EQ(0, process_state.BlockedItemsSize()) |
| 133 << "Blocked items shouldn't be possible under any circumstances"; |
| 134 EXPECT_EQ(0, cycle_state.SuccessfullyAppliedUpdateCount()) |
| 135 << "No item with an unknown ancestor should be applied"; |
| 136 } |
| 137 |
| 138 TEST_F(ApplyUpdatesCommandTest, ItemsBothKnownAndUnknown) { |
| 139 // See what happens when there's a mixture of good and bad updates. |
| 140 string root_server_id = syncable::kNullId.GetServerId(); |
| 141 CreateUnappliedNewItemWithParent("first_unknown_item", "unknown_parent"); |
| 142 CreateUnappliedNewItemWithParent("first_known_item", root_server_id); |
| 143 CreateUnappliedNewItemWithParent("second_unknown_item", "unknown_parent"); |
| 144 CreateUnappliedNewItemWithParent("second_known_item", "first_known_item"); |
| 145 CreateUnappliedNewItemWithParent("third_known_item", "fourth_known_item"); |
| 146 CreateUnappliedNewItemWithParent("fourth_known_item", root_server_id); |
| 147 |
| 148 SyncCycleState cycle_state; |
| 149 SyncProcessState process_state(syncdb_.manager(), syncdb_.name(), |
| 150 NULL, NULL, NULL, NULL); |
| 151 SyncerSession session(&cycle_state, &process_state); |
| 152 |
| 153 apply_updates_command_.ModelChangingExecuteImpl(&session); |
| 154 |
| 155 EXPECT_EQ(6, cycle_state.AppliedUpdatesSize()) |
| 156 << "All updates should have been attempted"; |
| 157 EXPECT_EQ(2, process_state.ConflictingItemsSize()) |
| 158 << "The updates with unknown ancestors should be in conflict"; |
| 159 EXPECT_EQ(0, process_state.BlockedItemsSize()) |
| 160 << "Blocked items shouldn't be possible under any circumstances"; |
| 161 EXPECT_EQ(4, cycle_state.SuccessfullyAppliedUpdateCount()) |
| 162 << "The updates with known ancestors should be successfully applied"; |
| 163 } |
| 164 |
| 165 |
| 166 } // namespace browser_sync |
OLD | NEW |