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

Side by Side Diff: sync/engine/apply_updates_and_resolve_conflicts_command_unittest.cc

Issue 11192071: sync: Merge apply updates and resolve conflicts (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Retry (base files were missing) Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <string> 5 #include <string>
6 6
7 #include "base/location.h" 7 #include "base/location.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/stringprintf.h" 9 #include "base/stringprintf.h"
10 #include "sync/engine/apply_updates_command.h" 10 #include "sync/engine/apply_updates_and_resolve_conflicts_command.h"
11 #include "sync/engine/syncer.h" 11 #include "sync/engine/syncer.h"
12 #include "sync/internal_api/public/test/test_entry_factory.h" 12 #include "sync/internal_api/public/test/test_entry_factory.h"
13 #include "sync/protocol/bookmark_specifics.pb.h" 13 #include "sync/protocol/bookmark_specifics.pb.h"
14 #include "sync/protocol/password_specifics.pb.h" 14 #include "sync/protocol/password_specifics.pb.h"
15 #include "sync/syncable/mutable_entry.h" 15 #include "sync/syncable/mutable_entry.h"
16 #include "sync/syncable/read_transaction.h" 16 #include "sync/syncable/read_transaction.h"
17 #include "sync/syncable/syncable_id.h" 17 #include "sync/syncable/syncable_id.h"
18 #include "sync/syncable/syncable_util.h" 18 #include "sync/syncable/syncable_util.h"
19 #include "sync/syncable/write_transaction.h" 19 #include "sync/syncable/write_transaction.h"
20 #include "sync/test/engine/fake_model_worker.h" 20 #include "sync/test/engine/fake_model_worker.h"
(...skipping 12 matching lines...) Expand all
33 using syncable::WriteTransaction; 33 using syncable::WriteTransaction;
34 34
35 namespace { 35 namespace {
36 sync_pb::EntitySpecifics DefaultBookmarkSpecifics() { 36 sync_pb::EntitySpecifics DefaultBookmarkSpecifics() {
37 sync_pb::EntitySpecifics result; 37 sync_pb::EntitySpecifics result;
38 AddDefaultFieldValue(BOOKMARKS, &result); 38 AddDefaultFieldValue(BOOKMARKS, &result);
39 return result; 39 return result;
40 } 40 }
41 } // namespace 41 } // namespace
42 42
43 // A test fixture for tests exercising ApplyUpdatesCommand. 43 // A test fixture for tests exercising ApplyUpdatesAndResolveConflictsCommand.
44 class ApplyUpdatesCommandTest : public SyncerCommandTest { 44 class ApplyUpdatesAndResolveConflictsCommandTest : public SyncerCommandTest {
45 public: 45 public:
46 protected: 46 protected:
47 ApplyUpdatesCommandTest() {} 47 ApplyUpdatesAndResolveConflictsCommandTest() {}
48 virtual ~ApplyUpdatesCommandTest() {} 48 virtual ~ApplyUpdatesAndResolveConflictsCommandTest() {}
49 49
50 virtual void SetUp() { 50 virtual void SetUp() {
51 workers()->clear(); 51 workers()->clear();
52 mutable_routing_info()->clear(); 52 mutable_routing_info()->clear();
53 workers()->push_back( 53 workers()->push_back(
54 make_scoped_refptr(new FakeModelWorker(GROUP_UI))); 54 make_scoped_refptr(new FakeModelWorker(GROUP_UI)));
55 workers()->push_back( 55 workers()->push_back(
56 make_scoped_refptr(new FakeModelWorker(GROUP_PASSWORD))); 56 make_scoped_refptr(new FakeModelWorker(GROUP_PASSWORD)));
57 (*mutable_routing_info())[BOOKMARKS] = GROUP_UI; 57 (*mutable_routing_info())[BOOKMARKS] = GROUP_UI;
58 (*mutable_routing_info())[PASSWORDS] = GROUP_PASSWORD; 58 (*mutable_routing_info())[PASSWORDS] = GROUP_PASSWORD;
59 (*mutable_routing_info())[NIGORI] = GROUP_PASSIVE; 59 (*mutable_routing_info())[NIGORI] = GROUP_PASSIVE;
60 SyncerCommandTest::SetUp(); 60 SyncerCommandTest::SetUp();
61 entry_factory_.reset(new TestEntryFactory(directory())); 61 entry_factory_.reset(new TestEntryFactory(directory()));
62 ExpectNoGroupsToChange(apply_updates_command_); 62 ExpectNoGroupsToChange(apply_updates_command_);
63 } 63 }
64 64
65 protected: 65 protected:
66 DISALLOW_COPY_AND_ASSIGN(ApplyUpdatesCommandTest); 66 DISALLOW_COPY_AND_ASSIGN(ApplyUpdatesAndResolveConflictsCommandTest);
67 67
68 ApplyUpdatesCommand apply_updates_command_; 68 ApplyUpdatesAndResolveConflictsCommand apply_updates_command_;
69 scoped_ptr<TestEntryFactory> entry_factory_; 69 scoped_ptr<TestEntryFactory> entry_factory_;
70 }; 70 };
71 71
72 TEST_F(ApplyUpdatesCommandTest, Simple) { 72 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest, Simple) {
73 string root_server_id = syncable::GetNullId().GetServerId(); 73 string root_server_id = syncable::GetNullId().GetServerId();
74 entry_factory_->CreateUnappliedNewItemWithParent("parent", 74 entry_factory_->CreateUnappliedNewItemWithParent("parent",
75 DefaultBookmarkSpecifics(), 75 DefaultBookmarkSpecifics(),
76 root_server_id); 76 root_server_id);
77 entry_factory_->CreateUnappliedNewItemWithParent("child", 77 entry_factory_->CreateUnappliedNewItemWithParent("child",
78 DefaultBookmarkSpecifics(), 78 DefaultBookmarkSpecifics(),
79 "parent"); 79 "parent");
80 80
81 ExpectGroupToChange(apply_updates_command_, GROUP_UI); 81 ExpectGroupToChange(apply_updates_command_, GROUP_UI);
82 apply_updates_command_.ExecuteImpl(session()); 82 apply_updates_command_.ExecuteImpl(session());
83 83
84 const sessions::StatusController& status = session()->status_controller(); 84 const sessions::StatusController& status = session()->status_controller();
85 EXPECT_EQ(0, status.num_simple_conflicts())
86 << "Simple update shouldn't result in conflicts";
87 EXPECT_EQ(0, status.num_encryption_conflicts()) 85 EXPECT_EQ(0, status.num_encryption_conflicts())
88 << "Simple update shouldn't result in conflicts"; 86 << "Simple update shouldn't result in conflicts";
89 EXPECT_EQ(0, status.num_hierarchy_conflicts()) 87 EXPECT_EQ(0, status.num_hierarchy_conflicts())
90 << "Simple update shouldn't result in conflicts"; 88 << "Simple update shouldn't result in conflicts";
91 EXPECT_EQ(2, status.num_updates_applied()) 89 EXPECT_EQ(2, status.num_updates_applied())
92 << "All items should have been successfully applied"; 90 << "All items should have been successfully applied";
93 } 91 }
94 92
95 TEST_F(ApplyUpdatesCommandTest, UpdateWithChildrenBeforeParents) { 93 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest,
94 UpdateWithChildrenBeforeParents) {
96 // Set a bunch of updates which are difficult to apply in the order 95 // Set a bunch of updates which are difficult to apply in the order
97 // they're received due to dependencies on other unseen items. 96 // they're received due to dependencies on other unseen items.
98 string root_server_id = syncable::GetNullId().GetServerId(); 97 string root_server_id = syncable::GetNullId().GetServerId();
99 entry_factory_->CreateUnappliedNewItemWithParent( 98 entry_factory_->CreateUnappliedNewItemWithParent(
100 "a_child_created_first", DefaultBookmarkSpecifics(), "parent"); 99 "a_child_created_first", DefaultBookmarkSpecifics(), "parent");
101 entry_factory_->CreateUnappliedNewItemWithParent( 100 entry_factory_->CreateUnappliedNewItemWithParent(
102 "x_child_created_first", DefaultBookmarkSpecifics(), "parent"); 101 "x_child_created_first", DefaultBookmarkSpecifics(), "parent");
103 entry_factory_->CreateUnappliedNewItemWithParent( 102 entry_factory_->CreateUnappliedNewItemWithParent(
104 "parent", DefaultBookmarkSpecifics(), root_server_id); 103 "parent", DefaultBookmarkSpecifics(), root_server_id);
105 entry_factory_->CreateUnappliedNewItemWithParent( 104 entry_factory_->CreateUnappliedNewItemWithParent(
106 "a_child_created_second", DefaultBookmarkSpecifics(), "parent"); 105 "a_child_created_second", DefaultBookmarkSpecifics(), "parent");
107 entry_factory_->CreateUnappliedNewItemWithParent( 106 entry_factory_->CreateUnappliedNewItemWithParent(
108 "x_child_created_second", DefaultBookmarkSpecifics(), "parent"); 107 "x_child_created_second", DefaultBookmarkSpecifics(), "parent");
109 108
110 ExpectGroupToChange(apply_updates_command_, GROUP_UI); 109 ExpectGroupToChange(apply_updates_command_, GROUP_UI);
111 apply_updates_command_.ExecuteImpl(session()); 110 apply_updates_command_.ExecuteImpl(session());
112 111
113 const sessions::StatusController& status = session()->status_controller(); 112 const sessions::StatusController& status = session()->status_controller();
114 EXPECT_EQ(0, status.num_simple_conflicts())
115 << "Simple update shouldn't result in conflicts, even if out-of-order";
116 EXPECT_EQ(5, status.num_updates_applied()) 113 EXPECT_EQ(5, status.num_updates_applied())
117 << "All updates should have been successfully applied"; 114 << "All updates should have been successfully applied";
118 } 115 }
119 116
120 // Runs the ApplyUpdatesCommand on an item that has both local and remote 117 // Runs the ApplyUpdatesAndResolveConflictsCommand on an item that has both
121 // modifications (IS_UNSYNCED and IS_UNAPPLIED_UPDATE). We expect the command 118 // local and remote modifications (IS_UNSYNCED and IS_UNAPPLIED_UPDATE). We
122 // to detect that this update can't be applied because it is in a CONFLICT 119 // expect the command to detect that this update can't be applied because it is
123 // state. 120 // in a CONFLICT state.
124 TEST_F(ApplyUpdatesCommandTest, SimpleConflict) { 121 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest, SimpleConflict) {
125 entry_factory_->CreateUnappliedAndUnsyncedItem("item", BOOKMARKS); 122 entry_factory_->CreateUnappliedAndUnsyncedItem("item", BOOKMARKS);
126 123
127 ExpectGroupToChange(apply_updates_command_, GROUP_UI); 124 ExpectGroupToChange(apply_updates_command_, GROUP_UI);
128 apply_updates_command_.ExecuteImpl(session()); 125 apply_updates_command_.ExecuteImpl(session());
129 126
130 const sessions::StatusController& status = session()->status_controller(); 127 const sessions::StatusController& status = session()->status_controller();
131 EXPECT_EQ(1, status.num_simple_conflicts()) 128 EXPECT_EQ(1, status.num_server_overwrites())
132 << "Unsynced and unapplied item should be a simple conflict"; 129 << "Unsynced and unapplied item conflict should be resolved";
130 EXPECT_EQ(0, status.num_updates_applied())
131 << "Update should not be applied; we should override the server.";
133 } 132 }
134 133
135 // Runs the ApplyUpdatesCommand on an item that has both local and remote 134 // Runs the ApplyUpdatesAndResolveConflictsCommand on an item that has both
136 // modifications *and* the remote modification cannot be applied without 135 // local and remote modifications *and* the remote modification cannot be
137 // violating the tree constraints. We expect the command to detect that this 136 // applied without violating the tree constraints. We expect the command to
138 // update can't be applied and that this situation can't be resolved with the 137 // detect that this update can't be applied and that this situation can't be
139 // simple conflict processing logic; it is in a CONFLICT_HIERARCHY state. 138 // resolved with the simple conflict processing logic; it is in a
140 TEST_F(ApplyUpdatesCommandTest, HierarchyAndSimpleConflict) { 139 // CONFLICT_HIERARCHY state.
140 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest, HierarchyAndSimpleConflict) {
141 // Create a simply-conflicting item. It will start with valid parent ids. 141 // Create a simply-conflicting item. It will start with valid parent ids.
142 int64 handle = entry_factory_->CreateUnappliedAndUnsyncedItem( 142 int64 handle = entry_factory_->CreateUnappliedAndUnsyncedItem(
143 "orphaned_by_server", BOOKMARKS); 143 "orphaned_by_server", BOOKMARKS);
144 { 144 {
145 // Manually set the SERVER_PARENT_ID to bad value. 145 // Manually set the SERVER_PARENT_ID to bad value.
146 // A bad parent indicates a hierarchy conflict. 146 // A bad parent indicates a hierarchy conflict.
147 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); 147 WriteTransaction trans(FROM_HERE, UNITTEST, directory());
148 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); 148 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle);
149 ASSERT_TRUE(entry.good()); 149 ASSERT_TRUE(entry.good());
150 150
151 entry.Put(syncable::SERVER_PARENT_ID, 151 entry.Put(syncable::SERVER_PARENT_ID,
152 TestIdFactory::MakeServer("bogus_parent")); 152 TestIdFactory::MakeServer("bogus_parent"));
153 } 153 }
154 154
155 ExpectGroupToChange(apply_updates_command_, GROUP_UI); 155 ExpectGroupToChange(apply_updates_command_, GROUP_UI);
156 apply_updates_command_.ExecuteImpl(session()); 156 apply_updates_command_.ExecuteImpl(session());
157 157
158 const sessions::StatusController& status = session()->status_controller(); 158 const sessions::StatusController& status = session()->status_controller();
159
160 // An update that is both a simple conflict and a hierarchy conflict should be
161 // treated as a hierarchy conflict.
162 EXPECT_EQ(1, status.num_hierarchy_conflicts()); 159 EXPECT_EQ(1, status.num_hierarchy_conflicts());
163 EXPECT_EQ(0, status.num_simple_conflicts());
164 } 160 }
165 161
166 162
167 // Runs the ApplyUpdatesCommand on an item with remote modifications that would 163 // Runs the ApplyUpdatesAndResolveConflictsCommand on an item with remote
168 // create a directory loop if the update were applied. We expect the command to 164 // modifications that would create a directory loop if the update were applied.
169 // detect that this update can't be applied because it is in a 165 // We expect the command to detect that this update can't be applied because it
170 // CONFLICT_HIERARCHY state. 166 // is in a CONFLICT_HIERARCHY state.
171 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDirectoryLoop) { 167 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest,
168 HierarchyConflictDirectoryLoop) {
172 // Item 'X' locally has parent of 'root'. Server is updating it to have 169 // Item 'X' locally has parent of 'root'. Server is updating it to have
173 // parent of 'Y'. 170 // parent of 'Y'.
174 { 171 {
175 // Create it as a child of root node. 172 // Create it as a child of root node.
176 int64 handle = entry_factory_->CreateSyncedItem("X", BOOKMARKS, true); 173 int64 handle = entry_factory_->CreateSyncedItem("X", BOOKMARKS, true);
177 174
178 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); 175 WriteTransaction trans(FROM_HERE, UNITTEST, directory());
179 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); 176 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle);
180 ASSERT_TRUE(entry.good()); 177 ASSERT_TRUE(entry.good());
181 178
(...skipping 13 matching lines...) Expand all
195 // prevent the update from being applied and note that this is a hierarchy 192 // prevent the update from being applied and note that this is a hierarchy
196 // conflict. 193 // conflict.
197 194
198 ExpectGroupToChange(apply_updates_command_, GROUP_UI); 195 ExpectGroupToChange(apply_updates_command_, GROUP_UI);
199 apply_updates_command_.ExecuteImpl(session()); 196 apply_updates_command_.ExecuteImpl(session());
200 197
201 const sessions::StatusController& status = session()->status_controller(); 198 const sessions::StatusController& status = session()->status_controller();
202 199
203 // This should count as a hierarchy conflict. 200 // This should count as a hierarchy conflict.
204 EXPECT_EQ(1, status.num_hierarchy_conflicts()); 201 EXPECT_EQ(1, status.num_hierarchy_conflicts());
205 EXPECT_EQ(0, status.num_simple_conflicts());
206 } 202 }
207 203
208 // Runs the ApplyUpdatesCommand on a directory where the server sent us an 204 // Runs the ApplyUpdatesAndResolveConflictsCommand on a directory where the
209 // update to add a child to a locally deleted (and unsynced) parent. We expect 205 // server sent us an update to add a child to a locally deleted (and unsynced)
210 // the command to not apply the update and to indicate the update is in a 206 // parent. We expect the command to not apply the update and to indicate the
211 // CONFLICT_HIERARCHY state. 207 // update is in a CONFLICT_HIERARCHY state.
212 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeletedParent) { 208 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest,
209 HierarchyConflictDeletedParent) {
213 // Create a locally deleted parent item. 210 // Create a locally deleted parent item.
214 int64 parent_handle; 211 int64 parent_handle;
215 entry_factory_->CreateUnsyncedItem( 212 entry_factory_->CreateUnsyncedItem(
216 Id::CreateFromServerId("parent"), TestIdFactory::root(), 213 Id::CreateFromServerId("parent"), TestIdFactory::root(),
217 "parent", true, BOOKMARKS, &parent_handle); 214 "parent", true, BOOKMARKS, &parent_handle);
218 { 215 {
219 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); 216 WriteTransaction trans(FROM_HERE, UNITTEST, directory());
220 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, parent_handle); 217 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, parent_handle);
221 entry.Put(syncable::IS_DEL, true); 218 entry.Put(syncable::IS_DEL, true);
222 } 219 }
223 220
224 // Create an incoming child from the server. 221 // Create an incoming child from the server.
225 entry_factory_->CreateUnappliedNewItemWithParent( 222 entry_factory_->CreateUnappliedNewItemWithParent(
226 "child", DefaultBookmarkSpecifics(), "parent"); 223 "child", DefaultBookmarkSpecifics(), "parent");
227 224
228 // The server's update may seem valid to some other client, but on this client 225 // The server's update may seem valid to some other client, but on this client
229 // that new item's parent no longer exists. The update should not be applied 226 // that new item's parent no longer exists. The update should not be applied
230 // and the update applicator should indicate this is a hierarchy conflict. 227 // and the update applicator should indicate this is a hierarchy conflict.
231 228
232 ExpectGroupToChange(apply_updates_command_, GROUP_UI); 229 ExpectGroupToChange(apply_updates_command_, GROUP_UI);
233 apply_updates_command_.ExecuteImpl(session()); 230 apply_updates_command_.ExecuteImpl(session());
234 231
235 const sessions::StatusController& status = session()->status_controller(); 232 const sessions::StatusController& status = session()->status_controller();
236 EXPECT_EQ(1, status.num_hierarchy_conflicts()); 233 EXPECT_EQ(1, status.num_hierarchy_conflicts());
237 EXPECT_EQ(0, status.num_simple_conflicts());
238 } 234 }
239 235
240 // Runs the ApplyUpdatesCommand on a directory where the server is trying to 236 // Runs the ApplyUpdatesAndResolveConflictsCommand on a directory where the
241 // delete a folder that has a recently added (and unsynced) child. We expect 237 // server is trying to delete a folder that has a recently added (and unsynced)
242 // the command to not apply the update because it is in a CONFLICT_HIERARCHY 238 // child. We expect the command to not apply the update because it is in a
243 // state. 239 // CONFLICT_HIERARCHY state.
244 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictDeleteNonEmptyDirectory) { 240 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest,
241 HierarchyConflictDeleteNonEmptyDirectory) {
245 // Create a server-deleted directory. 242 // Create a server-deleted directory.
246 { 243 {
247 // Create it as a child of root node. 244 // Create it as a child of root node.
248 int64 handle = 245 int64 handle =
249 entry_factory_->CreateSyncedItem("parent", BOOKMARKS, true); 246 entry_factory_->CreateSyncedItem("parent", BOOKMARKS, true);
250 247
251 WriteTransaction trans(FROM_HERE, UNITTEST, directory()); 248 WriteTransaction trans(FROM_HERE, UNITTEST, directory());
252 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle); 249 MutableEntry entry(&trans, syncable::GET_BY_HANDLE, handle);
253 ASSERT_TRUE(entry.good()); 250 ASSERT_TRUE(entry.good());
254 251
(...skipping 11 matching lines...) Expand all
266 263
267 // The server's request to delete the directory must be ignored, otherwise our 264 // The server's request to delete the directory must be ignored, otherwise our
268 // unsynced new child would be orphaned. This is a hierarchy conflict. 265 // unsynced new child would be orphaned. This is a hierarchy conflict.
269 266
270 ExpectGroupToChange(apply_updates_command_, GROUP_UI); 267 ExpectGroupToChange(apply_updates_command_, GROUP_UI);
271 apply_updates_command_.ExecuteImpl(session()); 268 apply_updates_command_.ExecuteImpl(session());
272 269
273 const sessions::StatusController& status = session()->status_controller(); 270 const sessions::StatusController& status = session()->status_controller();
274 // This should count as a hierarchy conflict. 271 // This should count as a hierarchy conflict.
275 EXPECT_EQ(1, status.num_hierarchy_conflicts()); 272 EXPECT_EQ(1, status.num_hierarchy_conflicts());
276 EXPECT_EQ(0, status.num_simple_conflicts());
277 } 273 }
278 274
279 // Runs the ApplyUpdatesCommand on a server-created item that has a locally 275 // Runs the ApplyUpdatesAndResolveConflictsCommand on a server-created item that
280 // unknown parent. We expect the command to not apply the update because the 276 // has a locally unknown parent. We expect the command to not apply the update
281 // item is in a CONFLICT_HIERARCHY state. 277 // because the item is in a CONFLICT_HIERARCHY state.
282 TEST_F(ApplyUpdatesCommandTest, HierarchyConflictUnknownParent) { 278 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest,
279 HierarchyConflictUnknownParent) {
283 // We shouldn't be able to do anything with either of these items. 280 // We shouldn't be able to do anything with either of these items.
284 entry_factory_->CreateUnappliedNewItemWithParent( 281 entry_factory_->CreateUnappliedNewItemWithParent(
285 "some_item", DefaultBookmarkSpecifics(), "unknown_parent"); 282 "some_item", DefaultBookmarkSpecifics(), "unknown_parent");
286 entry_factory_->CreateUnappliedNewItemWithParent( 283 entry_factory_->CreateUnappliedNewItemWithParent(
287 "some_other_item", DefaultBookmarkSpecifics(), "some_item"); 284 "some_other_item", DefaultBookmarkSpecifics(), "some_item");
288 285
289 ExpectGroupToChange(apply_updates_command_, GROUP_UI); 286 ExpectGroupToChange(apply_updates_command_, GROUP_UI);
290 apply_updates_command_.ExecuteImpl(session()); 287 apply_updates_command_.ExecuteImpl(session());
291 288
292 const sessions::StatusController& status = session()->status_controller(); 289 const sessions::StatusController& status = session()->status_controller();
293 EXPECT_EQ(0, status.num_simple_conflicts())
294 << "Updates with unknown parent should not be treated as 'simple'"
295 << " conflicts";
296 EXPECT_EQ(2, status.num_hierarchy_conflicts()) 290 EXPECT_EQ(2, status.num_hierarchy_conflicts())
297 << "All updates with an unknown ancestors should be in conflict"; 291 << "All updates with an unknown ancestors should be in conflict";
298 EXPECT_EQ(0, status.num_updates_applied()) 292 EXPECT_EQ(0, status.num_updates_applied())
299 << "No item with an unknown ancestor should be applied"; 293 << "No item with an unknown ancestor should be applied";
300 } 294 }
301 295
302 TEST_F(ApplyUpdatesCommandTest, ItemsBothKnownAndUnknown) { 296 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest, ItemsBothKnownAndUnknown) {
303 // See what happens when there's a mixture of good and bad updates. 297 // See what happens when there's a mixture of good and bad updates.
304 string root_server_id = syncable::GetNullId().GetServerId(); 298 string root_server_id = syncable::GetNullId().GetServerId();
305 entry_factory_->CreateUnappliedNewItemWithParent( 299 entry_factory_->CreateUnappliedNewItemWithParent(
306 "first_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); 300 "first_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent");
307 entry_factory_->CreateUnappliedNewItemWithParent( 301 entry_factory_->CreateUnappliedNewItemWithParent(
308 "first_known_item", DefaultBookmarkSpecifics(), root_server_id); 302 "first_known_item", DefaultBookmarkSpecifics(), root_server_id);
309 entry_factory_->CreateUnappliedNewItemWithParent( 303 entry_factory_->CreateUnappliedNewItemWithParent(
310 "second_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent"); 304 "second_unknown_item", DefaultBookmarkSpecifics(), "unknown_parent");
311 entry_factory_->CreateUnappliedNewItemWithParent( 305 entry_factory_->CreateUnappliedNewItemWithParent(
312 "second_known_item", DefaultBookmarkSpecifics(), "first_known_item"); 306 "second_known_item", DefaultBookmarkSpecifics(), "first_known_item");
313 entry_factory_->CreateUnappliedNewItemWithParent( 307 entry_factory_->CreateUnappliedNewItemWithParent(
314 "third_known_item", DefaultBookmarkSpecifics(), "fourth_known_item"); 308 "third_known_item", DefaultBookmarkSpecifics(), "fourth_known_item");
315 entry_factory_->CreateUnappliedNewItemWithParent( 309 entry_factory_->CreateUnappliedNewItemWithParent(
316 "fourth_known_item", DefaultBookmarkSpecifics(), root_server_id); 310 "fourth_known_item", DefaultBookmarkSpecifics(), root_server_id);
317 311
318 ExpectGroupToChange(apply_updates_command_, GROUP_UI); 312 ExpectGroupToChange(apply_updates_command_, GROUP_UI);
319 apply_updates_command_.ExecuteImpl(session()); 313 apply_updates_command_.ExecuteImpl(session());
320 314
321 const sessions::StatusController& status = session()->status_controller(); 315 const sessions::StatusController& status = session()->status_controller();
322 EXPECT_EQ(2, status.num_hierarchy_conflicts()) 316 EXPECT_EQ(2, status.num_hierarchy_conflicts())
323 << "The updates with unknown ancestors should be in conflict"; 317 << "The updates with unknown ancestors should be in conflict";
324 EXPECT_EQ(4, status.num_updates_applied()) 318 EXPECT_EQ(4, status.num_updates_applied())
325 << "The updates with known ancestors should be successfully applied"; 319 << "The updates with known ancestors should be successfully applied";
326 } 320 }
327 321
328 TEST_F(ApplyUpdatesCommandTest, DecryptablePassword) { 322 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest, DecryptablePassword) {
329 // Decryptable password updates should be applied. 323 // Decryptable password updates should be applied.
330 Cryptographer* cryptographer; 324 Cryptographer* cryptographer;
331 { 325 {
332 // Storing the cryptographer separately is bad, but for this test we 326 // Storing the cryptographer separately is bad, but for this test we
333 // know it's safe. 327 // know it's safe.
334 syncable::ReadTransaction trans(FROM_HERE, directory()); 328 syncable::ReadTransaction trans(FROM_HERE, directory());
335 cryptographer = directory()->GetCryptographer(&trans); 329 cryptographer = directory()->GetCryptographer(&trans);
336 } 330 }
337 331
338 KeyParams params = {"localhost", "dummy", "foobar"}; 332 KeyParams params = {"localhost", "dummy", "foobar"};
339 cryptographer->AddKey(params); 333 cryptographer->AddKey(params);
340 334
341 sync_pb::EntitySpecifics specifics; 335 sync_pb::EntitySpecifics specifics;
342 sync_pb::PasswordSpecificsData data; 336 sync_pb::PasswordSpecificsData data;
343 data.set_origin("http://example.com"); 337 data.set_origin("http://example.com");
344 338
345 cryptographer->Encrypt(data, 339 cryptographer->Encrypt(data,
346 specifics.mutable_password()->mutable_encrypted()); 340 specifics.mutable_password()->mutable_encrypted());
347 entry_factory_->CreateUnappliedNewItem("item", specifics, false); 341 entry_factory_->CreateUnappliedNewItem("item", specifics, false);
348 342
349 ExpectGroupToChange(apply_updates_command_, GROUP_PASSWORD); 343 ExpectGroupToChange(apply_updates_command_, GROUP_PASSWORD);
350 apply_updates_command_.ExecuteImpl(session()); 344 apply_updates_command_.ExecuteImpl(session());
351 345
352 const sessions::StatusController& status = session()->status_controller(); 346 const sessions::StatusController& status = session()->status_controller();
353 EXPECT_EQ(0, status.num_simple_conflicts())
354 << "No update should be in conflict because they're all decryptable";
355 EXPECT_EQ(1, status.num_updates_applied()) 347 EXPECT_EQ(1, status.num_updates_applied())
356 << "The updates that can be decrypted should be applied"; 348 << "The updates that can be decrypted should be applied";
357 } 349 }
358 350
359 TEST_F(ApplyUpdatesCommandTest, UndecryptableData) { 351 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest, UndecryptableData) {
360 // Undecryptable updates should not be applied. 352 // Undecryptable updates should not be applied.
361 sync_pb::EntitySpecifics encrypted_bookmark; 353 sync_pb::EntitySpecifics encrypted_bookmark;
362 encrypted_bookmark.mutable_encrypted(); 354 encrypted_bookmark.mutable_encrypted();
363 AddDefaultFieldValue(BOOKMARKS, &encrypted_bookmark); 355 AddDefaultFieldValue(BOOKMARKS, &encrypted_bookmark);
364 string root_server_id = syncable::GetNullId().GetServerId(); 356 string root_server_id = syncable::GetNullId().GetServerId();
365 entry_factory_->CreateUnappliedNewItemWithParent( 357 entry_factory_->CreateUnappliedNewItemWithParent(
366 "folder", encrypted_bookmark, root_server_id); 358 "folder", encrypted_bookmark, root_server_id);
367 entry_factory_->CreateUnappliedNewItem("item2", encrypted_bookmark, false); 359 entry_factory_->CreateUnappliedNewItem("item2", encrypted_bookmark, false);
368 sync_pb::EntitySpecifics encrypted_password; 360 sync_pb::EntitySpecifics encrypted_password;
369 encrypted_password.mutable_password(); 361 encrypted_password.mutable_password();
370 entry_factory_->CreateUnappliedNewItem("item3", encrypted_password, false); 362 entry_factory_->CreateUnappliedNewItem("item3", encrypted_password, false);
371 363
372 ExpectGroupsToChange(apply_updates_command_, GROUP_UI, GROUP_PASSWORD); 364 ExpectGroupsToChange(apply_updates_command_, GROUP_UI, GROUP_PASSWORD);
373 apply_updates_command_.ExecuteImpl(session()); 365 apply_updates_command_.ExecuteImpl(session());
374 366
375 const sessions::StatusController& status = session()->status_controller(); 367 const sessions::StatusController& status = session()->status_controller();
376 EXPECT_TRUE(status.HasConflictingUpdates())
377 << "Updates that can't be decrypted should trigger the syncer to have "
378 << "conflicting updates.";
379 EXPECT_EQ(0, status.num_simple_conflicts())
380 << "Updates that can't be decrypted should not be in regular conflict";
381 EXPECT_EQ(3, status.num_encryption_conflicts()) 368 EXPECT_EQ(3, status.num_encryption_conflicts())
382 << "Updates that can't be decrypted should be in encryption conflict"; 369 << "Updates that can't be decrypted should be in encryption conflict";
383 EXPECT_EQ(0, status.num_updates_applied()) 370 EXPECT_EQ(0, status.num_updates_applied())
384 << "No update that can't be decrypted should be applied"; 371 << "No update that can't be decrypted should be applied";
385 } 372 }
386 373
387 TEST_F(ApplyUpdatesCommandTest, SomeUndecryptablePassword) { 374 TEST_F(ApplyUpdatesAndResolveConflictsCommandTest, SomeUndecryptablePassword) {
388 Cryptographer* cryptographer; 375 Cryptographer* cryptographer;
389 // Only decryptable password updates should be applied. 376 // Only decryptable password updates should be applied.
390 { 377 {
391 sync_pb::EntitySpecifics specifics; 378 sync_pb::EntitySpecifics specifics;
392 sync_pb::PasswordSpecificsData data; 379 sync_pb::PasswordSpecificsData data;
393 data.set_origin("http://example.com/1"); 380 data.set_origin("http://example.com/1");
394 { 381 {
395 syncable::ReadTransaction trans(FROM_HERE, directory()); 382 syncable::ReadTransaction trans(FROM_HERE, directory());
396 cryptographer = directory()->GetCryptographer(&trans); 383 cryptographer = directory()->GetCryptographer(&trans);
397 384
(...skipping 17 matching lines...) Expand all
415 402
416 other_cryptographer.Encrypt(data, 403 other_cryptographer.Encrypt(data,
417 specifics.mutable_password()->mutable_encrypted()); 404 specifics.mutable_password()->mutable_encrypted());
418 entry_factory_->CreateUnappliedNewItem("item2", specifics, false); 405 entry_factory_->CreateUnappliedNewItem("item2", specifics, false);
419 } 406 }
420 407
421 ExpectGroupToChange(apply_updates_command_, GROUP_PASSWORD); 408 ExpectGroupToChange(apply_updates_command_, GROUP_PASSWORD);
422 apply_updates_command_.ExecuteImpl(session()); 409 apply_updates_command_.ExecuteImpl(session());
423 410
424 const sessions::StatusController& status = session()->status_controller(); 411 const sessions::StatusController& status = session()->status_controller();
425 EXPECT_TRUE(status.HasConflictingUpdates())
426 << "Updates that can't be decrypted should trigger the syncer to have "
427 << "conflicting updates.";
428 EXPECT_EQ(0, status.num_simple_conflicts())
429 << "The updates that can't be decrypted should not be in regular "
430 << "conflict";
431 EXPECT_EQ(1, status.num_encryption_conflicts()) 412 EXPECT_EQ(1, status.num_encryption_conflicts())
432 << "The updates that can't be decrypted should be in encryption " 413 << "The updates that can't be decrypted should be in encryption "
433 << "conflict"; 414 << "conflict";
434 EXPECT_EQ(1, status.num_updates_applied()) 415 EXPECT_EQ(1, status.num_updates_applied())
435 << "The undecryptable password update shouldn't be applied"; 416 << "The undecryptable password update shouldn't be applied";
436 } 417 }
437 418
438 } // namespace syncer 419 } // namespace syncer
OLDNEW
« no previous file with comments | « sync/engine/apply_updates_and_resolve_conflicts_command.cc ('k') | sync/engine/apply_updates_command.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698