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/model_type_test_util.h"
     14 #include "sync/protocol/bookmark_specifics.pb.h"
     15 #include "sync/protocol/password_specifics.pb.h"
     16 #include "sync/protocol/sync.pb.h"
     17 #include "sync/protocol/sync_enums.pb.h"
     18 #include "sync/sessions/sync_session_context.h"
     19 #include "sync/syncable/blob.h"
     20 #include "sync/syncable/directory.h"
     21 #include "sync/test/engine/mock_connection_manager.h"
     22 #include "sync/test/engine/test_directory_setter_upper.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 
     25 using ::testing::_;
     26 
     27 using sync_pb::ClientToServerMessage;
     28 using sync_pb::CommitResponse_EntryResponse;
     29 using sync_pb::SyncEntity;
     30 
     31 namespace syncer {
     32 
     33 using sessions::SyncSessionContext;
     34 using syncable::Blob;
     35 
     36 class MockDelegate : public sessions::SyncSession::Delegate {
     37  public:
     38    MockDelegate() {}
     39    ~MockDelegate() {}
     40 
     41   MOCK_METHOD0(IsSyncingCurrentlySilenced, bool());
     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 sessions::SyncSessionSnapshot&));
     47   MOCK_METHOD0(OnShouldStopSyncingPermanently, void());
     48   MOCK_METHOD1(OnSilencedUntil, void(const base::TimeTicks&));
     49 };
     50 
     51 // Builds a ClientToServerResponse with some data type ids, including
     52 // invalid ones.  GetTypesToMigrate() should return only the valid
     53 // model types.
     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);
     61   EXPECT_TRUE(
     62       GetTypesToMigrate(response).Equals(
     63           ModelTypeSet(BOOKMARKS, HISTORY_DELETE_DIRECTIVES)));
     64 }
     65 
     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);
     78   EXPECT_TRUE(
     79       error.error_data_types.Equals(
     80           ModelTypeSet(BOOKMARKS, HISTORY_DELETE_DIRECTIVES)));
     81 }
     82 
     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};
     87 
     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]);
     95 
     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));
    102 
    103   EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
    104                                                     test_blob1));
    105   EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
    106                                                      test_blob2));
    107   EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
    108                                                      test_blob3));
    109   EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message2,
    110                                                      test_blob1));
    111   EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message2,
    112                                                     test_blob2));
    113   EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message2,
    114                                                      test_blob3));
    115   EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message3,
    116                                                      test_blob1));
    117   EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message3,
    118                                                      test_blob2));
    119   EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message3,
    120                                                     test_blob3));
    121 
    122   Blob blob1_copy;
    123   EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
    124                                                      blob1_copy));
    125   SyncerProtoUtil::CopyProtoBytesIntoBlob(test_message1, &blob1_copy);
    126   EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(test_message1,
    127                                                     blob1_copy));
    128 
    129   std::string message2_copy;
    130   EXPECT_FALSE(SyncerProtoUtil::ProtoBytesEqualsBlob(message2_copy,
    131                                                      test_blob2));
    132   SyncerProtoUtil::CopyBlobIntoProtoBytes(test_blob2, &message2_copy);
    133   EXPECT_TRUE(SyncerProtoUtil::ProtoBytesEqualsBlob(message2_copy,
    134                                                     test_blob2));
    135 }
    136 
    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;
    142 
    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);
    146 
    147   const std::string name_a =
    148       SyncerProtoUtil::NameFromSyncEntity(one_name_entity);
    149   EXPECT_EQ(one_name_string, name_a);
    150 }
    151 
    152 TEST(SyncerProtoUtil, NameExtractionOneUniqueName) {
    153   SyncEntity one_name_entity;
    154   CommitResponse_EntryResponse one_name_response;
    155 
    156   const std::string one_name_string("Eggheadednesses");
    157 
    158   one_name_entity.set_non_unique_name(one_name_string);
    159   one_name_response.set_non_unique_name(one_name_string);
    160 
    161   const std::string name_a =
    162       SyncerProtoUtil::NameFromSyncEntity(one_name_entity);
    163   EXPECT_EQ(one_name_string, name_a);
    164 }
    165 
    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;
    172 
    173   const std::string neuro("Neuroanatomists");
    174   const std::string oxyphen("Oxyphenbutazone");
    175 
    176   two_name_entity.set_name(oxyphen);
    177   two_name_entity.set_non_unique_name(neuro);
    178 
    179   two_name_response.set_name(oxyphen);
    180   two_name_response.set_non_unique_name(neuro);
    181 
    182   const std::string name_a =
    183       SyncerProtoUtil::NameFromSyncEntity(two_name_entity);
    184   EXPECT_EQ(neuro, name_a);
    185 }
    186 
    187 class SyncerProtoUtilTest : public testing::Test {
    188  public:
    189   virtual void SetUp() {
    190     dir_maker_.SetUp();
    191   }
    192 
    193   virtual void TearDown() {
    194     dir_maker_.TearDown();
    195   }
    196 
    197   syncable::Directory* directory() {
    198     return dir_maker_.directory();
    199   }
    200 
    201  protected:
    202   base::MessageLoop message_loop_;
    203   TestDirectorySetterUpper dir_maker_;
    204 };
    205 
    206 TEST_F(SyncerProtoUtilTest, VerifyResponseBirthday) {
    207   // Both sides empty
    208   EXPECT_TRUE(directory()->store_birthday().empty());
    209   sync_pb::ClientToServerResponse response;
    210   EXPECT_FALSE(SyncerProtoUtil::VerifyResponseBirthday(response, directory()));
    211 
    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");
    216 
    217   // Remote empty, local set.
    218   response.clear_store_birthday();
    219   EXPECT_TRUE(SyncerProtoUtil::VerifyResponseBirthday(response, directory()));
    220   EXPECT_EQ(directory()->store_birthday(), "flan");
    221 
    222   // Doesn't match
    223   response.set_store_birthday("meat");
    224   EXPECT_FALSE(SyncerProtoUtil::VerifyResponseBirthday(response, directory()));
    225 
    226   response.set_error_code(sync_pb::SyncEnums::CLEAR_PENDING);
    227   EXPECT_FALSE(SyncerProtoUtil::VerifyResponseBirthday(response, directory()));
    228 }
    229 
    230 TEST_F(SyncerProtoUtilTest, VerifyDisabledByAdmin) {
    231   // No error code
    232   sync_pb::ClientToServerResponse response;
    233   EXPECT_FALSE(SyncerProtoUtil::IsSyncDisabledByAdmin(response));
    234 
    235   // Has error code, but not disabled
    236   response.set_error_code(sync_pb::SyncEnums::NOT_MY_BIRTHDAY);
    237   EXPECT_FALSE(SyncerProtoUtil::IsSyncDisabledByAdmin(response));
    238 
    239   // Has error code, and is disabled by admin
    240   response.set_error_code(sync_pb::SyncEnums::DISABLED_BY_ADMIN);
    241   EXPECT_TRUE(SyncerProtoUtil::IsSyncDisabledByAdmin(response));
    242 }
    243 
    244 TEST_F(SyncerProtoUtilTest, AddRequestBirthday) {
    245   EXPECT_TRUE(directory()->store_birthday().empty());
    246   ClientToServerMessage msg;
    247   SyncerProtoUtil::AddRequestBirthday(directory(), &msg);
    248   EXPECT_FALSE(msg.has_store_birthday());
    249 
    250   directory()->set_store_birthday("meat");
    251   SyncerProtoUtil::AddRequestBirthday(directory(), &msg);
    252   EXPECT_EQ(msg.store_birthday(), "meat");
    253 }
    254 
    255 class DummyConnectionManager : public ServerConnectionManager {
    256  public:
    257   DummyConnectionManager()
    258       : ServerConnectionManager("unused", 0, false, false),
    259         send_error_(false),
    260         access_denied_(false) {}
    261 
    262   virtual ~DummyConnectionManager() {}
    263   virtual bool PostBufferWithCachedAuth(
    264       PostBufferParams* params,
    265       ScopedServerStatusWatcher* watcher) OVERRIDE {
    266     if (send_error_) {
    267       return false;
    268     }
    269 
    270     sync_pb::ClientToServerResponse response;
    271     if (access_denied_) {
    272       response.set_error_code(sync_pb::SyncEnums::ACCESS_DENIED);
    273     }
    274     response.SerializeToString(&params->buffer_out);
    275 
    276     return true;
    277   }
    278 
    279   void set_send_error(bool send) {
    280     send_error_ = send;
    281   }
    282 
    283   void set_access_denied(bool denied) {
    284     access_denied_ = denied;
    285   }
    286 
    287  private:
    288   bool send_error_;
    289   bool access_denied_;
    290 };
    291 
    292 TEST_F(SyncerProtoUtilTest, PostAndProcessHeaders) {
    293   DummyConnectionManager dcm;
    294   ClientToServerMessage msg;
    295   SyncerProtoUtil::SetProtocolVersion(&msg);
    296   msg.set_share("required");
    297   msg.set_message_contents(ClientToServerMessage::GET_UPDATES);
    298   sync_pb::ClientToServerResponse response;
    299 
    300   dcm.set_send_error(true);
    301   EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, NULL,
    302       msg, &response));
    303 
    304   dcm.set_send_error(false);
    305   EXPECT_TRUE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, NULL,
    306       msg, &response));
    307 
    308   dcm.set_access_denied(true);
    309   EXPECT_FALSE(SyncerProtoUtil::PostAndProcessHeaders(&dcm, NULL,
    310       msg, &response));
    311 }
    312 
    313 }  // namespace syncer
    314