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