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
3 // found in the LICENSE file.
5 #include "sync/engine/syncer_proto_util.h"
9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h"
11 #include "base/message_loop.h"
12 #include "base/time.h"
13 #include "sync/engine/throttled_data_type_tracker.h"
14 #include "sync/internal_api/public/base/model_type_test_util.h"
15 #include "sync/protocol/bookmark_specifics.pb.h"
16 #include "sync/protocol/password_specifics.pb.h"
17 #include "sync/protocol/sync.pb.h"
18 #include "sync/protocol/sync_enums.pb.h"
19 #include "sync/sessions/sync_session_context.h"
20 #include "sync/syncable/blob.h"
21 #include "sync/syncable/directory.h"
22 #include "sync/test/engine/mock_connection_manager.h"
23 #include "sync/test/engine/test_directory_setter_upper.h"
24 #include "testing/gtest/include/gtest/gtest.h"
28 using sync_pb::ClientToServerMessage
;
29 using sync_pb::CommitResponse_EntryResponse
;
30 using sync_pb::SyncEntity
;
34 using sessions::SyncSessionContext
;
37 class MockDelegate
: public sessions::SyncSession::Delegate
{
42 MOCK_METHOD0(IsSyncingCurrentlySilenced
, bool());
43 MOCK_METHOD1(OnReceivedShortPollIntervalUpdate
, void(const base::TimeDelta
&));
44 MOCK_METHOD1(OnReceivedLongPollIntervalUpdate
,void(const base::TimeDelta
&));
45 MOCK_METHOD1(OnReceivedSessionsCommitDelay
, void(const base::TimeDelta
&));
46 MOCK_METHOD1(OnSyncProtocolError
, void(const sessions::SyncSessionSnapshot
&));
47 MOCK_METHOD0(OnShouldStopSyncingPermanently
, void());
48 MOCK_METHOD1(OnSilencedUntil
, void(const base::TimeTicks
&));
51 // Builds a ClientToServerResponse with some data type ids, including
52 // invalid ones. GetTypesToMigrate() should return only the valid
54 TEST(SyncerProtoUtil
, GetTypesToMigrate
) {
55 sync_pb::ClientToServerResponse response
;
56 response
.add_migrated_data_type_id(
57 GetSpecificsFieldNumberFromModelType(BOOKMARKS
));
58 response
.add_migrated_data_type_id(
59 GetSpecificsFieldNumberFromModelType(HISTORY_DELETE_DIRECTIVES
));
60 response
.add_migrated_data_type_id(-1);
62 GetTypesToMigrate(response
).Equals(
63 ModelTypeSet(BOOKMARKS
, HISTORY_DELETE_DIRECTIVES
)));
66 // Builds a ClientToServerResponse_Error with some error data type
67 // ids, including invalid ones. ConvertErrorPBToLocalType() should
68 // return a SyncProtocolError with only the valid model types.
69 TEST(SyncerProtoUtil
, ConvertErrorPBToLocalType
) {
70 sync_pb::ClientToServerResponse_Error error_pb
;
71 error_pb
.set_error_type(sync_pb::SyncEnums::THROTTLED
);
72 error_pb
.add_error_data_type_ids(
73 GetSpecificsFieldNumberFromModelType(BOOKMARKS
));
74 error_pb
.add_error_data_type_ids(
75 GetSpecificsFieldNumberFromModelType(HISTORY_DELETE_DIRECTIVES
));
76 error_pb
.add_error_data_type_ids(-1);
77 SyncProtocolError error
= ConvertErrorPBToLocalType(error_pb
);
79 error
.error_data_types
.Equals(
80 ModelTypeSet(BOOKMARKS
, HISTORY_DELETE_DIRECTIVES
)));
83 TEST(SyncerProtoUtil
, TestBlobToProtocolBufferBytesUtilityFunctions
) {
84 unsigned char test_data1
[] = {1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 4, 2, 9};
85 unsigned char test_data2
[] = {1, 99, 3, 4, 5, 6, 7, 8, 0, 1, 4, 2, 9};
86 unsigned char test_data3
[] = {99, 2, 3, 4, 5, 6, 7, 8};
88 syncable::Blob test_blob1
, test_blob2
, test_blob3
;
89 for (size_t i
= 0; i
< arraysize(test_data1
); ++i
)
90 test_blob1
.push_back(test_data1
[i
]);
91 for (size_t i
= 0; i
< arraysize(test_data2
); ++i
)
92 test_blob2
.push_back(test_data2
[i
]);
93 for (size_t i
= 0; i
< arraysize(test_data3
); ++i
)
94 test_blob3
.push_back(test_data3
[i
]);
96 std::string
test_message1(reinterpret_cast<char*>(test_data1
),
97 arraysize(test_data1
));
98 std::string
test_message2(reinterpret_cast<char*>(test_data2
),
99 arraysize(test_data2
));
100 std::string
test_message3(reinterpret_cast<char*>(test_data3
),
101 arraysize(test_data3
));
103 EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1
,
105 EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1
,
107 EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1
,
109 EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message2
,
111 EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message2
,
113 EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message2
,
115 EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message3
,
117 EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message3
,
119 EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message3
,
123 EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1
,
125 SyncerProtoUtil::CopyProtoBytesIntoBlob(test_message1
, &blob1_copy
);
126 EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1
,
129 std::string message2_copy
;
130 EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(message2_copy
,
132 SyncerProtoUtil::CopyBlobIntoProtoBytes(test_blob2
, &message2_copy
);
133 EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(message2_copy
,
137 // Tests NameFromSyncEntity and NameFromCommitEntryResponse when only the name
138 // field is provided.
139 TEST(SyncerProtoUtil
, NameExtractionOneName
) {
140 SyncEntity one_name_entity
;
141 CommitResponse_EntryResponse one_name_response
;
143 const std::string
one_name_string("Eggheadednesses");
144 one_name_entity
.set_name(one_name_string
);
145 one_name_response
.set_name(one_name_string
);
147 const std::string name_a
=
148 SyncerProtoUtil::NameFromSyncEntity(one_name_entity
);
149 EXPECT_EQ(one_name_string
, name_a
);
152 TEST(SyncerProtoUtil
, NameExtractionOneUniqueName
) {
153 SyncEntity one_name_entity
;
154 CommitResponse_EntryResponse one_name_response
;
156 const std::string
one_name_string("Eggheadednesses");
158 one_name_entity
.set_non_unique_name(one_name_string
);
159 one_name_response
.set_non_unique_name(one_name_string
);
161 const std::string name_a
=
162 SyncerProtoUtil::NameFromSyncEntity(one_name_entity
);
163 EXPECT_EQ(one_name_string
, name_a
);
166 // Tests NameFromSyncEntity and NameFromCommitEntryResponse when both the name
167 // field and the non_unique_name fields are provided.
168 // Should prioritize non_unique_name.
169 TEST(SyncerProtoUtil
, NameExtractionTwoNames
) {
170 SyncEntity two_name_entity
;
171 CommitResponse_EntryResponse two_name_response
;
173 const std::string
neuro("Neuroanatomists");
174 const std::string
oxyphen("Oxyphenbutazone");
176 two_name_entity
.set_name(oxyphen
);
177 two_name_entity
.set_non_unique_name(neuro
);
179 two_name_response
.set_name(oxyphen
);
180 two_name_response
.set_non_unique_name(neuro
);
182 const std::string name_a
=
183 SyncerProtoUtil::NameFromSyncEntity(two_name_entity
);
184 EXPECT_EQ(neuro
, name_a
);
187 class SyncerProtoUtilTest
: public testing::Test
{
189 virtual void SetUp() {
193 virtual void TearDown() {
194 dir_maker_
.TearDown();
197 syncable::Directory
* directory() {
198 return dir_maker_
.directory();
202 MessageLoop message_loop_
;
203 TestDirectorySetterUpper dir_maker_
;
206 TEST_F(SyncerProtoUtilTest
, VerifyResponseBirthday
) {
208 EXPECT_TRUE(directory()->store_birthday().empty());
209 sync_pb::ClientToServerResponse response
;
210 EXPECT_FALSE(SyncerProtoUtil::VerifyResponseBirthday(response
, directory()));
212 // Remote set, local empty
213 response
.set_store_birthday("flan");
214 EXPECT_TRUE(SyncerProtoUtil::VerifyResponseBirthday(response
, directory()));
215 EXPECT_EQ(directory()->store_birthday(), "flan");
217 // Remote empty, local set.
218 response
.clear_store_birthday();
219 EXPECT_TRUE(SyncerProtoUtil::VerifyResponseBirthday(response
, directory()));
220 EXPECT_EQ(directory()->store_birthday(), "flan");
223 response
.set_store_birthday("meat");
224 EXPECT_FALSE(SyncerProtoUtil::VerifyResponseBirthday(response
, directory()));
226 response
.set_error_code(sync_pb::SyncEnums::CLEAR_PENDING
);
227 EXPECT_FALSE(SyncerProtoUtil::VerifyResponseBirthday(response
, directory()));
230 TEST_F(SyncerProtoUtilTest
, AddRequestBirthday
) {
231 EXPECT_TRUE(directory()->store_birthday().empty());
232 ClientToServerMessage msg
;
233 SyncerProtoUtil::AddRequestBirthday(directory(), &msg
);
234 EXPECT_FALSE(msg
.has_store_birthday());
236 directory()->set_store_birthday("meat");
237 SyncerProtoUtil::AddRequestBirthday(directory(), &msg
);
238 EXPECT_EQ(msg
.store_birthday(), "meat");
241 class DummyConnectionManager
: public ServerConnectionManager
{
243 DummyConnectionManager()
244 : ServerConnectionManager("unused", 0, false),
246 access_denied_(false) {}
248 virtual ~DummyConnectionManager() {}
249 virtual bool PostBufferWithCachedAuth(
250 PostBufferParams
* params
,
251 ScopedServerStatusWatcher
* watcher
) OVERRIDE
{
256 sync_pb::ClientToServerResponse response
;
257 if (access_denied_
) {
258 response
.set_error_code(sync_pb::SyncEnums::ACCESS_DENIED
);
260 response
.SerializeToString(¶ms
->buffer_out
);
265 void set_send_error(bool send
) {
269 void set_access_denied(bool denied
) {
270 access_denied_
= denied
;
278 TEST_F(SyncerProtoUtilTest
, PostAndProcessHeaders
) {
279 DummyConnectionManager dcm
;
280 ClientToServerMessage msg
;
281 SyncerProtoUtil::SetProtocolVersion(&msg
);
282 msg
.set_share("required");
283 msg
.set_message_contents(ClientToServerMessage::GET_UPDATES
);
284 sync_pb::ClientToServerResponse response
;
286 dcm
.set_send_error(true);
287 EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm
, NULL
,
290 dcm
.set_send_error(false);
291 EXPECT_TRUE(SyncerProtoUtil::PostAndProcessHeaders(&dcm
, NULL
,
294 dcm
.set_access_denied(true);
295 EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm
, NULL
,
299 TEST_F(SyncerProtoUtilTest
, HandleThrottlingWithDatatypes
) {
300 ThrottledDataTypeTracker
tracker(NULL
);
301 SyncProtocolError error
;
302 error
.error_type
= THROTTLED
;
304 types
.Put(BOOKMARKS
);
305 types
.Put(PASSWORDS
);
306 error
.error_data_types
= types
;
308 base::TimeTicks ticks
= base::TimeTicks::FromInternalValue(1);
309 SyncerProtoUtil::HandleThrottleError(error
, ticks
, &tracker
, NULL
);
310 EXPECT_TRUE(tracker
.GetThrottledTypes().Equals(types
));
313 TEST_F(SyncerProtoUtilTest
, HandleThrottlingNoDatatypes
) {
314 ThrottledDataTypeTracker
tracker(NULL
);
315 MockDelegate delegate
;
316 SyncProtocolError error
;
317 error
.error_type
= THROTTLED
;
319 base::TimeTicks ticks
= base::TimeTicks::FromInternalValue(1);
321 EXPECT_CALL(delegate
, OnSilencedUntil(ticks
));
323 SyncerProtoUtil::HandleThrottleError(error
, ticks
, &tracker
, &delegate
);
324 EXPECT_TRUE(tracker
.GetThrottledTypes().Empty());
327 } // namespace syncer