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