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