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.
5 // Mock ServerConnectionManager class for use in client regression tests.
7 #include "sync/test/engine/mock_connection_manager.h"
11 #include "base/location.h"
12 #include "base/strings/stringprintf.h"
13 #include "sync/engine/syncer_proto_util.h"
14 #include "sync/protocol/bookmark_specifics.pb.h"
15 #include "sync/syncable/directory.h"
16 #include "sync/syncable/syncable_write_transaction.h"
17 #include "sync/test/engine/test_id_factory.h"
18 #include "testing/gtest/include/gtest/gtest.h"
23 using sync_pb::ClientToServerMessage
;
24 using sync_pb::CommitMessage
;
25 using sync_pb::CommitResponse
;
26 using sync_pb::GetUpdatesMessage
;
27 using sync_pb::SyncEnums
;
31 using syncable::WriteTransaction
;
33 static char kValidAuthToken
[] = "AuthToken";
34 static char kCacheGuid
[] = "kqyg7097kro6GSUod+GSg==";
36 MockConnectionManager::MockConnectionManager(syncable::Directory
* directory
,
37 CancelationSignal
* signal
)
38 : ServerConnectionManager("unused", 0, false, signal
),
39 server_reachable_(true),
40 conflict_all_commits_(false),
41 conflict_n_commits_(0),
43 store_birthday_("Store BDay!"),
44 store_birthday_sent_(false),
46 countdown_to_postbuffer_fail_(0),
47 directory_(directory
),
48 mid_commit_observer_(NULL
),
50 partialThrottling_(false),
51 fail_with_auth_invalid_(false),
52 fail_non_periodic_get_updates_(false),
53 next_position_in_parent_(2),
54 use_legacy_bookmarks_protocol_(false),
55 num_get_updates_requests_(0) {
57 SetAuthToken(kValidAuthToken
);
60 MockConnectionManager::~MockConnectionManager() {
61 EXPECT_TRUE(update_queue_
.empty()) << "Unfetched updates.";
64 void MockConnectionManager::SetCommitTimeRename(const string
& prepend
) {
65 commit_time_rename_prepended_string_
= prepend
;
68 void MockConnectionManager::SetMidCommitCallback(
69 const base::Closure
& callback
) {
70 mid_commit_callback_
= callback
;
73 void MockConnectionManager::SetMidCommitObserver(
74 MockConnectionManager::MidCommitObserver
* observer
) {
75 mid_commit_observer_
= observer
;
78 bool MockConnectionManager::PostBufferToPath(PostBufferParams
* params
,
80 const string
& auth_token
,
81 ScopedServerStatusWatcher
* watcher
) {
82 ClientToServerMessage post
;
83 CHECK(post
.ParseFromString(params
->buffer_in
));
84 CHECK(post
.has_protocol_version());
85 CHECK(post
.has_api_key());
86 CHECK(post
.has_bag_of_chips());
88 requests_
.push_back(post
);
89 client_stuck_
= post
.sync_problem_detected();
90 sync_pb::ClientToServerResponse response
;
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_
);
102 if (auth_token
.empty()) {
103 params
->response
.server_status
= HttpResponse::SYNC_AUTH_ERROR
;
107 if (auth_token
!= kValidAuthToken
) {
108 // Simulate server-side auth failure.
109 params
->response
.server_status
= HttpResponse::SYNC_AUTH_ERROR
;
110 InvalidateAndClearAuthToken();
113 if (--countdown_to_postbuffer_fail_
== 0) {
114 // Fail as countdown hits zero.
115 params
->response
.server_status
= HttpResponse::SYNC_SERVER_ERROR
;
119 if (!server_reachable_
) {
120 params
->response
.server_status
= HttpResponse::CONNECTION_UNAVAILABLE
;
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;
138 EXPECT_TRUE(!store_birthday_sent_
|| post
.has_store_birthday() ||
139 post
.message_contents() == ClientToServerMessage::AUTHENTICATE
||
140 post
.message_contents() ==
141 ClientToServerMessage::CLEAR_SERVER_DATA
);
142 store_birthday_sent_
= true;
144 if (post
.message_contents() == ClientToServerMessage::COMMIT
) {
145 ProcessCommit(&post
, &response
);
146 } else if (post
.message_contents() == ClientToServerMessage::GET_UPDATES
) {
147 ProcessGetUpdates(&post
, &response
);
148 } else if (post
.message_contents() ==
149 ClientToServerMessage::CLEAR_SERVER_DATA
) {
150 ProcessClearServerData(&post
, &response
);
152 EXPECT_TRUE(false) << "Unknown/unsupported ClientToServerMessage";
157 base::AutoLock
lock(response_code_override_lock_
);
159 response
.set_error_code(SyncEnums::THROTTLED
);
163 if (partialThrottling_
) {
164 sync_pb::ClientToServerResponse_Error
* response_error
=
165 response
.mutable_error();
166 response_error
->set_error_type(SyncEnums::PARTIAL_FAILURE
);
167 for (ModelTypeSet::Iterator it
= throttled_type_
.First(); it
.Good();
169 response_error
->add_error_data_type_ids(
170 GetSpecificsFieldNumberFromModelType(it
.Get()));
172 partialThrottling_
= false;
175 if (fail_with_auth_invalid_
)
176 response
.set_error_code(SyncEnums::AUTH_INVALID
);
179 response
.SerializeToString(¶ms
->buffer_out
);
180 if (post
.message_contents() == ClientToServerMessage::COMMIT
&&
181 !mid_commit_callback_
.is_null()) {
182 mid_commit_callback_
.Run();
183 mid_commit_callback_
.Reset();
185 if (mid_commit_observer_
) {
186 mid_commit_observer_
->Observe();
192 sync_pb::GetUpdatesResponse
* MockConnectionManager::GetUpdateResponse() {
193 if (update_queue_
.empty()) {
196 return &update_queue_
.back();
199 void MockConnectionManager::AddDefaultBookmarkData(sync_pb::SyncEntity
* entity
,
201 if (use_legacy_bookmarks_protocol_
) {
202 sync_pb::SyncEntity_BookmarkData
* data
= entity
->mutable_bookmarkdata();
203 data
->set_bookmark_folder(is_folder
);
206 data
->set_bookmark_url("http://google.com");
209 entity
->set_folder(is_folder
);
210 entity
->mutable_specifics()->mutable_bookmark();
212 entity
->mutable_specifics()->mutable_bookmark()->
213 set_url("http://google.com");
218 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateDirectory(
224 const std::string
& originator_cache_guid
,
225 const std::string
& originator_client_item_id
) {
226 return AddUpdateDirectory(TestIdFactory::FromNumber(id
),
227 TestIdFactory::FromNumber(parent_id
),
231 originator_cache_guid
,
232 originator_client_item_id
);
235 void MockConnectionManager::SetGUClientCommand(
236 sync_pb::ClientCommand
* command
) {
237 gu_client_command_
.reset(command
);
240 void MockConnectionManager::SetCommitClientCommand(
241 sync_pb::ClientCommand
* command
) {
242 commit_client_command_
.reset(command
);
245 void MockConnectionManager::SetTransientErrorId(syncable::Id id
) {
246 transient_error_ids_
.push_back(id
);
249 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateBookmark(
255 const string
& originator_client_item_id
,
256 const string
& originator_cache_guid
) {
257 return AddUpdateBookmark(TestIdFactory::FromNumber(id
),
258 TestIdFactory::FromNumber(parent_id
),
262 originator_client_item_id
,
263 originator_cache_guid
);
266 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateSpecifics(
274 const sync_pb::EntitySpecifics
& specifics
) {
275 sync_pb::SyncEntity
* ent
= AddUpdateMeta(
276 TestIdFactory::FromNumber(id
).GetServerId(),
277 TestIdFactory::FromNumber(parent_id
).GetServerId(),
278 name
, version
, sync_ts
);
279 ent
->set_position_in_parent(position
);
280 ent
->mutable_specifics()->CopyFrom(specifics
);
281 ent
->set_folder(is_dir
);
285 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateSpecifics(
293 const sync_pb::EntitySpecifics
& specifics
,
294 const string
& originator_cache_guid
,
295 const string
& originator_client_item_id
) {
296 sync_pb::SyncEntity
* ent
= AddUpdateSpecifics(
297 id
, parent_id
, name
, version
, sync_ts
, is_dir
, position
, specifics
);
298 ent
->set_originator_cache_guid(originator_cache_guid
);
299 ent
->set_originator_client_item_id(originator_client_item_id
);
303 sync_pb::SyncEntity
* MockConnectionManager::SetNigori(
307 const sync_pb::EntitySpecifics
& specifics
) {
308 sync_pb::SyncEntity
* ent
= GetUpdateResponse()->add_entries();
309 ent
->set_id_string(TestIdFactory::FromNumber(id
).GetServerId());
310 ent
->set_parent_id_string(TestIdFactory::FromNumber(0).GetServerId());
311 ent
->set_server_defined_unique_tag(ModelTypeToRootTag(NIGORI
));
312 ent
->set_name("Nigori");
313 ent
->set_non_unique_name("Nigori");
314 ent
->set_version(version
);
315 ent
->set_sync_timestamp(sync_ts
);
316 ent
->set_mtime(sync_ts
);
318 ent
->set_position_in_parent(0);
319 ent
->set_folder(false);
320 ent
->mutable_specifics()->CopyFrom(specifics
);
324 sync_pb::SyncEntity
* MockConnectionManager::AddUpdatePref(
326 const string
& parent_id
,
327 const string
& client_tag
,
330 sync_pb::SyncEntity
* ent
=
331 AddUpdateMeta(id
, parent_id
, " ", version
, sync_ts
);
333 ent
->set_client_defined_unique_tag(client_tag
);
335 sync_pb::EntitySpecifics specifics
;
336 AddDefaultFieldValue(PREFERENCES
, &specifics
);
337 ent
->mutable_specifics()->CopyFrom(specifics
);
342 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateFull(
344 const string
& parent_id
,
349 sync_pb::SyncEntity
* ent
=
350 AddUpdateMeta(id
, parent_id
, name
, version
, sync_ts
);
351 AddDefaultBookmarkData(ent
, is_dir
);
355 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateMeta(
357 const string
& parent_id
,
361 sync_pb::SyncEntity
* ent
= GetUpdateResponse()->add_entries();
362 ent
->set_id_string(id
);
363 ent
->set_parent_id_string(parent_id
);
364 ent
->set_non_unique_name(name
);
366 ent
->set_version(version
);
367 ent
->set_sync_timestamp(sync_ts
);
368 ent
->set_mtime(sync_ts
);
370 ent
->set_position_in_parent(GeneratePositionInParent());
372 // This isn't perfect, but it works well enough. This is an update, which
373 // means the ID is a server ID, which means it never changes. By making
374 // kCacheGuid also never change, we guarantee that the same item always has
375 // the same originator_cache_guid and originator_client_item_id.
377 // Unfortunately, neither this class nor the tests that use it explicitly
378 // track sync entitites, so supporting proper cache guids and client item IDs
379 // would require major refactoring. The ID used here ought to be the "c-"
380 // style ID that was sent up on the commit.
381 ent
->set_originator_cache_guid(kCacheGuid
);
382 ent
->set_originator_client_item_id(id
);
387 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateDirectory(
389 const string
& parent_id
,
393 const std::string
& originator_cache_guid
,
394 const std::string
& originator_client_item_id
) {
395 sync_pb::SyncEntity
* ret
=
396 AddUpdateFull(id
, parent_id
, name
, version
, sync_ts
, true);
397 ret
->set_originator_cache_guid(originator_cache_guid
);
398 ret
->set_originator_client_item_id(originator_client_item_id
);
402 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateBookmark(
404 const string
& parent_id
,
408 const string
& originator_cache_guid
,
409 const string
& originator_client_item_id
) {
410 sync_pb::SyncEntity
* ret
=
411 AddUpdateFull(id
, parent_id
, name
, version
, sync_ts
, false);
412 ret
->set_originator_cache_guid(originator_cache_guid
);
413 ret
->set_originator_client_item_id(originator_client_item_id
);
417 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateFromLastCommit() {
418 EXPECT_EQ(1, last_sent_commit().entries_size());
419 EXPECT_EQ(1, last_commit_response().entryresponse_size());
420 EXPECT_EQ(CommitResponse::SUCCESS
,
421 last_commit_response().entryresponse(0).response_type());
423 if (last_sent_commit().entries(0).deleted()) {
424 ModelType type
= GetModelType(last_sent_commit().entries(0));
425 AddUpdateTombstone(syncable::Id::CreateFromServerId(
426 last_sent_commit().entries(0).id_string()), type
);
428 sync_pb::SyncEntity
* ent
= GetUpdateResponse()->add_entries();
429 ent
->CopyFrom(last_sent_commit().entries(0));
430 ent
->clear_insert_after_item_id();
431 ent
->clear_old_parent_id();
432 ent
->set_position_in_parent(
433 last_commit_response().entryresponse(0).position_in_parent());
435 last_commit_response().entryresponse(0).version());
437 last_commit_response().entryresponse(0).id_string());
439 // This is the same hack as in AddUpdateMeta. See the comment in that
440 // function for more information.
441 ent
->set_originator_cache_guid(kCacheGuid
);
442 ent
->set_originator_client_item_id(
443 last_commit_response().entryresponse(0).id_string());
445 if (last_sent_commit().entries(0).has_unique_position()) {
446 ent
->mutable_unique_position()->CopyFrom(
447 last_sent_commit().entries(0).unique_position());
450 // Tests don't currently care about the following:
451 // parent_id_string, name, non_unique_name.
453 return GetMutableLastUpdate();
456 void MockConnectionManager::AddUpdateTombstone(
457 const syncable::Id
& id
,
459 // Tombstones have only the ID set and dummy values for the required fields.
460 sync_pb::SyncEntity
* ent
= GetUpdateResponse()->add_entries();
461 ent
->set_id_string(id
.GetServerId());
464 ent
->set_deleted(true);
466 // Make sure we can still extract the ModelType from this tombstone.
467 AddDefaultFieldValue(type
, ent
->mutable_specifics());
470 void MockConnectionManager::SetLastUpdateDeleted() {
471 // Tombstones have only the ID set. Wipe anything else.
472 string id_string
= GetMutableLastUpdate()->id_string();
473 ModelType type
= GetModelType(*GetMutableLastUpdate());
474 GetUpdateResponse()->mutable_entries()->RemoveLast();
475 AddUpdateTombstone(syncable::Id::CreateFromServerId(id_string
), type
);
478 void MockConnectionManager::SetLastUpdateOriginatorFields(
479 const string
& client_id
,
480 const string
& entry_id
) {
481 GetMutableLastUpdate()->set_originator_cache_guid(client_id
);
482 GetMutableLastUpdate()->set_originator_client_item_id(entry_id
);
485 void MockConnectionManager::SetLastUpdateServerTag(const string
& tag
) {
486 GetMutableLastUpdate()->set_server_defined_unique_tag(tag
);
489 void MockConnectionManager::SetLastUpdateClientTag(const string
& tag
) {
490 GetMutableLastUpdate()->set_client_defined_unique_tag(tag
);
493 void MockConnectionManager::SetLastUpdatePosition(int64 server_position
) {
494 GetMutableLastUpdate()->set_position_in_parent(server_position
);
497 void MockConnectionManager::SetNewTimestamp(int ts
) {
498 next_token_
= base::StringPrintf("mock connection ts = %d", ts
);
502 void MockConnectionManager::ApplyToken() {
503 if (!update_queue_
.empty()) {
504 GetUpdateResponse()->clear_new_progress_marker();
505 sync_pb::DataTypeProgressMarker
* new_marker
=
506 GetUpdateResponse()->add_new_progress_marker();
507 new_marker
->set_data_type_id(-1); // Invalid -- clients shouldn't see.
508 new_marker
->set_token(next_token_
);
512 void MockConnectionManager::SetChangesRemaining(int64 timestamp
) {
513 GetUpdateResponse()->set_changes_remaining(timestamp
);
516 void MockConnectionManager::ProcessGetUpdates(
517 sync_pb::ClientToServerMessage
* csm
,
518 sync_pb::ClientToServerResponse
* response
) {
519 CHECK(csm
->has_get_updates());
520 ASSERT_EQ(csm
->message_contents(), ClientToServerMessage::GET_UPDATES
);
521 const GetUpdatesMessage
& gu
= csm
->get_updates();
522 num_get_updates_requests_
++;
523 EXPECT_FALSE(gu
.has_from_timestamp());
524 EXPECT_FALSE(gu
.has_requested_types());
526 if (fail_non_periodic_get_updates_
) {
527 EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::PERIODIC
,
528 gu
.caller_info().source());
531 // Verify that the items we're about to send back to the client are of
532 // the types requested by the client. If this fails, it probably indicates
534 EXPECT_TRUE(gu
.fetch_folders());
535 EXPECT_FALSE(gu
.has_requested_types());
536 if (update_queue_
.empty()) {
539 sync_pb::GetUpdatesResponse
* updates
= &update_queue_
.front();
540 for (int i
= 0; i
< updates
->entries_size(); ++i
) {
541 if (!updates
->entries(i
).deleted()) {
542 ModelType entry_type
= GetModelType(updates
->entries(i
));
544 IsModelTypePresentInSpecifics(gu
.from_progress_marker(), entry_type
))
545 << "Syncer did not request updates being provided by the test.";
549 response
->mutable_get_updates()->CopyFrom(*updates
);
551 // Set appropriate progress markers, overriding the value squirreled
552 // away by ApplyToken().
553 std::string token
= response
->get_updates().new_progress_marker(0).token();
554 response
->mutable_get_updates()->clear_new_progress_marker();
555 for (int i
= 0; i
< gu
.from_progress_marker_size(); ++i
) {
556 sync_pb::DataTypeProgressMarker
* new_marker
=
557 response
->mutable_get_updates()->add_new_progress_marker();
558 new_marker
->set_data_type_id(gu
.from_progress_marker(i
).data_type_id());
559 new_marker
->set_token(token
);
562 // Fill the keystore key if requested.
563 if (gu
.need_encryption_key())
564 response
->mutable_get_updates()->add_encryption_keys(keystore_key_
);
566 update_queue_
.pop_front();
568 if (gu_client_command_
) {
569 response
->mutable_client_command()->CopyFrom(*gu_client_command_
.get());
573 void MockConnectionManager::SetKeystoreKey(const std::string
& key
) {
574 // Note: this is not a thread-safe set, ok for now. NOT ok if tests
575 // run the syncer on the background thread while this method is called.
579 bool MockConnectionManager::ShouldConflictThisCommit() {
580 bool conflict
= false;
581 if (conflict_all_commits_
) {
583 } else if (conflict_n_commits_
> 0) {
585 --conflict_n_commits_
;
590 bool MockConnectionManager::ShouldTransientErrorThisId(syncable::Id id
) {
591 return find(transient_error_ids_
.begin(), transient_error_ids_
.end(), id
)
592 != transient_error_ids_
.end();
595 void MockConnectionManager::ProcessCommit(
596 sync_pb::ClientToServerMessage
* csm
,
597 sync_pb::ClientToServerResponse
* response_buffer
) {
598 CHECK(csm
->has_commit());
599 ASSERT_EQ(csm
->message_contents(), ClientToServerMessage::COMMIT
);
600 map
<string
, string
> changed_ids
;
601 const CommitMessage
& commit_message
= csm
->commit();
602 CommitResponse
* commit_response
= response_buffer
->mutable_commit();
603 commit_messages_
.push_back(new CommitMessage
);
604 commit_messages_
.back()->CopyFrom(commit_message
);
605 map
<string
, sync_pb::CommitResponse_EntryResponse
*> response_map
;
606 for (int i
= 0; i
< commit_message
.entries_size() ; i
++) {
607 const sync_pb::SyncEntity
& entry
= commit_message
.entries(i
);
608 CHECK(entry
.has_id_string());
609 string id_string
= entry
.id_string();
610 ASSERT_LT(entry
.name().length(), 256ul) << " name probably too long. True "
611 "server name checking not implemented";
613 if (entry
.version() == 0) {
614 // Relies on our new item string id format. (string representation of a
616 id
= syncable::Id::CreateFromClientString(id_string
);
618 id
= syncable::Id::CreateFromServerId(id_string
);
620 committed_ids_
.push_back(id
);
622 if (response_map
.end() == response_map
.find(id_string
))
623 response_map
[id_string
] = commit_response
->add_entryresponse();
624 sync_pb::CommitResponse_EntryResponse
* er
= response_map
[id_string
];
625 if (ShouldConflictThisCommit()) {
626 er
->set_response_type(CommitResponse::CONFLICT
);
629 if (ShouldTransientErrorThisId(id
)) {
630 er
->set_response_type(CommitResponse::TRANSIENT_ERROR
);
633 er
->set_response_type(CommitResponse::SUCCESS
);
634 er
->set_version(entry
.version() + 1);
635 if (!commit_time_rename_prepended_string_
.empty()) {
636 // Commit time rename sent down from the server.
637 er
->set_name(commit_time_rename_prepended_string_
+ entry
.name());
639 string parent_id_string
= entry
.parent_id_string();
640 // Remap id's we've already assigned.
641 if (changed_ids
.end() != changed_ids
.find(parent_id_string
)) {
642 parent_id_string
= changed_ids
[parent_id_string
];
643 er
->set_parent_id_string(parent_id_string
);
645 if (entry
.has_version() && 0 != entry
.version()) {
646 er
->set_id_string(id_string
); // Allows verification.
648 string new_id
= base::StringPrintf("mock_server:%d", next_new_id_
++);
649 changed_ids
[id_string
] = new_id
;
650 er
->set_id_string(new_id
);
653 commit_responses_
.push_back(new CommitResponse(*commit_response
));
655 if (commit_client_command_
) {
656 response_buffer
->mutable_client_command()->CopyFrom(
657 *commit_client_command_
.get());
661 void MockConnectionManager::ProcessClearServerData(
662 sync_pb::ClientToServerMessage
* csm
,
663 sync_pb::ClientToServerResponse
* response
) {
664 CHECK(csm
->has_clear_server_data());
665 ASSERT_EQ(csm
->message_contents(), ClientToServerMessage::CLEAR_SERVER_DATA
);
666 response
->mutable_clear_server_data();
669 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateDirectory(
671 syncable::Id parent_id
,
675 const string
& originator_cache_guid
,
676 const string
& originator_client_item_id
) {
677 return AddUpdateDirectory(id
.GetServerId(), parent_id
.GetServerId(),
678 name
, version
, sync_ts
, originator_cache_guid
,
679 originator_client_item_id
);
682 sync_pb::SyncEntity
* MockConnectionManager::AddUpdateBookmark(
684 syncable::Id parent_id
,
688 const string
& originator_cache_guid
,
689 const string
& originator_client_item_id
) {
690 return AddUpdateBookmark(id
.GetServerId(), parent_id
.GetServerId(),
691 name
, version
, sync_ts
, originator_cache_guid
,
692 originator_client_item_id
);
695 sync_pb::SyncEntity
* MockConnectionManager::GetMutableLastUpdate() {
696 sync_pb::GetUpdatesResponse
* updates
= GetUpdateResponse();
697 EXPECT_GT(updates
->entries_size(), 0);
698 return updates
->mutable_entries()->Mutable(updates
->entries_size() - 1);
701 void MockConnectionManager::NextUpdateBatch() {
702 update_queue_
.push_back(sync_pb::GetUpdatesResponse::default_instance());
703 SetChangesRemaining(0);
707 const CommitMessage
& MockConnectionManager::last_sent_commit() const {
708 EXPECT_TRUE(!commit_messages_
.empty());
709 return *commit_messages_
.back();
712 const CommitResponse
& MockConnectionManager::last_commit_response() const {
713 EXPECT_TRUE(!commit_responses_
.empty());
714 return *commit_responses_
.back();
717 const sync_pb::ClientToServerMessage
&
718 MockConnectionManager::last_request() const {
719 EXPECT_TRUE(!requests_
.empty());
720 return requests_
.back();
723 const std::vector
<sync_pb::ClientToServerMessage
>&
724 MockConnectionManager::requests() const {
728 bool MockConnectionManager::IsModelTypePresentInSpecifics(
729 const google::protobuf::RepeatedPtrField
<
730 sync_pb::DataTypeProgressMarker
>& filter
,
732 int data_type_id
= GetSpecificsFieldNumberFromModelType(value
);
733 for (int i
= 0; i
< filter
.size(); ++i
) {
734 if (filter
.Get(i
).data_type_id() == data_type_id
) {
741 sync_pb::DataTypeProgressMarker
const*
742 MockConnectionManager::GetProgressMarkerForType(
743 const google::protobuf::RepeatedPtrField
<
744 sync_pb::DataTypeProgressMarker
>& filter
,
746 int data_type_id
= GetSpecificsFieldNumberFromModelType(value
);
747 for (int i
= 0; i
< filter
.size(); ++i
) {
748 if (filter
.Get(i
).data_type_id() == data_type_id
) {
749 return &(filter
.Get(i
));
755 void MockConnectionManager::SetServerReachable() {
756 server_reachable_
= true;
759 void MockConnectionManager::SetServerNotReachable() {
760 server_reachable_
= false;
763 void MockConnectionManager::UpdateConnectionStatus() {
764 if (!server_reachable_
) {
765 server_status_
= HttpResponse::CONNECTION_UNAVAILABLE
;
767 server_status_
= HttpResponse::SERVER_CONNECTION_OK
;
771 void MockConnectionManager::SetServerStatus(
772 HttpResponse::ServerConnectionCode server_status
) {
773 server_status_
= server_status
;
776 } // namespace syncer