Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / sync / syncable / parent_child_index_unittest.cc
blob5ae9d27bd87faae8b337265a1fe5c25d53b7534d
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.
5 #include "sync/syncable/parent_child_index.h"
7 #include <list>
9 #include "base/stl_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "sync/syncable/entry_kernel.h"
12 #include "sync/syncable/syncable_util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace syncer {
16 namespace syncable {
18 namespace {
20 static const std::string kCacheGuid = "8HhNIHlEOCGQbIAALr9QEg==";
22 class ParentChildIndexTest : public testing::Test {
23 public:
24 virtual void TearDown() {
25 // To make memory management easier, we take ownership of all EntryKernels
26 // returned by our factory methods and delete them here.
27 STLDeleteElements(&owned_entry_kernels_);
30 // Unfortunately, we can't use the regular Entry factory methods, because the
31 // ParentChildIndex deals in EntryKernels.
33 static syncable::Id GetBookmarkRootId() {
34 return syncable::Id::CreateFromServerId("bookmark_folder");
37 static syncable::Id GetBookmarkId(int n) {
38 return syncable::Id::CreateFromServerId("b" + base::IntToString(n));
41 static syncable::Id GetClientUniqueId(int n) {
42 return syncable::Id::CreateFromServerId("c" + base::IntToString(n));
45 EntryKernel* MakeRoot() {
46 // Mimics the root node.
47 EntryKernel* root = new EntryKernel();
48 root->put(META_HANDLE, 1);
49 root->put(BASE_VERSION, -1);
50 root->put(SERVER_VERSION, 0);
51 root->put(IS_DIR, true);
52 root->put(ID, syncable::Id());
53 root->put(PARENT_ID, syncable::Id());
54 root->put(SERVER_PARENT_ID, syncable::Id());
56 owned_entry_kernels_.push_back(root);
57 return root;
60 EntryKernel* MakeBookmarkRoot() {
61 // Mimics a server-created bookmark folder.
62 EntryKernel* folder = new EntryKernel;
63 folder->put(META_HANDLE, 1);
64 folder->put(BASE_VERSION, 9);
65 folder->put(SERVER_VERSION, 9);
66 folder->put(IS_DIR, true);
67 folder->put(ID, GetBookmarkRootId());
68 folder->put(SERVER_PARENT_ID, syncable::Id());
69 folder->put(PARENT_ID, syncable::Id());
70 folder->put(UNIQUE_SERVER_TAG, "google_chrome_bookmarks");
72 owned_entry_kernels_.push_back(folder);
73 return folder;
76 EntryKernel* MakeBookmark(int n, int pos, bool is_dir) {
77 // Mimics a regular bookmark or folder.
78 EntryKernel* bm = new EntryKernel();
79 bm->put(META_HANDLE, n);
80 bm->put(BASE_VERSION, 10);
81 bm->put(SERVER_VERSION, 10);
82 bm->put(IS_DIR, is_dir);
83 bm->put(ID, GetBookmarkId(n));
84 bm->put(PARENT_ID, GetBookmarkRootId());
85 bm->put(SERVER_PARENT_ID, GetBookmarkRootId());
87 bm->put(UNIQUE_BOOKMARK_TAG,
88 syncable::GenerateSyncableBookmarkHash(kCacheGuid,
89 bm->ref(ID).GetServerId()));
91 UniquePosition unique_pos =
92 UniquePosition::FromInt64(pos, bm->ref(UNIQUE_BOOKMARK_TAG));
93 bm->put(UNIQUE_POSITION, unique_pos);
94 bm->put(SERVER_UNIQUE_POSITION, unique_pos);
96 owned_entry_kernels_.push_back(bm);
97 return bm;
100 EntryKernel* MakeUniqueClientItem(int n) {
101 EntryKernel* item = new EntryKernel();
102 item->put(META_HANDLE, n);
103 item->put(BASE_VERSION, 10);
104 item->put(SERVER_VERSION, 10);
105 item->put(IS_DIR, false);
106 item->put(ID, GetClientUniqueId(n));
107 item->put(PARENT_ID, syncable::Id());
108 item->put(SERVER_PARENT_ID, syncable::Id());
109 item->put(UNIQUE_CLIENT_TAG, base::IntToString(n));
111 owned_entry_kernels_.push_back(item);
112 return item;
115 ParentChildIndex index_;
117 private:
118 std::list<EntryKernel*> owned_entry_kernels_;
121 TEST_F(ParentChildIndexTest, TestRootNode) {
122 EntryKernel* root = MakeRoot();
123 EXPECT_FALSE(ParentChildIndex::ShouldInclude(root));
126 TEST_F(ParentChildIndexTest, TestBookmarkRootFolder) {
127 EntryKernel* bm_folder = MakeBookmarkRoot();
128 EXPECT_TRUE(ParentChildIndex::ShouldInclude(bm_folder));
131 // Tests iteration over a set of siblings.
132 TEST_F(ParentChildIndexTest, ChildInsertionAndIteration) {
133 EntryKernel* bm_folder = MakeBookmarkRoot();
134 index_.Insert(bm_folder);
136 // Make some folder and non-folder entries.
137 EntryKernel* b1 = MakeBookmark(1, 1, false);
138 EntryKernel* b2 = MakeBookmark(2, 2, false);
139 EntryKernel* b3 = MakeBookmark(3, 3, true);
140 EntryKernel* b4 = MakeBookmark(4, 4, false);
142 // Insert them out-of-order to test different cases.
143 index_.Insert(b3); // Only child.
144 index_.Insert(b4); // Right-most child.
145 index_.Insert(b1); // Left-most child.
146 index_.Insert(b2); // Between existing items.
148 // Double-check they've been added.
149 EXPECT_TRUE(index_.Contains(b1));
150 EXPECT_TRUE(index_.Contains(b2));
151 EXPECT_TRUE(index_.Contains(b3));
152 EXPECT_TRUE(index_.Contains(b4));
154 // Check the ordering.
155 const OrderedChildSet* children = index_.GetChildren(GetBookmarkRootId());
156 ASSERT_TRUE(children);
157 ASSERT_EQ(children->size(), 4UL);
158 OrderedChildSet::const_iterator it = children->begin();
159 EXPECT_EQ(*it, b1);
160 it++;
161 EXPECT_EQ(*it, b2);
162 it++;
163 EXPECT_EQ(*it, b3);
164 it++;
165 EXPECT_EQ(*it, b4);
166 it++;
167 EXPECT_TRUE(it == children->end());
170 // Tests iteration when hierarchy is involved.
171 TEST_F(ParentChildIndexTest, ChildInsertionAndIterationWithHierarchy) {
172 EntryKernel* bm_folder = MakeBookmarkRoot();
173 index_.Insert(bm_folder);
175 // Just below the root, we have folders f1 and f2.
176 EntryKernel* f1 = MakeBookmark(1, 1, false);
177 EntryKernel* f2 = MakeBookmark(2, 2, false);
178 EntryKernel* f3 = MakeBookmark(3, 3, false);
180 // Under folder f1, we have two bookmarks.
181 EntryKernel* f1_b1 = MakeBookmark(101, 1, false);
182 f1_b1->put(PARENT_ID, GetBookmarkId(1));
183 EntryKernel* f1_b2 = MakeBookmark(102, 2, false);
184 f1_b2->put(PARENT_ID, GetBookmarkId(1));
186 // Under folder f2, there is one bookmark.
187 EntryKernel* f2_b1 = MakeBookmark(201, 1, false);
188 f2_b1->put(PARENT_ID, GetBookmarkId(2));
190 // Under folder f3, there is nothing.
192 // Insert in a strange order, because we can.
193 index_.Insert(f1_b2);
194 index_.Insert(f2);
195 index_.Insert(f2_b1);
196 index_.Insert(f1);
197 index_.Insert(f1_b1);
198 index_.Insert(f3);
200 OrderedChildSet::const_iterator it;
202 // Iterate over children of the bookmark root.
203 const OrderedChildSet* top_children = index_.GetChildren(GetBookmarkRootId());
204 ASSERT_TRUE(top_children);
205 ASSERT_EQ(top_children->size(), 3UL);
206 it = top_children->begin();
207 EXPECT_EQ(*it, f1);
208 it++;
209 EXPECT_EQ(*it, f2);
210 it++;
211 EXPECT_EQ(*it, f3);
212 it++;
213 EXPECT_TRUE(it == top_children->end());
215 // Iterate over children of the first folder.
216 const OrderedChildSet* f1_children = index_.GetChildren(GetBookmarkId(1));
217 ASSERT_TRUE(f1_children);
218 ASSERT_EQ(f1_children->size(), 2UL);
219 it = f1_children->begin();
220 EXPECT_EQ(*it, f1_b1);
221 it++;
222 EXPECT_EQ(*it, f1_b2);
223 it++;
224 EXPECT_TRUE(it == f1_children->end());
226 // Iterate over children of the second folder.
227 const OrderedChildSet* f2_children = index_.GetChildren(GetBookmarkId(2));
228 ASSERT_TRUE(f2_children);
229 ASSERT_EQ(f2_children->size(), 1UL);
230 it = f2_children->begin();
231 EXPECT_EQ(*it, f2_b1);
232 it++;
233 EXPECT_TRUE(it == f2_children->end());
235 // Check for children of the third folder.
236 const OrderedChildSet* f3_children = index_.GetChildren(GetBookmarkId(3));
237 EXPECT_FALSE(f3_children);
240 // Tests removing items.
241 TEST_F(ParentChildIndexTest, RemoveWithHierarchy) {
242 EntryKernel* bm_folder = MakeBookmarkRoot();
243 index_.Insert(bm_folder);
245 // Just below the root, we have folders f1 and f2.
246 EntryKernel* f1 = MakeBookmark(1, 1, false);
247 EntryKernel* f2 = MakeBookmark(2, 2, false);
248 EntryKernel* f3 = MakeBookmark(3, 3, false);
250 // Under folder f1, we have two bookmarks.
251 EntryKernel* f1_b1 = MakeBookmark(101, 1, false);
252 f1_b1->put(PARENT_ID, GetBookmarkId(1));
253 EntryKernel* f1_b2 = MakeBookmark(102, 2, false);
254 f1_b2->put(PARENT_ID, GetBookmarkId(1));
256 // Under folder f2, there is one bookmark.
257 EntryKernel* f2_b1 = MakeBookmark(201, 1, false);
258 f2_b1->put(PARENT_ID, GetBookmarkId(2));
260 // Under folder f3, there is nothing.
262 // Insert in any order.
263 index_.Insert(f2_b1);
264 index_.Insert(f3);
265 index_.Insert(f1_b2);
266 index_.Insert(f1);
267 index_.Insert(f2);
268 index_.Insert(f1_b1);
270 // Check that all are in the index.
271 EXPECT_TRUE(index_.Contains(f1));
272 EXPECT_TRUE(index_.Contains(f2));
273 EXPECT_TRUE(index_.Contains(f3));
274 EXPECT_TRUE(index_.Contains(f1_b1));
275 EXPECT_TRUE(index_.Contains(f1_b2));
276 EXPECT_TRUE(index_.Contains(f2_b1));
278 // Remove them all in any order.
279 index_.Remove(f3);
280 EXPECT_FALSE(index_.Contains(f3));
281 index_.Remove(f1_b2);
282 EXPECT_FALSE(index_.Contains(f1_b2));
283 index_.Remove(f2_b1);
284 EXPECT_FALSE(index_.Contains(f2_b1));
285 index_.Remove(f1);
286 EXPECT_FALSE(index_.Contains(f1));
287 index_.Remove(f2);
288 EXPECT_FALSE(index_.Contains(f2));
289 index_.Remove(f1_b1);
290 EXPECT_FALSE(index_.Contains(f1_b1));
293 // Test that involves two non-ordered items.
294 TEST_F(ParentChildIndexTest, UnorderedChildren) {
295 // Make two unique client tag items under the root node.
296 EntryKernel* u1 = MakeUniqueClientItem(1);
297 EntryKernel* u2 = MakeUniqueClientItem(2);
299 EXPECT_FALSE(u1->ShouldMaintainPosition());
300 EXPECT_FALSE(u2->ShouldMaintainPosition());
302 index_.Insert(u1);
303 index_.Insert(u2);
305 const OrderedChildSet* children = index_.GetChildren(syncable::Id());
306 EXPECT_EQ(children->count(u1), 1UL);
307 EXPECT_EQ(children->count(u2), 1UL);
308 EXPECT_EQ(children->size(), 2UL);
311 // Test ordered and non-ordered entries under the same parent.
312 // TODO(rlarocque): We should not need to support this.
313 TEST_F(ParentChildIndexTest, OrderedAndUnorderedChildren) {
314 EntryKernel* bm_folder = MakeBookmarkRoot();
315 index_.Insert(bm_folder);
317 EntryKernel* b1 = MakeBookmark(1, 1, false);
318 EntryKernel* b2 = MakeBookmark(2, 2, false);
319 EntryKernel* u1 = MakeUniqueClientItem(1);
320 u1->put(PARENT_ID, GetBookmarkRootId());
322 index_.Insert(b1);
323 index_.Insert(u1);
324 index_.Insert(b2);
326 const OrderedChildSet* children = index_.GetChildren(GetBookmarkRootId());
327 ASSERT_TRUE(children);
328 EXPECT_EQ(children->size(), 3UL);
330 // Ensure that the non-positionable item is moved to the far right.
331 OrderedChildSet::const_iterator it = children->begin();
332 EXPECT_EQ(*it, b1);
333 it++;
334 EXPECT_EQ(*it, b2);
335 it++;
336 EXPECT_EQ(*it, u1);
337 it++;
338 EXPECT_TRUE(it == children->end());
341 } // namespace
342 } // namespace syncable
343 } // namespace syncer