OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 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 "sync/syncable/parent_child_index.h" | |
6 | |
7 #include <list> | |
8 #include <string> | |
9 | |
10 #include "base/stl_util.h" | |
11 #include "base/strings/string_number_conversions.h" | |
12 #include "sync/syncable/entry_kernel.h" | |
13 #include "sync/syncable/syncable_util.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 namespace syncer { | |
17 namespace syncable { | |
18 | |
19 namespace { | |
20 | |
21 static const std::string kCacheGuid = "8HhNIHlEOCGQbIAALr9QEg=="; | |
22 | |
23 } // namespace | |
24 | |
25 class ParentChildIndexTest : public testing::Test { | |
26 public: | |
27 void TearDown() override { | |
28 // To make memory management easier, we take ownership of all EntryKernels | |
29 // returned by our factory methods and delete them here. | |
30 STLDeleteElements(&owned_entry_kernels_); | |
31 } | |
32 | |
33 // Unfortunately, we can't use the regular Entry factory methods, because the | |
34 // ParentChildIndex deals in EntryKernels. | |
35 | |
36 static syncable::Id GetBookmarkRootId() { | |
37 return syncable::Id::CreateFromServerId("bookmark_folder"); | |
38 } | |
39 | |
40 static syncable::Id GetBookmarkId(int n) { | |
41 return syncable::Id::CreateFromServerId("b" + base::IntToString(n)); | |
42 } | |
43 | |
44 static syncable::Id GetClientUniqueId(int n) { | |
45 return syncable::Id::CreateFromServerId("c" + base::IntToString(n)); | |
46 } | |
47 | |
48 EntryKernel* MakeRoot() { | |
49 // Mimics the root node. | |
50 EntryKernel* root = new EntryKernel(); | |
51 root->put(META_HANDLE, 1); | |
52 root->put(BASE_VERSION, -1); | |
53 root->put(SERVER_VERSION, 0); | |
54 root->put(IS_DIR, true); | |
55 root->put(ID, syncable::Id::GetRoot()); | |
56 root->put(PARENT_ID, syncable::Id::GetRoot()); | |
57 | |
58 owned_entry_kernels_.push_back(root); | |
59 return root; | |
60 } | |
61 | |
62 EntryKernel* MakeTypeRoot(ModelType model_type, const syncable::Id& id) { | |
63 // Mimics a server-created bookmark folder. | |
64 EntryKernel* folder = new EntryKernel; | |
65 folder->put(META_HANDLE, 1); | |
66 folder->put(BASE_VERSION, 9); | |
67 folder->put(SERVER_VERSION, 9); | |
68 folder->put(IS_DIR, true); | |
69 folder->put(ID, id); | |
70 folder->put(PARENT_ID, syncable::Id::GetRoot()); | |
71 folder->put(UNIQUE_SERVER_TAG, ModelTypeToRootTag(model_type)); | |
72 | |
73 // Ensure that GetModelType() returns a correct value. | |
74 sync_pb::EntitySpecifics specifics; | |
75 AddDefaultFieldValue(model_type, &specifics); | |
76 folder->put(SPECIFICS, specifics); | |
77 | |
78 owned_entry_kernels_.push_back(folder); | |
79 return folder; | |
80 } | |
81 | |
82 EntryKernel* MakeBookmarkRoot() { | |
83 return MakeTypeRoot(BOOKMARKS, GetBookmarkRootId()); | |
84 } | |
85 | |
86 EntryKernel* MakeBookmark(int n, int pos, bool is_dir) { | |
87 // Mimics a regular bookmark or folder. | |
88 EntryKernel* bm = new EntryKernel(); | |
89 bm->put(META_HANDLE, n); | |
90 bm->put(BASE_VERSION, 10); | |
91 bm->put(SERVER_VERSION, 10); | |
92 bm->put(IS_DIR, is_dir); | |
93 bm->put(ID, GetBookmarkId(n)); | |
94 bm->put(PARENT_ID, GetBookmarkRootId()); | |
95 | |
96 bm->put(UNIQUE_BOOKMARK_TAG, | |
97 syncable::GenerateSyncableBookmarkHash(kCacheGuid, | |
98 bm->ref(ID).GetServerId())); | |
99 | |
100 UniquePosition unique_pos = | |
101 UniquePosition::FromInt64(pos, bm->ref(UNIQUE_BOOKMARK_TAG)); | |
102 bm->put(UNIQUE_POSITION, unique_pos); | |
103 bm->put(SERVER_UNIQUE_POSITION, unique_pos); | |
104 | |
105 owned_entry_kernels_.push_back(bm); | |
106 return bm; | |
107 } | |
108 | |
109 EntryKernel* MakeUniqueClientItem(ModelType model_type, | |
110 int n, | |
111 const syncable::Id& parent_id) { | |
112 EntryKernel* item = new EntryKernel(); | |
113 item->put(META_HANDLE, n); | |
114 item->put(BASE_VERSION, 10); | |
115 item->put(SERVER_VERSION, 10); | |
116 item->put(IS_DIR, false); | |
117 item->put(ID, GetClientUniqueId(n)); | |
118 item->put(UNIQUE_CLIENT_TAG, base::IntToString(n)); | |
119 | |
120 if (!parent_id.IsNull()) { | |
121 item->put(PARENT_ID, parent_id); | |
122 } | |
123 | |
124 if (model_type != UNSPECIFIED) { | |
125 // Ensure that GetModelType() returns a correct value. | |
126 sync_pb::EntitySpecifics specifics; | |
127 AddDefaultFieldValue(model_type, &specifics); | |
128 item->put(SPECIFICS, specifics); | |
129 } | |
130 | |
131 owned_entry_kernels_.push_back(item); | |
132 return item; | |
133 } | |
134 | |
135 EntryKernel* MakeUniqueClientItem(int n, const syncable::Id& parent_id) { | |
136 return MakeUniqueClientItem(UNSPECIFIED, n, parent_id); | |
137 } | |
138 | |
139 EntryKernel* MakeUniqueClientItem(ModelType model_type, int n) { | |
140 return MakeUniqueClientItem(model_type, n, Id()); | |
141 } | |
142 | |
143 const syncable::Id& IndexKnownModelTypeRootId(ModelType model_type) const { | |
144 return index_.GetModelTypeRootId(model_type); | |
145 } | |
146 | |
147 ParentChildIndex index_; | |
148 | |
149 private: | |
150 std::list<EntryKernel*> owned_entry_kernels_; | |
151 }; | |
152 | |
153 TEST_F(ParentChildIndexTest, TestRootNode) { | |
154 EntryKernel* root = MakeRoot(); | |
155 EXPECT_FALSE(ParentChildIndex::ShouldInclude(root)); | |
156 } | |
157 | |
158 TEST_F(ParentChildIndexTest, TestBookmarkRootFolder) { | |
159 EntryKernel* bm_folder = MakeBookmarkRoot(); | |
160 EXPECT_TRUE(ParentChildIndex::ShouldInclude(bm_folder)); | |
161 | |
162 index_.Insert(bm_folder); | |
163 // Since BOOKMARKS is a hierarchical type, its type root folder shouldn't be | |
164 // tracked by ParentChildIndex. | |
165 EXPECT_EQ(Id(), IndexKnownModelTypeRootId(BOOKMARKS)); | |
166 } | |
167 | |
168 // Tests iteration over a set of siblings. | |
169 TEST_F(ParentChildIndexTest, ChildInsertionAndIteration) { | |
170 EntryKernel* bm_folder = MakeBookmarkRoot(); | |
171 index_.Insert(bm_folder); | |
172 | |
173 // Make some folder and non-folder entries. | |
174 EntryKernel* b1 = MakeBookmark(1, 1, false); | |
175 EntryKernel* b2 = MakeBookmark(2, 2, false); | |
176 EntryKernel* b3 = MakeBookmark(3, 3, true); | |
177 EntryKernel* b4 = MakeBookmark(4, 4, false); | |
178 | |
179 // Insert them out-of-order to test different cases. | |
180 index_.Insert(b3); // Only child. | |
181 index_.Insert(b4); // Right-most child. | |
182 index_.Insert(b1); // Left-most child. | |
183 index_.Insert(b2); // Between existing items. | |
184 | |
185 // Double-check they've been added. | |
186 EXPECT_TRUE(index_.Contains(b1)); | |
187 EXPECT_TRUE(index_.Contains(b2)); | |
188 EXPECT_TRUE(index_.Contains(b3)); | |
189 EXPECT_TRUE(index_.Contains(b4)); | |
190 | |
191 // Check the ordering. | |
192 const OrderedChildSet* children = index_.GetChildren(GetBookmarkRootId()); | |
193 ASSERT_TRUE(children); | |
194 ASSERT_EQ(children->size(), 4UL); | |
195 OrderedChildSet::const_iterator it = children->begin(); | |
196 EXPECT_EQ(*it, b1); | |
197 it++; | |
198 EXPECT_EQ(*it, b2); | |
199 it++; | |
200 EXPECT_EQ(*it, b3); | |
201 it++; | |
202 EXPECT_EQ(*it, b4); | |
203 it++; | |
204 EXPECT_TRUE(it == children->end()); | |
205 } | |
206 | |
207 // Tests iteration when hierarchy is involved. | |
208 TEST_F(ParentChildIndexTest, ChildInsertionAndIterationWithHierarchy) { | |
209 EntryKernel* bm_folder = MakeBookmarkRoot(); | |
210 index_.Insert(bm_folder); | |
211 | |
212 // Just below the root, we have folders f1 and f2. | |
213 EntryKernel* f1 = MakeBookmark(1, 1, false); | |
214 EntryKernel* f2 = MakeBookmark(2, 2, false); | |
215 EntryKernel* f3 = MakeBookmark(3, 3, false); | |
216 | |
217 // Under folder f1, we have two bookmarks. | |
218 EntryKernel* f1_b1 = MakeBookmark(101, 1, false); | |
219 f1_b1->put(PARENT_ID, GetBookmarkId(1)); | |
220 EntryKernel* f1_b2 = MakeBookmark(102, 2, false); | |
221 f1_b2->put(PARENT_ID, GetBookmarkId(1)); | |
222 | |
223 // Under folder f2, there is one bookmark. | |
224 EntryKernel* f2_b1 = MakeBookmark(201, 1, false); | |
225 f2_b1->put(PARENT_ID, GetBookmarkId(2)); | |
226 | |
227 // Under folder f3, there is nothing. | |
228 | |
229 // Insert in a strange order, because we can. | |
230 index_.Insert(f1_b2); | |
231 index_.Insert(f2); | |
232 index_.Insert(f2_b1); | |
233 index_.Insert(f1); | |
234 index_.Insert(f1_b1); | |
235 index_.Insert(f3); | |
236 | |
237 OrderedChildSet::const_iterator it; | |
238 | |
239 // Iterate over children of the bookmark root. | |
240 const OrderedChildSet* top_children = index_.GetChildren(GetBookmarkRootId()); | |
241 ASSERT_TRUE(top_children); | |
242 ASSERT_EQ(top_children->size(), 3UL); | |
243 it = top_children->begin(); | |
244 EXPECT_EQ(*it, f1); | |
245 it++; | |
246 EXPECT_EQ(*it, f2); | |
247 it++; | |
248 EXPECT_EQ(*it, f3); | |
249 it++; | |
250 EXPECT_TRUE(it == top_children->end()); | |
251 | |
252 // Iterate over children of the first folder. | |
253 const OrderedChildSet* f1_children = index_.GetChildren(GetBookmarkId(1)); | |
254 ASSERT_TRUE(f1_children); | |
255 ASSERT_EQ(f1_children->size(), 2UL); | |
256 it = f1_children->begin(); | |
257 EXPECT_EQ(*it, f1_b1); | |
258 it++; | |
259 EXPECT_EQ(*it, f1_b2); | |
260 it++; | |
261 EXPECT_TRUE(it == f1_children->end()); | |
262 | |
263 // Iterate over children of the second folder. | |
264 const OrderedChildSet* f2_children = index_.GetChildren(GetBookmarkId(2)); | |
265 ASSERT_TRUE(f2_children); | |
266 ASSERT_EQ(f2_children->size(), 1UL); | |
267 it = f2_children->begin(); | |
268 EXPECT_EQ(*it, f2_b1); | |
269 it++; | |
270 EXPECT_TRUE(it == f2_children->end()); | |
271 | |
272 // Check for children of the third folder. | |
273 const OrderedChildSet* f3_children = index_.GetChildren(GetBookmarkId(3)); | |
274 EXPECT_FALSE(f3_children); | |
275 } | |
276 | |
277 // Tests removing items. | |
278 TEST_F(ParentChildIndexTest, RemoveWithHierarchy) { | |
279 EntryKernel* bm_folder = MakeBookmarkRoot(); | |
280 index_.Insert(bm_folder); | |
281 | |
282 // Just below the root, we have folders f1 and f2. | |
283 EntryKernel* f1 = MakeBookmark(1, 1, false); | |
284 EntryKernel* f2 = MakeBookmark(2, 2, false); | |
285 EntryKernel* f3 = MakeBookmark(3, 3, false); | |
286 | |
287 // Under folder f1, we have two bookmarks. | |
288 EntryKernel* f1_b1 = MakeBookmark(101, 1, false); | |
289 f1_b1->put(PARENT_ID, GetBookmarkId(1)); | |
290 EntryKernel* f1_b2 = MakeBookmark(102, 2, false); | |
291 f1_b2->put(PARENT_ID, GetBookmarkId(1)); | |
292 | |
293 // Under folder f2, there is one bookmark. | |
294 EntryKernel* f2_b1 = MakeBookmark(201, 1, false); | |
295 f2_b1->put(PARENT_ID, GetBookmarkId(2)); | |
296 | |
297 // Under folder f3, there is nothing. | |
298 | |
299 // Insert in any order. | |
300 index_.Insert(f2_b1); | |
301 index_.Insert(f3); | |
302 index_.Insert(f1_b2); | |
303 index_.Insert(f1); | |
304 index_.Insert(f2); | |
305 index_.Insert(f1_b1); | |
306 | |
307 // Check that all are in the index. | |
308 EXPECT_TRUE(index_.Contains(f1)); | |
309 EXPECT_TRUE(index_.Contains(f2)); | |
310 EXPECT_TRUE(index_.Contains(f3)); | |
311 EXPECT_TRUE(index_.Contains(f1_b1)); | |
312 EXPECT_TRUE(index_.Contains(f1_b2)); | |
313 EXPECT_TRUE(index_.Contains(f2_b1)); | |
314 | |
315 // Remove them all in any order. | |
316 index_.Remove(f3); | |
317 EXPECT_FALSE(index_.Contains(f3)); | |
318 index_.Remove(f1_b2); | |
319 EXPECT_FALSE(index_.Contains(f1_b2)); | |
320 index_.Remove(f2_b1); | |
321 EXPECT_FALSE(index_.Contains(f2_b1)); | |
322 index_.Remove(f1); | |
323 EXPECT_FALSE(index_.Contains(f1)); | |
324 index_.Remove(f2); | |
325 EXPECT_FALSE(index_.Contains(f2)); | |
326 index_.Remove(f1_b1); | |
327 EXPECT_FALSE(index_.Contains(f1_b1)); | |
328 } | |
329 | |
330 // Test that involves two non-ordered items. | |
331 TEST_F(ParentChildIndexTest, UnorderedChildren) { | |
332 // Make two unique client tag items under the root node. | |
333 EntryKernel* u1 = MakeUniqueClientItem(1, syncable::Id::GetRoot()); | |
334 EntryKernel* u2 = MakeUniqueClientItem(2, syncable::Id::GetRoot()); | |
335 | |
336 EXPECT_FALSE(u1->ShouldMaintainPosition()); | |
337 EXPECT_FALSE(u2->ShouldMaintainPosition()); | |
338 | |
339 index_.Insert(u1); | |
340 index_.Insert(u2); | |
341 | |
342 const OrderedChildSet* children = index_.GetChildren(syncable::Id::GetRoot()); | |
343 EXPECT_EQ(children->count(u1), 1UL); | |
344 EXPECT_EQ(children->count(u2), 1UL); | |
345 EXPECT_EQ(children->size(), 2UL); | |
346 } | |
347 | |
348 // Test ordered and non-ordered entries under the same parent. | |
349 // TODO(rlarocque): We should not need to support this. | |
350 TEST_F(ParentChildIndexTest, OrderedAndUnorderedChildren) { | |
351 EntryKernel* bm_folder = MakeBookmarkRoot(); | |
352 index_.Insert(bm_folder); | |
353 | |
354 EntryKernel* b1 = MakeBookmark(1, 1, false); | |
355 EntryKernel* b2 = MakeBookmark(2, 2, false); | |
356 EntryKernel* u1 = MakeUniqueClientItem(1, GetBookmarkRootId()); | |
357 | |
358 index_.Insert(b1); | |
359 index_.Insert(u1); | |
360 index_.Insert(b2); | |
361 | |
362 const OrderedChildSet* children = index_.GetChildren(GetBookmarkRootId()); | |
363 ASSERT_TRUE(children); | |
364 EXPECT_EQ(3UL, children->size()); | |
365 | |
366 // Ensure that the non-positionable item is moved to the far right. | |
367 OrderedChildSet::const_iterator it = children->begin(); | |
368 EXPECT_EQ(*it, b1); | |
369 it++; | |
370 EXPECT_EQ(*it, b2); | |
371 it++; | |
372 EXPECT_EQ(*it, u1); | |
373 it++; | |
374 EXPECT_TRUE(it == children->end()); | |
375 } | |
376 | |
377 TEST_F(ParentChildIndexTest, NodesWithImplicitParentId) { | |
378 syncable::Id type_root_id = syncable::Id::CreateFromServerId("type_root"); | |
379 EntryKernel* type_root = MakeTypeRoot(PREFERENCES, type_root_id); | |
380 index_.Insert(type_root); | |
381 EXPECT_EQ(type_root_id, IndexKnownModelTypeRootId(PREFERENCES)); | |
382 | |
383 // Create entries without parent ID | |
384 EntryKernel* p1 = MakeUniqueClientItem(PREFERENCES, 1); | |
385 EntryKernel* p2 = MakeUniqueClientItem(PREFERENCES, 2); | |
386 | |
387 index_.Insert(p1); | |
388 index_.Insert(p2); | |
389 | |
390 EXPECT_TRUE(index_.Contains(p1)); | |
391 EXPECT_TRUE(index_.Contains(p2)); | |
392 | |
393 // Items should appear under the type root | |
394 const OrderedChildSet* children = index_.GetChildren(type_root); | |
395 ASSERT_TRUE(children); | |
396 EXPECT_EQ(2UL, children->size()); | |
397 | |
398 EXPECT_EQ(2UL, index_.GetSiblings(p1)->size()); | |
399 EXPECT_EQ(2UL, index_.GetSiblings(p2)->size()); | |
400 | |
401 index_.Remove(p1); | |
402 | |
403 EXPECT_FALSE(index_.Contains(p1)); | |
404 EXPECT_TRUE(index_.Contains(p2)); | |
405 children = index_.GetChildren(type_root_id); | |
406 ASSERT_TRUE(children); | |
407 EXPECT_EQ(1UL, children->size()); | |
408 | |
409 index_.Remove(p2); | |
410 | |
411 EXPECT_FALSE(index_.Contains(p2)); | |
412 children = index_.GetChildren(type_root); | |
413 ASSERT_EQ(nullptr, children); | |
414 } | |
415 | |
416 // Test that the removal isn't sensitive to the order (PurgeEntriesWithTypeIn | |
417 // removes items in arbitrary order). | |
418 TEST_F(ParentChildIndexTest, RemoveOutOfOrder) { | |
419 // Insert a type root and two items (with implicit parent ID). | |
420 syncable::Id type_root_id = syncable::Id::CreateFromServerId("type_root"); | |
421 EntryKernel* type_root = MakeTypeRoot(PREFERENCES, type_root_id); | |
422 index_.Insert(type_root); | |
423 EntryKernel* p1 = MakeUniqueClientItem(PREFERENCES, 1); | |
424 EntryKernel* p2 = MakeUniqueClientItem(PREFERENCES, 2); | |
425 index_.Insert(p1); | |
426 index_.Insert(p2); | |
427 | |
428 // Two items expected under the type root. | |
429 const OrderedChildSet* children = index_.GetChildren(type_root); | |
430 ASSERT_TRUE(children); | |
431 EXPECT_EQ(2UL, children->size()); | |
432 | |
433 // Remove all 3 items in arbitrary order. | |
434 index_.Remove(p2); | |
435 index_.Remove(type_root); | |
436 index_.Remove(p1); | |
437 | |
438 EXPECT_EQ(nullptr, index_.GetChildren(type_root)); | |
439 | |
440 // Add a new root and another two items again. | |
441 type_root = MakeTypeRoot(PREFERENCES, type_root_id); | |
442 index_.Insert(type_root); | |
443 | |
444 index_.Insert(MakeUniqueClientItem(PREFERENCES, 3)); | |
445 index_.Insert(MakeUniqueClientItem(PREFERENCES, 4)); | |
446 | |
447 children = index_.GetChildren(type_root); | |
448 ASSERT_TRUE(children); | |
449 // Should have 2 items. If the out of order removal cleared the implicit | |
450 // parent folder ID prematurely, the collection would have 3 items including | |
451 // p1. | |
452 EXPECT_EQ(2UL, children->size()); | |
453 } | |
454 | |
455 // Test that the insert isn't sensitive to the order (Loading entries from | |
456 // Sync DB is done in arbitrary order). | |
457 TEST_F(ParentChildIndexTest, InsertOutOfOrder) { | |
458 // Insert two Preferences entries with implicit parent first | |
459 index_.Insert(MakeUniqueClientItem(PREFERENCES, 1)); | |
460 index_.Insert(MakeUniqueClientItem(PREFERENCES, 2)); | |
461 | |
462 // Then insert the Preferences type root | |
463 syncable::Id type_root_id = syncable::Id::CreateFromServerId("type_root"); | |
464 index_.Insert(MakeTypeRoot(PREFERENCES, type_root_id)); | |
465 | |
466 // The index should still be able to associate Preferences entries | |
467 // with the root. | |
468 const OrderedChildSet* children = index_.GetChildren(type_root_id); | |
469 ASSERT_TRUE(children); | |
470 EXPECT_EQ(2UL, children->size()); | |
471 } | |
472 | |
473 // Test that if for some reason we wind up with multiple type roots, we | |
474 // gracefully handle it and don't allow any new entities to become invisible. | |
475 TEST_F(ParentChildIndexTest, MultipleTypeRoots) { | |
476 // Create the good Preferences type root. | |
477 syncable::Id type_root_id = syncable::Id::CreateFromClientString("type_root"); | |
478 index_.Insert(MakeTypeRoot(PREFERENCES, type_root_id)); | |
479 | |
480 // Then insert the bad Preferences type root | |
481 syncable::Id bad_type_root_id = syncable::Id::CreateFromServerId("bad"); | |
482 index_.Insert(MakeTypeRoot(PREFERENCES, bad_type_root_id)); | |
483 | |
484 // Insert two Preferences entries with implicit parent. | |
485 index_.Insert(MakeUniqueClientItem(PREFERENCES, 1)); | |
486 index_.Insert(MakeUniqueClientItem(PREFERENCES, 2)); | |
487 | |
488 // The index should still be able to associate Preferences entries | |
489 // with the good and bad roots. | |
490 const OrderedChildSet* children = index_.GetChildren(type_root_id); | |
491 ASSERT_TRUE(children); | |
492 EXPECT_EQ(2UL, children->size()); | |
493 const OrderedChildSet* children_bad = index_.GetChildren(bad_type_root_id); | |
494 ASSERT_TRUE(children_bad); | |
495 EXPECT_EQ(2UL, children_bad->size()); | |
496 } | |
497 | |
498 // Test that if for some reason we wind up with multiple type roots, we | |
499 // gracefully handle it and don't allow any new entities to become invisible. | |
500 // Same as above but with the roots created in inverse order. | |
501 TEST_F(ParentChildIndexTest, MultipleTypeRootsInverse) { | |
502 // Create the bad Preferences type root | |
503 syncable::Id bad_type_root_id = syncable::Id::CreateFromServerId("bad"); | |
504 index_.Insert(MakeTypeRoot(PREFERENCES, bad_type_root_id)); | |
505 | |
506 // Then insert the good Preferences type root. | |
507 syncable::Id type_root_id = syncable::Id::CreateFromClientString("type_root"); | |
508 index_.Insert(MakeTypeRoot(PREFERENCES, type_root_id)); | |
509 | |
510 // Insert two Preferences entries with implicit parent. | |
511 index_.Insert(MakeUniqueClientItem(PREFERENCES, 1)); | |
512 index_.Insert(MakeUniqueClientItem(PREFERENCES, 2)); | |
513 | |
514 // The index should still be able to associate Preferences entries | |
515 // with the good root and bad roots. | |
516 const OrderedChildSet* children = index_.GetChildren(type_root_id); | |
517 ASSERT_TRUE(children); | |
518 EXPECT_EQ(2UL, children->size()); | |
519 const OrderedChildSet* children_bad = index_.GetChildren(bad_type_root_id); | |
520 ASSERT_TRUE(children_bad); | |
521 EXPECT_EQ(2UL, children_bad->size()); | |
522 } | |
523 | |
524 } // namespace syncable | |
525 } // namespace syncer | |
526 | |
OLD | NEW |