OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "sync/engine/syncer_util.h" | |
6 | |
7 #include <stdint.h> | |
8 | |
9 #include <memory> | |
10 | |
11 #include "base/rand_util.h" | |
12 #include "sync/internal_api/public/base/unique_position.h" | |
13 #include "sync/internal_api/public/test/test_entry_factory.h" | |
14 #include "sync/protocol/sync.pb.h" | |
15 #include "sync/syncable/mutable_entry.h" | |
16 #include "sync/syncable/syncable_write_transaction.h" | |
17 #include "sync/test/engine/test_directory_setter_upper.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 namespace syncer { | |
21 | |
22 class GetUpdatePositionTest : public ::testing::Test { | |
23 public: | |
24 void SetUp() override { | |
25 dir_maker_.SetUp(); | |
26 entry_factory_.reset(new TestEntryFactory(directory())); | |
27 } | |
28 | |
29 void TearDown() override { dir_maker_.TearDown(); } | |
30 | |
31 syncable::Directory* directory() { | |
32 return dir_maker_.directory(); | |
33 } | |
34 | |
35 TestEntryFactory* entry_factory() { | |
36 return entry_factory_.get(); | |
37 } | |
38 | |
39 GetUpdatePositionTest() { | |
40 InitUpdate(); | |
41 | |
42 // Init test_position to some valid position value, but don't assign | |
43 // it to the update just yet. | |
44 std::string pos_suffix = UniquePosition::RandomSuffix(); | |
45 test_position = UniquePosition::InitialPosition(pos_suffix); | |
46 } | |
47 | |
48 void InitUpdate() { | |
49 update.set_id_string("I"); | |
50 update.set_parent_id_string("P"); | |
51 update.set_version(10); | |
52 update.set_mtime(100); | |
53 update.set_ctime(100); | |
54 update.set_deleted(false); | |
55 update.mutable_specifics()->mutable_bookmark()->set_title("Chrome"); | |
56 update.mutable_specifics()->mutable_bookmark()-> | |
57 set_url("https://www.chrome.com"); | |
58 } | |
59 | |
60 void InitSuffixIngredients() { | |
61 update.set_originator_cache_guid("CacheGUID"); | |
62 update.set_originator_client_item_id("OrigID"); | |
63 } | |
64 | |
65 void InitProtoPosition() { | |
66 test_position.ToProto(update.mutable_unique_position()); | |
67 } | |
68 | |
69 void InitInt64Position(int64_t pos_value) { | |
70 update.set_position_in_parent(pos_value); | |
71 } | |
72 | |
73 sync_pb::SyncEntity update; | |
74 UniquePosition test_position; | |
75 base::MessageLoop message_loop_; | |
76 TestDirectorySetterUpper dir_maker_; | |
77 std::unique_ptr<TestEntryFactory> entry_factory_; | |
78 }; | |
79 | |
80 // Generate a suffix from originator client GUID and client-assigned ID. These | |
81 // values should always be present in updates sent down to the client, and | |
82 // combine to create a globally unique value. | |
83 TEST_F(GetUpdatePositionTest, SuffixFromUpdate) { | |
84 InitSuffixIngredients(); | |
85 | |
86 // Expect suffix is valid and consistent. | |
87 std::string suffix1 = GetUniqueBookmarkTagFromUpdate(update); | |
88 std::string suffix2 = GetUniqueBookmarkTagFromUpdate(update); | |
89 | |
90 EXPECT_EQ(suffix1, suffix2); | |
91 EXPECT_TRUE(UniquePosition::IsValidSuffix(suffix1)); | |
92 } | |
93 | |
94 // Receive an update without the ingredients used to make a consistent suffix. | |
95 // | |
96 // The server should never send us an update like this. If it does, | |
97 // that's a bug and it needs to be fixed. Still, we'd like to not | |
98 // crash and have fairly reasonable results in this scenario. | |
99 TEST_F(GetUpdatePositionTest, SuffixFromRandom) { | |
100 // Intentonally do not call InitSuffixIngredients() | |
101 | |
102 // Expect suffix is valid but inconsistent. | |
103 std::string suffix1 = GetUniqueBookmarkTagFromUpdate(update); | |
104 std::string suffix2 = GetUniqueBookmarkTagFromUpdate(update); | |
105 | |
106 EXPECT_NE(suffix1, suffix2); | |
107 EXPECT_TRUE(UniquePosition::IsValidSuffix(suffix1)); | |
108 EXPECT_TRUE(UniquePosition::IsValidSuffix(suffix2)); | |
109 } | |
110 | |
111 TEST_F(GetUpdatePositionTest, FromInt64) { | |
112 InitSuffixIngredients(); | |
113 InitInt64Position(10); | |
114 | |
115 std::string suffix = GetUniqueBookmarkTagFromUpdate(update); | |
116 | |
117 // Expect the result is valid. | |
118 UniquePosition pos = GetUpdatePosition(update, suffix); | |
119 EXPECT_TRUE(pos.IsValid()); | |
120 | |
121 // Expect the position had some effect on ordering. | |
122 EXPECT_TRUE(pos.LessThan( | |
123 UniquePosition::FromInt64(11, UniquePosition::RandomSuffix()))); | |
124 } | |
125 | |
126 TEST_F(GetUpdatePositionTest, FromProto) { | |
127 InitSuffixIngredients(); | |
128 InitInt64Position(10); | |
129 | |
130 std::string suffix = GetUniqueBookmarkTagFromUpdate(update); | |
131 | |
132 // The proto position is not set, so we should get one based on the int64_t. | |
133 // It should not match the proto we defined in the test harness. | |
134 UniquePosition int64_pos = GetUpdatePosition(update, suffix); | |
135 EXPECT_FALSE(int64_pos.Equals(test_position)); | |
136 | |
137 // Move the test harness' position value into the update proto. | |
138 // Expect that it takes precedence over the int64_t-based position. | |
139 InitProtoPosition(); | |
140 UniquePosition pos = GetUpdatePosition(update, suffix); | |
141 EXPECT_TRUE(pos.Equals(test_position)); | |
142 } | |
143 | |
144 TEST_F(GetUpdatePositionTest, FromNothing) { | |
145 // Init none of the ingredients necessary to make a position. | |
146 // Verify we still generate a valid position locally. | |
147 | |
148 std::string suffix = GetUniqueBookmarkTagFromUpdate(update); | |
149 UniquePosition pos = GetUpdatePosition(update, suffix); | |
150 EXPECT_TRUE(pos.IsValid()); | |
151 } | |
152 | |
153 namespace { | |
154 | |
155 sync_pb::EntitySpecifics DefaultBookmarkSpecifics() { | |
156 sync_pb::EntitySpecifics result; | |
157 AddDefaultFieldValue(BOOKMARKS, &result); | |
158 return result; | |
159 } | |
160 | |
161 } // namespace | |
162 | |
163 // Checks that whole cycle of unique_position updating from | |
164 // server works fine and does not browser crash. | |
165 TEST_F(GetUpdatePositionTest, UpdateServerFieldsFromUpdateTest) { | |
166 InitSuffixIngredients(); // Initialize update with valid data. | |
167 | |
168 std::string root_server_id = syncable::Id::GetRoot().GetServerId(); | |
169 int64_t handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( | |
170 "I", DefaultBookmarkSpecifics(), root_server_id); | |
171 | |
172 syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, directory()); | |
173 syncable::MutableEntry target(&trans, syncable::GET_BY_HANDLE, handle); | |
174 | |
175 // Before update, target has invalid bookmark tag and unique position. | |
176 EXPECT_FALSE(UniquePosition::IsValidSuffix(target.GetUniqueBookmarkTag())); | |
177 EXPECT_FALSE(target.GetServerUniquePosition().IsValid()); | |
178 UpdateServerFieldsFromUpdate(&target, update, "name"); | |
179 | |
180 // After update, target has valid bookmark tag and unique position. | |
181 EXPECT_TRUE(UniquePosition::IsValidSuffix(target.GetUniqueBookmarkTag())); | |
182 EXPECT_TRUE(target.GetServerUniquePosition().IsValid()); | |
183 } | |
184 | |
185 // Checks that whole cycle of unique_position updating does not | |
186 // browser crash even data from server is invalid. | |
187 // It looks like server bug, but browser should not crash and work further. | |
188 TEST_F(GetUpdatePositionTest, UpdateServerFieldsFromInvalidUpdateTest) { | |
189 // Do not initialize data in update, update is invalid. | |
190 | |
191 std::string root_server_id = syncable::Id::GetRoot().GetServerId(); | |
192 int64_t handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( | |
193 "I", DefaultBookmarkSpecifics(), root_server_id); | |
194 | |
195 syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, directory()); | |
196 syncable::MutableEntry target(&trans, syncable::GET_BY_HANDLE, handle); | |
197 | |
198 // Before update, target has invalid bookmark tag and unique position. | |
199 EXPECT_FALSE(UniquePosition::IsValidSuffix(target.GetUniqueBookmarkTag())); | |
200 EXPECT_FALSE(target.GetServerUniquePosition().IsValid()); | |
201 UpdateServerFieldsFromUpdate(&target, update, "name"); | |
202 | |
203 // After update, target has valid bookmark tag and unique position. | |
204 EXPECT_TRUE(UniquePosition::IsValidSuffix(target.GetUniqueBookmarkTag())); | |
205 EXPECT_TRUE(target.GetServerUniquePosition().IsValid()); | |
206 } | |
207 | |
208 TEST_F(GetUpdatePositionTest, UpdateServerFieldsFromInvalidUniquePositionTest) { | |
209 InitSuffixIngredients(); // Initialize update with valid data. | |
210 sync_pb::SyncEntity invalid_update(update); | |
211 | |
212 // Create and Setup an invalid position | |
213 sync_pb::UniquePosition* invalid_position = new sync_pb::UniquePosition(); | |
214 invalid_position->set_value(""); | |
215 invalid_update.set_allocated_unique_position(invalid_position); | |
216 | |
217 std::string root_server_id = syncable::Id::GetRoot().GetServerId(); | |
218 int64_t handle = entry_factory()->CreateUnappliedNewBookmarkItemWithParent( | |
219 "I", DefaultBookmarkSpecifics(), root_server_id); | |
220 | |
221 syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, directory()); | |
222 syncable::MutableEntry target(&trans, syncable::GET_BY_HANDLE, handle); | |
223 | |
224 // Before update, target has invalid bookmark tag and unique position. | |
225 EXPECT_FALSE(UniquePosition::IsValidSuffix(target.GetUniqueBookmarkTag())); | |
226 EXPECT_FALSE(target.GetServerUniquePosition().IsValid()); | |
227 UpdateServerFieldsFromUpdate(&target, invalid_update, "name"); | |
228 | |
229 // After update, target has valid bookmark tag and unique position. | |
230 EXPECT_TRUE(UniquePosition::IsValidSuffix(target.GetUniqueBookmarkTag())); | |
231 EXPECT_TRUE(target.GetServerUniquePosition().IsValid()); | |
232 } | |
233 | |
234 } // namespace syncer | |
OLD | NEW |