| OLD | NEW |
| (Empty) |
| 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 // Mock ServerConnectionManager class for use in client regression tests. | |
| 6 | |
| 7 #include "chrome/browser/sync/test/engine/mock_connection_manager.h" | |
| 8 | |
| 9 #include <map> | |
| 10 | |
| 11 #include "base/location.h" | |
| 12 #include "base/stringprintf.h" | |
| 13 #include "chrome/browser/sync/engine/syncer_proto_util.h" | |
| 14 #include "chrome/browser/sync/test/engine/test_id_factory.h" | |
| 15 #include "sync/protocol/bookmark_specifics.pb.h" | |
| 16 #include "testing/gtest/include/gtest/gtest.h" | |
| 17 | |
| 18 using browser_sync::HttpResponse; | |
| 19 using browser_sync::ServerConnectionManager; | |
| 20 using browser_sync::ServerConnectionEventListener; | |
| 21 using browser_sync::ServerConnectionEvent; | |
| 22 using browser_sync::SyncerProtoUtil; | |
| 23 using browser_sync::TestIdFactory; | |
| 24 using std::map; | |
| 25 using std::string; | |
| 26 using sync_pb::ClientToServerMessage; | |
| 27 using sync_pb::ClientToServerResponse; | |
| 28 using sync_pb::CommitMessage; | |
| 29 using sync_pb::CommitResponse; | |
| 30 using sync_pb::CommitResponse_EntryResponse; | |
| 31 using sync_pb::GetUpdatesMessage; | |
| 32 using sync_pb::SyncEnums; | |
| 33 using sync_pb::SyncEntity; | |
| 34 using syncable::FIRST_REAL_MODEL_TYPE; | |
| 35 using syncable::MODEL_TYPE_COUNT; | |
| 36 using syncable::ModelType; | |
| 37 using syncable::WriteTransaction; | |
| 38 | |
| 39 MockConnectionManager::MockConnectionManager(syncable::Directory* directory) | |
| 40 : ServerConnectionManager("unused", 0, false, "version"), | |
| 41 conflict_all_commits_(false), | |
| 42 conflict_n_commits_(0), | |
| 43 next_new_id_(10000), | |
| 44 store_birthday_("Store BDay!"), | |
| 45 store_birthday_sent_(false), | |
| 46 client_stuck_(false), | |
| 47 commit_time_rename_prepended_string_(""), | |
| 48 fail_next_postbuffer_(false), | |
| 49 directory_(directory), | |
| 50 mid_commit_observer_(NULL), | |
| 51 throttling_(false), | |
| 52 fail_with_auth_invalid_(false), | |
| 53 fail_non_periodic_get_updates_(false), | |
| 54 client_command_(NULL), | |
| 55 next_position_in_parent_(2), | |
| 56 use_legacy_bookmarks_protocol_(false), | |
| 57 num_get_updates_requests_(0) { | |
| 58 server_reachable_ = true; | |
| 59 SetNewTimestamp(0); | |
| 60 } | |
| 61 | |
| 62 MockConnectionManager::~MockConnectionManager() { | |
| 63 EXPECT_TRUE(update_queue_.empty()) << "Unfetched updates."; | |
| 64 } | |
| 65 | |
| 66 void MockConnectionManager::SetCommitTimeRename(string prepend) { | |
| 67 commit_time_rename_prepended_string_ = prepend; | |
| 68 } | |
| 69 | |
| 70 void MockConnectionManager::SetMidCommitCallback( | |
| 71 const base::Closure& callback) { | |
| 72 mid_commit_callback_ = callback; | |
| 73 } | |
| 74 | |
| 75 void MockConnectionManager::SetMidCommitObserver( | |
| 76 MockConnectionManager::MidCommitObserver* observer) { | |
| 77 mid_commit_observer_ = observer; | |
| 78 } | |
| 79 | |
| 80 bool MockConnectionManager::PostBufferToPath(PostBufferParams* params, | |
| 81 const string& path, | |
| 82 const string& auth_token, | |
| 83 browser_sync::ScopedServerStatusWatcher* watcher) { | |
| 84 ClientToServerMessage post; | |
| 85 CHECK(post.ParseFromString(params->buffer_in)); | |
| 86 last_request_.CopyFrom(post); | |
| 87 client_stuck_ = post.sync_problem_detected(); | |
| 88 ClientToServerResponse response; | |
| 89 response.Clear(); | |
| 90 | |
| 91 if (directory_) { | |
| 92 // If the Directory's locked when we do this, it's a problem as in normal | |
| 93 // use this function could take a while to return because it accesses the | |
| 94 // network. As we can't test this we do the next best thing and hang here | |
| 95 // when there's an issue. | |
| 96 CHECK(directory_->good()); | |
| 97 WriteTransaction wt(FROM_HERE, syncable::UNITTEST, directory_); | |
| 98 } | |
| 99 | |
| 100 if (fail_next_postbuffer_) { | |
| 101 fail_next_postbuffer_ = false; | |
| 102 return false; | |
| 103 } | |
| 104 | |
| 105 if (!server_reachable_) { | |
| 106 params->response.server_status = HttpResponse::CONNECTION_UNAVAILABLE; | |
| 107 return false; | |
| 108 } | |
| 109 | |
| 110 // Default to an ok connection. | |
| 111 params->response.server_status = HttpResponse::SERVER_CONNECTION_OK; | |
| 112 response.set_error_code(SyncEnums::SUCCESS); | |
| 113 const string current_store_birthday = store_birthday(); | |
| 114 response.set_store_birthday(current_store_birthday); | |
| 115 if (post.has_store_birthday() && post.store_birthday() != | |
| 116 current_store_birthday) { | |
| 117 response.set_error_code(SyncEnums::NOT_MY_BIRTHDAY); | |
| 118 response.set_error_message("Merry Unbirthday!"); | |
| 119 response.SerializeToString(¶ms->buffer_out); | |
| 120 store_birthday_sent_ = true; | |
| 121 return true; | |
| 122 } | |
| 123 bool result = true; | |
| 124 EXPECT_TRUE(!store_birthday_sent_ || post.has_store_birthday() || | |
| 125 post.message_contents() == ClientToServerMessage::AUTHENTICATE); | |
| 126 store_birthday_sent_ = true; | |
| 127 | |
| 128 if (post.message_contents() == ClientToServerMessage::COMMIT) { | |
| 129 ProcessCommit(&post, &response); | |
| 130 } else if (post.message_contents() == ClientToServerMessage::GET_UPDATES) { | |
| 131 ProcessGetUpdates(&post, &response); | |
| 132 } else if (post.message_contents() == ClientToServerMessage::AUTHENTICATE) { | |
| 133 ProcessAuthenticate(&post, &response, auth_token); | |
| 134 } else if (post.message_contents() == ClientToServerMessage::CLEAR_DATA) { | |
| 135 ProcessClearData(&post, &response); | |
| 136 } else { | |
| 137 EXPECT_TRUE(false) << "Unknown/unsupported ClientToServerMessage"; | |
| 138 return false; | |
| 139 } | |
| 140 if (client_command_.get()) { | |
| 141 response.mutable_client_command()->CopyFrom(*client_command_.get()); | |
| 142 } | |
| 143 | |
| 144 { | |
| 145 base::AutoLock lock(response_code_override_lock_); | |
| 146 if (throttling_) { | |
| 147 response.set_error_code(SyncEnums::THROTTLED); | |
| 148 throttling_ = false; | |
| 149 } | |
| 150 | |
| 151 if (fail_with_auth_invalid_) | |
| 152 response.set_error_code(SyncEnums::AUTH_INVALID); | |
| 153 } | |
| 154 | |
| 155 response.SerializeToString(¶ms->buffer_out); | |
| 156 if (post.message_contents() == ClientToServerMessage::COMMIT && | |
| 157 !mid_commit_callback_.is_null()) { | |
| 158 mid_commit_callback_.Run(); | |
| 159 } | |
| 160 if (mid_commit_observer_) { | |
| 161 mid_commit_observer_->Observe(); | |
| 162 } | |
| 163 | |
| 164 return result; | |
| 165 } | |
| 166 | |
| 167 bool MockConnectionManager::IsServerReachable() { | |
| 168 return true; | |
| 169 } | |
| 170 | |
| 171 bool MockConnectionManager::IsUserAuthenticated() { | |
| 172 return true; | |
| 173 } | |
| 174 | |
| 175 sync_pb::GetUpdatesResponse* MockConnectionManager::GetUpdateResponse() { | |
| 176 if (update_queue_.empty()) { | |
| 177 NextUpdateBatch(); | |
| 178 } | |
| 179 return &update_queue_.back(); | |
| 180 } | |
| 181 | |
| 182 void MockConnectionManager::AddDefaultBookmarkData(sync_pb::SyncEntity* entity, | |
| 183 bool is_folder) { | |
| 184 if (use_legacy_bookmarks_protocol_) { | |
| 185 sync_pb::SyncEntity_BookmarkData* data = entity->mutable_bookmarkdata(); | |
| 186 data->set_bookmark_folder(is_folder); | |
| 187 | |
| 188 if (!is_folder) { | |
| 189 data->set_bookmark_url("http://google.com"); | |
| 190 } | |
| 191 } else { | |
| 192 entity->set_folder(is_folder); | |
| 193 entity->mutable_specifics()->mutable_bookmark(); | |
| 194 if (!is_folder) { | |
| 195 entity->mutable_specifics()->mutable_bookmark()-> | |
| 196 set_url("http://google.com"); | |
| 197 } | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 SyncEntity* MockConnectionManager::AddUpdateDirectory(int id, | |
| 202 int parent_id, | |
| 203 string name, | |
| 204 int64 version, | |
| 205 int64 sync_ts) { | |
| 206 return AddUpdateDirectory(TestIdFactory::FromNumber(id), | |
| 207 TestIdFactory::FromNumber(parent_id), | |
| 208 name, | |
| 209 version, | |
| 210 sync_ts); | |
| 211 } | |
| 212 | |
| 213 sync_pb::ClientCommand* MockConnectionManager::GetNextClientCommand() { | |
| 214 if (!client_command_.get()) | |
| 215 client_command_.reset(new sync_pb::ClientCommand()); | |
| 216 return client_command_.get(); | |
| 217 } | |
| 218 | |
| 219 SyncEntity* MockConnectionManager::AddUpdateBookmark(int id, int parent_id, | |
| 220 string name, int64 version, | |
| 221 int64 sync_ts) { | |
| 222 return AddUpdateBookmark(TestIdFactory::FromNumber(id), | |
| 223 TestIdFactory::FromNumber(parent_id), | |
| 224 name, | |
| 225 version, | |
| 226 sync_ts); | |
| 227 } | |
| 228 | |
| 229 SyncEntity* MockConnectionManager::AddUpdateSpecifics( | |
| 230 int id, int parent_id, string name, int64 version, int64 sync_ts, | |
| 231 bool is_dir, int64 position, const sync_pb::EntitySpecifics& specifics) { | |
| 232 SyncEntity* ent = AddUpdateMeta( | |
| 233 TestIdFactory::FromNumber(id).GetServerId(), | |
| 234 TestIdFactory::FromNumber(parent_id).GetServerId(), | |
| 235 name, version, sync_ts); | |
| 236 ent->set_position_in_parent(position); | |
| 237 ent->mutable_specifics()->CopyFrom(specifics); | |
| 238 ent->set_folder(is_dir); | |
| 239 return ent; | |
| 240 } | |
| 241 | |
| 242 sync_pb::SyncEntity* MockConnectionManager::SetNigori( | |
| 243 int id, int64 version,int64 sync_ts, | |
| 244 const sync_pb::EntitySpecifics& specifics) { | |
| 245 SyncEntity* ent = GetUpdateResponse()->add_entries(); | |
| 246 ent->set_id_string(TestIdFactory::FromNumber(id).GetServerId()); | |
| 247 ent->set_parent_id_string(TestIdFactory::FromNumber(0).GetServerId()); | |
| 248 ent->set_server_defined_unique_tag(syncable::ModelTypeToRootTag( | |
| 249 syncable::NIGORI)); | |
| 250 ent->set_name("Nigori"); | |
| 251 ent->set_non_unique_name("Nigori"); | |
| 252 ent->set_version(version); | |
| 253 ent->set_sync_timestamp(sync_ts); | |
| 254 ent->set_mtime(sync_ts); | |
| 255 ent->set_ctime(1); | |
| 256 ent->set_position_in_parent(0); | |
| 257 ent->set_folder(false); | |
| 258 ent->mutable_specifics()->CopyFrom(specifics); | |
| 259 return ent; | |
| 260 } | |
| 261 | |
| 262 SyncEntity* MockConnectionManager::AddUpdateFull(string id, string parent_id, | |
| 263 string name, int64 version, | |
| 264 int64 sync_ts, bool is_dir) { | |
| 265 SyncEntity* ent = AddUpdateMeta(id, parent_id, name, version, sync_ts); | |
| 266 AddDefaultBookmarkData(ent, is_dir); | |
| 267 return ent; | |
| 268 } | |
| 269 | |
| 270 SyncEntity* MockConnectionManager::AddUpdateMeta(string id, string parent_id, | |
| 271 string name, int64 version, | |
| 272 int64 sync_ts) { | |
| 273 SyncEntity* ent = GetUpdateResponse()->add_entries(); | |
| 274 ent->set_id_string(id); | |
| 275 ent->set_parent_id_string(parent_id); | |
| 276 ent->set_non_unique_name(name); | |
| 277 ent->set_name(name); | |
| 278 ent->set_version(version); | |
| 279 ent->set_sync_timestamp(sync_ts); | |
| 280 ent->set_mtime(sync_ts); | |
| 281 ent->set_ctime(1); | |
| 282 ent->set_position_in_parent(GeneratePositionInParent()); | |
| 283 return ent; | |
| 284 } | |
| 285 | |
| 286 SyncEntity* MockConnectionManager::AddUpdateDirectory(string id, | |
| 287 string parent_id, | |
| 288 string name, | |
| 289 int64 version, | |
| 290 int64 sync_ts) { | |
| 291 return AddUpdateFull(id, parent_id, name, version, sync_ts, true); | |
| 292 } | |
| 293 | |
| 294 SyncEntity* MockConnectionManager::AddUpdateBookmark(string id, | |
| 295 string parent_id, | |
| 296 string name, int64 version, | |
| 297 int64 sync_ts) { | |
| 298 return AddUpdateFull(id, parent_id, name, version, sync_ts, false); | |
| 299 } | |
| 300 | |
| 301 SyncEntity* MockConnectionManager::AddUpdateFromLastCommit() { | |
| 302 EXPECT_EQ(1, last_sent_commit().entries_size()); | |
| 303 EXPECT_EQ(1, last_commit_response().entryresponse_size()); | |
| 304 EXPECT_EQ(CommitResponse::SUCCESS, | |
| 305 last_commit_response().entryresponse(0).response_type()); | |
| 306 | |
| 307 if (last_sent_commit().entries(0).deleted()) { | |
| 308 AddUpdateTombstone(syncable::Id::CreateFromServerId( | |
| 309 last_sent_commit().entries(0).id_string())); | |
| 310 } else { | |
| 311 SyncEntity* ent = GetUpdateResponse()->add_entries(); | |
| 312 ent->CopyFrom(last_sent_commit().entries(0)); | |
| 313 ent->clear_insert_after_item_id(); | |
| 314 ent->clear_old_parent_id(); | |
| 315 ent->set_position_in_parent( | |
| 316 last_commit_response().entryresponse(0).position_in_parent()); | |
| 317 ent->set_version( | |
| 318 last_commit_response().entryresponse(0).version()); | |
| 319 ent->set_id_string( | |
| 320 last_commit_response().entryresponse(0).id_string()); | |
| 321 // Tests don't currently care about the following: | |
| 322 // originator_cache_guid, originator_client_item_id, parent_id_string, | |
| 323 // name, non_unique_name. | |
| 324 } | |
| 325 return GetMutableLastUpdate(); | |
| 326 } | |
| 327 | |
| 328 void MockConnectionManager::AddUpdateTombstone(const syncable::Id& id) { | |
| 329 // Tombstones have only the ID set and dummy values for the required fields. | |
| 330 SyncEntity* ent = GetUpdateResponse()->add_entries(); | |
| 331 ent->set_id_string(id.GetServerId()); | |
| 332 ent->set_version(0); | |
| 333 ent->set_name(""); | |
| 334 ent->set_deleted(true); | |
| 335 } | |
| 336 | |
| 337 void MockConnectionManager::SetLastUpdateDeleted() { | |
| 338 // Tombstones have only the ID set. Wipe anything else. | |
| 339 string id_string = GetMutableLastUpdate()->id_string(); | |
| 340 GetUpdateResponse()->mutable_entries()->RemoveLast(); | |
| 341 AddUpdateTombstone(syncable::Id::CreateFromServerId(id_string)); | |
| 342 } | |
| 343 | |
| 344 void MockConnectionManager::SetLastUpdateOriginatorFields( | |
| 345 const string& client_id, | |
| 346 const string& entry_id) { | |
| 347 GetMutableLastUpdate()->set_originator_cache_guid(client_id); | |
| 348 GetMutableLastUpdate()->set_originator_client_item_id(entry_id); | |
| 349 } | |
| 350 | |
| 351 void MockConnectionManager::SetLastUpdateServerTag(const string& tag) { | |
| 352 GetMutableLastUpdate()->set_server_defined_unique_tag(tag); | |
| 353 } | |
| 354 | |
| 355 void MockConnectionManager::SetLastUpdateClientTag(const string& tag) { | |
| 356 GetMutableLastUpdate()->set_client_defined_unique_tag(tag); | |
| 357 } | |
| 358 | |
| 359 void MockConnectionManager::SetLastUpdatePosition(int64 server_position) { | |
| 360 GetMutableLastUpdate()->set_position_in_parent(server_position); | |
| 361 } | |
| 362 | |
| 363 void MockConnectionManager::SetNewTimestamp(int ts) { | |
| 364 next_token_ = base::StringPrintf("mock connection ts = %d", ts); | |
| 365 ApplyToken(); | |
| 366 } | |
| 367 | |
| 368 void MockConnectionManager::ApplyToken() { | |
| 369 if (!update_queue_.empty()) { | |
| 370 GetUpdateResponse()->clear_new_progress_marker(); | |
| 371 sync_pb::DataTypeProgressMarker* new_marker = | |
| 372 GetUpdateResponse()->add_new_progress_marker(); | |
| 373 new_marker->set_data_type_id(-1); // Invalid -- clients shouldn't see. | |
| 374 new_marker->set_token(next_token_); | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 void MockConnectionManager::SetChangesRemaining(int64 timestamp) { | |
| 379 GetUpdateResponse()->set_changes_remaining(timestamp); | |
| 380 } | |
| 381 | |
| 382 void MockConnectionManager::ProcessGetUpdates(ClientToServerMessage* csm, | |
| 383 ClientToServerResponse* response) { | |
| 384 CHECK(csm->has_get_updates()); | |
| 385 ASSERT_EQ(csm->message_contents(), ClientToServerMessage::GET_UPDATES); | |
| 386 const GetUpdatesMessage& gu = csm->get_updates(); | |
| 387 num_get_updates_requests_++; | |
| 388 EXPECT_FALSE(gu.has_from_timestamp()); | |
| 389 EXPECT_FALSE(gu.has_requested_types()); | |
| 390 | |
| 391 if (fail_non_periodic_get_updates_) { | |
| 392 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::PERIODIC, | |
| 393 gu.caller_info().source()); | |
| 394 } | |
| 395 | |
| 396 // Verify that the GetUpdates filter sent by the Syncer matches the test | |
| 397 // expectation. | |
| 398 for (int i = FIRST_REAL_MODEL_TYPE; i < MODEL_TYPE_COUNT; ++i) { | |
| 399 ModelType model_type = syncable::ModelTypeFromInt(i); | |
| 400 sync_pb::DataTypeProgressMarker const* progress_marker = | |
| 401 GetProgressMarkerForType(gu.from_progress_marker(), model_type); | |
| 402 EXPECT_EQ(expected_filter_.Has(model_type), (progress_marker != NULL)) | |
| 403 << "Syncer requested_types differs from test expectation."; | |
| 404 if (progress_marker) { | |
| 405 EXPECT_EQ((expected_payloads_.count(model_type) > 0 ? | |
| 406 expected_payloads_[model_type] : | |
| 407 std::string()), | |
| 408 progress_marker->notification_hint()); | |
| 409 } | |
| 410 } | |
| 411 | |
| 412 // Verify that the items we're about to send back to the client are of | |
| 413 // the types requested by the client. If this fails, it probably indicates | |
| 414 // a test bug. | |
| 415 EXPECT_TRUE(gu.fetch_folders()); | |
| 416 EXPECT_FALSE(gu.has_requested_types()); | |
| 417 if (update_queue_.empty()) { | |
| 418 GetUpdateResponse(); | |
| 419 } | |
| 420 sync_pb::GetUpdatesResponse* updates = &update_queue_.front(); | |
| 421 for (int i = 0; i < updates->entries_size(); ++i) { | |
| 422 if (!updates->entries(i).deleted()) { | |
| 423 ModelType entry_type = syncable::GetModelType(updates->entries(i)); | |
| 424 EXPECT_TRUE( | |
| 425 IsModelTypePresentInSpecifics(gu.from_progress_marker(), entry_type)) | |
| 426 << "Syncer did not request updates being provided by the test."; | |
| 427 } | |
| 428 } | |
| 429 | |
| 430 response->mutable_get_updates()->CopyFrom(*updates); | |
| 431 | |
| 432 // Set appropriate progress markers, overriding the value squirreled | |
| 433 // away by ApplyToken(). | |
| 434 std::string token = response->get_updates().new_progress_marker(0).token(); | |
| 435 response->mutable_get_updates()->clear_new_progress_marker(); | |
| 436 for (int i = 0; i < gu.from_progress_marker_size(); ++i) { | |
| 437 if (gu.from_progress_marker(i).token() != token) { | |
| 438 sync_pb::DataTypeProgressMarker* new_marker = | |
| 439 response->mutable_get_updates()->add_new_progress_marker(); | |
| 440 new_marker->set_data_type_id(gu.from_progress_marker(i).data_type_id()); | |
| 441 new_marker->set_token(token); | |
| 442 } | |
| 443 } | |
| 444 | |
| 445 update_queue_.pop_front(); | |
| 446 } | |
| 447 | |
| 448 void MockConnectionManager::SetClearUserDataResponseStatus( | |
| 449 sync_pb::SyncEnums::ErrorType errortype ) { | |
| 450 // Note: this is not a thread-safe set, ok for now. NOT ok if tests | |
| 451 // run the syncer on the background thread while this method is called. | |
| 452 clear_user_data_response_errortype_ = errortype; | |
| 453 } | |
| 454 | |
| 455 void MockConnectionManager::ProcessClearData(ClientToServerMessage* csm, | |
| 456 ClientToServerResponse* response) { | |
| 457 CHECK(csm->has_clear_user_data()); | |
| 458 ASSERT_EQ(csm->message_contents(), ClientToServerMessage::CLEAR_DATA); | |
| 459 response->clear_user_data(); | |
| 460 response->set_error_code(clear_user_data_response_errortype_); | |
| 461 } | |
| 462 | |
| 463 void MockConnectionManager::ProcessAuthenticate( | |
| 464 ClientToServerMessage* csm, | |
| 465 ClientToServerResponse* response, | |
| 466 const std::string& auth_token) { | |
| 467 ASSERT_EQ(csm->message_contents(), ClientToServerMessage::AUTHENTICATE); | |
| 468 EXPECT_FALSE(auth_token.empty()); | |
| 469 | |
| 470 if (auth_token != valid_auth_token_) { | |
| 471 response->set_error_code(SyncEnums::AUTH_INVALID); | |
| 472 return; | |
| 473 } | |
| 474 | |
| 475 response->set_error_code(SyncEnums::SUCCESS); | |
| 476 response->mutable_authenticate()->CopyFrom(auth_response_); | |
| 477 auth_response_.Clear(); | |
| 478 } | |
| 479 | |
| 480 void MockConnectionManager::SetAuthenticationResponseInfo( | |
| 481 const std::string& valid_auth_token, | |
| 482 const std::string& user_display_name, | |
| 483 const std::string& user_display_email, | |
| 484 const std::string& user_obfuscated_id) { | |
| 485 valid_auth_token_ = valid_auth_token; | |
| 486 sync_pb::UserIdentification* user = auth_response_.mutable_user(); | |
| 487 user->set_display_name(user_display_name); | |
| 488 user->set_email(user_display_email); | |
| 489 user->set_obfuscated_id(user_obfuscated_id); | |
| 490 } | |
| 491 | |
| 492 bool MockConnectionManager::ShouldConflictThisCommit() { | |
| 493 bool conflict = false; | |
| 494 if (conflict_all_commits_) { | |
| 495 conflict = true; | |
| 496 } else if (conflict_n_commits_ > 0) { | |
| 497 conflict = true; | |
| 498 --conflict_n_commits_; | |
| 499 } | |
| 500 return conflict; | |
| 501 } | |
| 502 | |
| 503 void MockConnectionManager::ProcessCommit(ClientToServerMessage* csm, | |
| 504 ClientToServerResponse* response_buffer) { | |
| 505 CHECK(csm->has_commit()); | |
| 506 ASSERT_EQ(csm->message_contents(), ClientToServerMessage::COMMIT); | |
| 507 map <string, string> changed_ids; | |
| 508 const CommitMessage& commit_message = csm->commit(); | |
| 509 CommitResponse* commit_response = response_buffer->mutable_commit(); | |
| 510 commit_messages_->push_back(new CommitMessage); | |
| 511 commit_messages_->back()->CopyFrom(commit_message); | |
| 512 map<string, CommitResponse_EntryResponse*> response_map; | |
| 513 for (int i = 0; i < commit_message.entries_size() ; i++) { | |
| 514 const sync_pb::SyncEntity& entry = commit_message.entries(i); | |
| 515 CHECK(entry.has_id_string()); | |
| 516 string id = entry.id_string(); | |
| 517 ASSERT_LT(entry.name().length(), 256ul) << " name probably too long. True " | |
| 518 "server name checking not implemented"; | |
| 519 if (entry.version() == 0) { | |
| 520 // Relies on our new item string id format. (string representation of a | |
| 521 // negative number). | |
| 522 committed_ids_.push_back(syncable::Id::CreateFromClientString(id)); | |
| 523 } else { | |
| 524 committed_ids_.push_back(syncable::Id::CreateFromServerId(id)); | |
| 525 } | |
| 526 if (response_map.end() == response_map.find(id)) | |
| 527 response_map[id] = commit_response->add_entryresponse(); | |
| 528 CommitResponse_EntryResponse* er = response_map[id]; | |
| 529 if (ShouldConflictThisCommit()) { | |
| 530 er->set_response_type(CommitResponse::CONFLICT); | |
| 531 continue; | |
| 532 } | |
| 533 er->set_response_type(CommitResponse::SUCCESS); | |
| 534 er->set_version(entry.version() + 1); | |
| 535 if (!commit_time_rename_prepended_string_.empty()) { | |
| 536 // Commit time rename sent down from the server. | |
| 537 er->set_name(commit_time_rename_prepended_string_ + entry.name()); | |
| 538 } | |
| 539 string parent_id = entry.parent_id_string(); | |
| 540 // Remap id's we've already assigned. | |
| 541 if (changed_ids.end() != changed_ids.find(parent_id)) { | |
| 542 parent_id = changed_ids[parent_id]; | |
| 543 er->set_parent_id_string(parent_id); | |
| 544 } | |
| 545 if (entry.has_version() && 0 != entry.version()) { | |
| 546 er->set_id_string(id); // Allows verification. | |
| 547 } else { | |
| 548 string new_id = base::StringPrintf("mock_server:%d", next_new_id_++); | |
| 549 changed_ids[id] = new_id; | |
| 550 er->set_id_string(new_id); | |
| 551 } | |
| 552 } | |
| 553 commit_responses_->push_back(new CommitResponse(*commit_response)); | |
| 554 } | |
| 555 | |
| 556 SyncEntity* MockConnectionManager::AddUpdateDirectory( | |
| 557 syncable::Id id, syncable::Id parent_id, string name, int64 version, | |
| 558 int64 sync_ts) { | |
| 559 return AddUpdateDirectory(id.GetServerId(), parent_id.GetServerId(), | |
| 560 name, version, sync_ts); | |
| 561 } | |
| 562 | |
| 563 SyncEntity* MockConnectionManager::AddUpdateBookmark( | |
| 564 syncable::Id id, syncable::Id parent_id, string name, int64 version, | |
| 565 int64 sync_ts) { | |
| 566 return AddUpdateBookmark(id.GetServerId(), parent_id.GetServerId(), | |
| 567 name, version, sync_ts); | |
| 568 } | |
| 569 | |
| 570 SyncEntity* MockConnectionManager::GetMutableLastUpdate() { | |
| 571 sync_pb::GetUpdatesResponse* updates = GetUpdateResponse(); | |
| 572 EXPECT_GT(updates->entries_size(), 0); | |
| 573 return updates->mutable_entries()->Mutable(updates->entries_size() - 1); | |
| 574 } | |
| 575 | |
| 576 void MockConnectionManager::NextUpdateBatch() { | |
| 577 update_queue_.push_back(sync_pb::GetUpdatesResponse::default_instance()); | |
| 578 SetChangesRemaining(0); | |
| 579 ApplyToken(); | |
| 580 } | |
| 581 | |
| 582 const CommitMessage& MockConnectionManager::last_sent_commit() const { | |
| 583 EXPECT_TRUE(!commit_messages_.empty()); | |
| 584 return *commit_messages_->back(); | |
| 585 } | |
| 586 | |
| 587 const CommitResponse& MockConnectionManager::last_commit_response() const { | |
| 588 EXPECT_TRUE(!commit_responses_.empty()); | |
| 589 return *commit_responses_->back(); | |
| 590 } | |
| 591 | |
| 592 void MockConnectionManager::ThrottleNextRequest( | |
| 593 ResponseCodeOverrideRequestor* visitor) { | |
| 594 base::AutoLock lock(response_code_override_lock_); | |
| 595 throttling_ = true; | |
| 596 if (visitor) | |
| 597 visitor->OnOverrideComplete(); | |
| 598 } | |
| 599 | |
| 600 void MockConnectionManager::FailWithAuthInvalid( | |
| 601 ResponseCodeOverrideRequestor* visitor) { | |
| 602 base::AutoLock lock(response_code_override_lock_); | |
| 603 fail_with_auth_invalid_ = true; | |
| 604 if (visitor) | |
| 605 visitor->OnOverrideComplete(); | |
| 606 } | |
| 607 | |
| 608 void MockConnectionManager::StopFailingWithAuthInvalid( | |
| 609 ResponseCodeOverrideRequestor* visitor) { | |
| 610 base::AutoLock lock(response_code_override_lock_); | |
| 611 fail_with_auth_invalid_ = false; | |
| 612 if (visitor) | |
| 613 visitor->OnOverrideComplete(); | |
| 614 } | |
| 615 | |
| 616 bool MockConnectionManager::IsModelTypePresentInSpecifics( | |
| 617 const google::protobuf::RepeatedPtrField< | |
| 618 sync_pb::DataTypeProgressMarker>& filter, | |
| 619 syncable::ModelType value) { | |
| 620 int data_type_id = syncable::GetSpecificsFieldNumberFromModelType(value); | |
| 621 for (int i = 0; i < filter.size(); ++i) { | |
| 622 if (filter.Get(i).data_type_id() == data_type_id) { | |
| 623 return true; | |
| 624 } | |
| 625 } | |
| 626 return false; | |
| 627 } | |
| 628 | |
| 629 sync_pb::DataTypeProgressMarker const* | |
| 630 MockConnectionManager::GetProgressMarkerForType( | |
| 631 const google::protobuf::RepeatedPtrField< | |
| 632 sync_pb::DataTypeProgressMarker>& filter, | |
| 633 syncable::ModelType value) { | |
| 634 int data_type_id = syncable::GetSpecificsFieldNumberFromModelType(value); | |
| 635 for (int i = 0; i < filter.size(); ++i) { | |
| 636 if (filter.Get(i).data_type_id() == data_type_id) { | |
| 637 return &(filter.Get(i)); | |
| 638 } | |
| 639 } | |
| 640 return NULL; | |
| 641 } | |
| 642 | |
| 643 void MockConnectionManager::SetServerReachable() { | |
| 644 server_status_ = HttpResponse::SERVER_CONNECTION_OK; | |
| 645 server_reachable_ = true; | |
| 646 | |
| 647 FOR_EACH_OBSERVER(ServerConnectionEventListener, listeners_, | |
| 648 OnServerConnectionEvent( | |
| 649 ServerConnectionEvent(server_status_, server_reachable_))); | |
| 650 } | |
| 651 | |
| 652 void MockConnectionManager::SetServerNotReachable() { | |
| 653 server_status_ = HttpResponse::CONNECTION_UNAVAILABLE; | |
| 654 server_reachable_ = false; | |
| 655 | |
| 656 FOR_EACH_OBSERVER(ServerConnectionEventListener, listeners_, | |
| 657 OnServerConnectionEvent( | |
| 658 ServerConnectionEvent(server_status_, server_reachable_))); | |
| 659 } | |
| OLD | NEW |