syncer_proto_util_unittest.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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.
4
5#include "sync/engine/syncer_proto_util.h"
6
7#include <string>
8
9#include "base/basictypes.h"
10#include "base/compiler_specific.h"
11#include "base/message_loop/message_loop.h"
12#include "base/time/time.h"
13#include "sync/internal_api/public/base/cancelation_signal.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"
25
26using ::testing::_;
27
28using sync_pb::ClientToServerMessage;
29using sync_pb::CommitResponse_EntryResponse;
30using sync_pb::SyncEntity;
31
32namespace syncer {
33
34using sessions::SyncSessionContext;
35using syncable::Blob;
36
37class MockDelegate : public sessions::SyncSession::Delegate {
38 public:
39   MockDelegate() {}
40   ~MockDelegate() {}
41
42  MOCK_METHOD1(OnReceivedShortPollIntervalUpdate, void(const base::TimeDelta&));
43  MOCK_METHOD1(OnReceivedLongPollIntervalUpdate ,void(const base::TimeDelta&));
44  MOCK_METHOD1(OnReceivedSessionsCommitDelay, void(const base::TimeDelta&));
45  MOCK_METHOD1(OnReceivedClientInvalidationHintBufferSize, void(int));
46  MOCK_METHOD1(OnSyncProtocolError, void(const SyncProtocolError&));
47};
48
49// Builds a ClientToServerResponse with some data type ids, including
50// invalid ones.  GetTypesToMigrate() should return only the valid
51// model types.
52TEST(SyncerProtoUtil, GetTypesToMigrate) {
53  sync_pb::ClientToServerResponse response;
54  response.add_migrated_data_type_id(
55      GetSpecificsFieldNumberFromModelType(BOOKMARKS));
56  response.add_migrated_data_type_id(
57      GetSpecificsFieldNumberFromModelType(HISTORY_DELETE_DIRECTIVES));
58  response.add_migrated_data_type_id(-1);
59  EXPECT_TRUE(
60      GetTypesToMigrate(response).Equals(
61          ModelTypeSet(BOOKMARKS, HISTORY_DELETE_DIRECTIVES)));
62}
63
64// Builds a ClientToServerResponse_Error with some error data type
65// ids, including invalid ones.  ConvertErrorPBToLocalType() should
66// return a SyncProtocolError with only the valid model types.
67TEST(SyncerProtoUtil, ConvertErrorPBToLocalType) {
68  sync_pb::ClientToServerResponse_Error error_pb;
69  error_pb.set_error_type(sync_pb::SyncEnums::THROTTLED);
70  error_pb.add_error_data_type_ids(
71      GetSpecificsFieldNumberFromModelType(BOOKMARKS));
72  error_pb.add_error_data_type_ids(
73      GetSpecificsFieldNumberFromModelType(HISTORY_DELETE_DIRECTIVES));
74  error_pb.add_error_data_type_ids(-1);
75  SyncProtocolError error = ConvertErrorPBToLocalType(error_pb);
76  EXPECT_TRUE(
77      error.error_data_types.Equals(
78          ModelTypeSet(BOOKMARKS, HISTORY_DELETE_DIRECTIVES)));
79}
80
81TEST(SyncerProtoUtil, TestBlobToProtocolBufferBytesUtilityFunctions) {
82  unsigned char test_data1[] = {1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 4, 2, 9};
83  unsigned char test_data2[] = {1, 99, 3, 4, 5, 6, 7, 8, 0, 1, 4, 2, 9};
84  unsigned char test_data3[] = {99, 2, 3, 4, 5, 6, 7, 8};
85
86  syncable::Blob test_blob1, test_blob2, test_blob3;
87  for (size_t i = 0; i < arraysize(test_data1); ++i)
88    test_blob1.push_back(test_data1[i]);
89  for (size_t i = 0; i < arraysize(test_data2); ++i)
90    test_blob2.push_back(test_data2[i]);
91  for (size_t i = 0; i < arraysize(test_data3); ++i)
92    test_blob3.push_back(test_data3[i]);
93
94  std::string test_message1(reinterpret_cast<char*>(test_data1),
95      arraysize(test_data1));
96  std::string test_message2(reinterpret_cast<char*>(test_data2),
97      arraysize(test_data2));
98  std::string test_message3(reinterpret_cast<char*>(test_data3),
99      arraysize(test_data3));
100
101  EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
102                                                    test_blob1));
103  EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
104                                                     test_blob2));
105  EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
106                                                     test_blob3));
107  EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message2,
108                                                     test_blob1));
109  EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message2,
110                                                    test_blob2));
111  EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message2,
112                                                     test_blob3));
113  EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message3,
114                                                     test_blob1));
115  EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message3,
116                                                     test_blob2));
117  EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message3,
118                                                    test_blob3));
119
120  Blob blob1_copy;
121  EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
122                                                     blob1_copy));
123  SyncerProtoUtil::CopyProtoBytesIntoBlob(test_message1, &blob1_copy);
124  EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
125                                                    blob1_copy));
126
127  std::string message2_copy;
128  EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(message2_copy,
129                                                     test_blob2));
130  SyncerProtoUtil::CopyBlobIntoProtoBytes(test_blob2, &message2_copy);
131  EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(message2_copy,
132                                                    test_blob2));
133}
134
135// Tests NameFromSyncEntity and NameFromCommitEntryResponse when only the name
136// field is provided.
137TEST(SyncerProtoUtil, NameExtractionOneName) {
138  SyncEntity one_name_entity;
139  CommitResponse_EntryResponse one_name_response;
140
141  const std::string one_name_string("Eggheadednesses");
142  one_name_entity.set_name(one_name_string);
143  one_name_response.set_name(one_name_string);
144
145  const std::string name_a =
146      SyncerProtoUtil::NameFromSyncEntity(one_name_entity);
147  EXPECT_EQ(one_name_string, name_a);
148}
149
150TEST(SyncerProtoUtil, NameExtractionOneUniqueName) {
151  SyncEntity one_name_entity;
152  CommitResponse_EntryResponse one_name_response;
153
154  const std::string one_name_string("Eggheadednesses");
155
156  one_name_entity.set_non_unique_name(one_name_string);
157  one_name_response.set_non_unique_name(one_name_string);
158
159  const std::string name_a =
160      SyncerProtoUtil::NameFromSyncEntity(one_name_entity);
161  EXPECT_EQ(one_name_string, name_a);
162}
163
164// Tests NameFromSyncEntity and NameFromCommitEntryResponse when both the name
165// field and the non_unique_name fields are provided.
166// Should prioritize non_unique_name.
167TEST(SyncerProtoUtil, NameExtractionTwoNames) {
168  SyncEntity two_name_entity;
169  CommitResponse_EntryResponse two_name_response;
170
171  const std::string neuro("Neuroanatomists");
172  const std::string oxyphen("Oxyphenbutazone");
173
174  two_name_entity.set_name(oxyphen);
175  two_name_entity.set_non_unique_name(neuro);
176
177  two_name_response.set_name(oxyphen);
178  two_name_response.set_non_unique_name(neuro);
179
180  const std::string name_a =
181      SyncerProtoUtil::NameFromSyncEntity(two_name_entity);
182  EXPECT_EQ(neuro, name_a);
183}
184
185class SyncerProtoUtilTest : public testing::Test {
186 public:
187  virtual void SetUp() {
188    dir_maker_.SetUp();
189  }
190
191  virtual void TearDown() {
192    dir_maker_.TearDown();
193  }
194
195  syncable::Directory* directory() {
196    return dir_maker_.directory();
197  }
198
199 protected:
200  base::MessageLoop message_loop_;
201  TestDirectorySetterUpper dir_maker_;
202};
203
204TEST_F(SyncerProtoUtilTest, VerifyResponseBirthday) {
205  // Both sides empty
206  EXPECT_TRUE(directory()->store_birthday().empty());
207  sync_pb::ClientToServerResponse response;
208  EXPECT_FALSE(SyncerProtoUtil::VerifyResponseBirthday(response, directory()));
209
210  // Remote set, local empty
211  response.set_store_birthday("flan");
212  EXPECT_TRUE(SyncerProtoUtil::VerifyResponseBirthday(response, directory()));
213  EXPECT_EQ(directory()->store_birthday(), "flan");
214
215  // Remote empty, local set.
216  response.clear_store_birthday();
217  EXPECT_TRUE(SyncerProtoUtil::VerifyResponseBirthday(response, directory()));
218  EXPECT_EQ(directory()->store_birthday(), "flan");
219
220  // Doesn't match
221  response.set_store_birthday("meat");
222  EXPECT_FALSE(SyncerProtoUtil::VerifyResponseBirthday(response, directory()));
223
224  response.set_error_code(sync_pb::SyncEnums::CLEAR_PENDING);
225  EXPECT_FALSE(SyncerProtoUtil::VerifyResponseBirthday(response, directory()));
226}
227
228TEST_F(SyncerProtoUtilTest, VerifyDisabledByAdmin) {
229  // No error code
230  sync_pb::ClientToServerResponse response;
231  EXPECT_FALSE(SyncerProtoUtil::IsSyncDisabledByAdmin(response));
232
233  // Has error code, but not disabled
234  response.set_error_code(sync_pb::SyncEnums::NOT_MY_BIRTHDAY);
235  EXPECT_FALSE(SyncerProtoUtil::IsSyncDisabledByAdmin(response));
236
237  // Has error code, and is disabled by admin
238  response.set_error_code(sync_pb::SyncEnums::DISABLED_BY_ADMIN);
239  EXPECT_TRUE(SyncerProtoUtil::IsSyncDisabledByAdmin(response));
240}
241
242TEST_F(SyncerProtoUtilTest, AddRequestBirthday) {
243  EXPECT_TRUE(directory()->store_birthday().empty());
244  ClientToServerMessage msg;
245  SyncerProtoUtil::AddRequestBirthday(directory(), &msg);
246  EXPECT_FALSE(msg.has_store_birthday());
247
248  directory()->set_store_birthday("meat");
249  SyncerProtoUtil::AddRequestBirthday(directory(), &msg);
250  EXPECT_EQ(msg.store_birthday(), "meat");
251}
252
253class DummyConnectionManager : public ServerConnectionManager {
254 public:
255  DummyConnectionManager(CancelationSignal* signal)
256      : ServerConnectionManager("unused", 0, false, signal),
257        send_error_(false),
258        access_denied_(false) {}
259
260  virtual ~DummyConnectionManager() {}
261  virtual bool PostBufferWithCachedAuth(
262      PostBufferParams* params,
263      ScopedServerStatusWatcher* watcher) OVERRIDE {
264    if (send_error_) {
265      return false;
266    }
267
268    sync_pb::ClientToServerResponse response;
269    if (access_denied_) {
270      response.set_error_code(sync_pb::SyncEnums::ACCESS_DENIED);
271    }
272    response.SerializeToString(&params->buffer_out);
273
274    return true;
275  }
276
277  void set_send_error(bool send) {
278    send_error_ = send;
279  }
280
281  void set_access_denied(bool denied) {
282    access_denied_ = denied;
283  }
284
285 private:
286  bool send_error_;
287  bool access_denied_;
288};
289
290TEST_F(SyncerProtoUtilTest, PostAndProcessHeaders) {
291  CancelationSignal signal;
292  DummyConnectionManager dcm(&signal);
293  ClientToServerMessage msg;
294  SyncerProtoUtil::SetProtocolVersion(&msg);
295  msg.set_share("required");
296  msg.set_message_contents(ClientToServerMessage::GET_UPDATES);
297  sync_pb::ClientToServerResponse response;
298
299  dcm.set_send_error(true);
300  EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, NULL,
301      msg, &response));
302
303  dcm.set_send_error(false);
304  EXPECT_TRUE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, NULL,
305      msg, &response));
306
307  dcm.set_access_denied(true);
308  EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, NULL,
309      msg, &response));
310}
311
312}  // namespace syncer
313