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(¶ms->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