Home | History | Annotate | Download | only in engine
      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 
     26 using ::testing::_;
     27 
     28 using sync_pb::ClientToServerMessage;
     29 using sync_pb::CommitResponse_EntryResponse;
     30 using sync_pb::SyncEntity;
     31 
     32 namespace syncer {
     33 
     34 using sessions::SyncSessionContext;
     35 using syncable::Blob;
     36 
     37 class 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.
     52 TEST(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.
     67 TEST(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 
     81 TEST(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.
    137 TEST(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 
    150 TEST(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.
    167 TEST(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 
    185 class 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 
    204 TEST_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 
    228 TEST_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 
    242 TEST_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 
    253 class 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 
    290 TEST_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