Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: components/sync/test/fake_server/fake_server.cc

Issue 2938553003: Revert of [sync] Replace FakeServer's implementation with LoopbackServer invocations. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/sync/test/fake_server/fake_server.h" 5 #include "components/sync/test/fake_server/fake_server.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/guid.h" 12 #include "base/guid.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h" 17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h" 18 #include "base/strings/stringprintf.h"
19 #include "base/synchronization/lock.h" 19 #include "base/synchronization/lock.h"
20 #include "base/threading/thread_restrictions.h" 20 #include "components/sync/test/fake_server/bookmark_entity.h"
21 #include "components/sync/engine_impl/net/server_connection_manager.h" 21 #include "components/sync/test/fake_server/permanent_entity.h"
22 #include "components/sync/test/fake_server/tombstone_entity.h"
23 #include "components/sync/test/fake_server/unique_client_entity.h"
22 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
23 #include "net/http/http_status_code.h" 25 #include "net/http/http_status_code.h"
24 26
25 using std::string; 27 using std::string;
26 using std::vector; 28 using std::vector;
27 using syncer::GetModelType; 29 using syncer::GetModelType;
28 using syncer::GetModelTypeFromSpecifics; 30 using syncer::GetModelTypeFromSpecifics;
29 using syncer::LoopbackServerEntity;
30 using syncer::ModelType; 31 using syncer::ModelType;
31 using syncer::ModelTypeSet; 32 using syncer::ModelTypeSet;
32 33
33 namespace fake_server { 34 namespace fake_server {
34 35
36 class FakeServerEntity;
37
38 namespace {
39
40 // The default keystore key.
41 static const char kDefaultKeystoreKey[] = "1111111111111111";
42
43 // Properties of the bookmark bar permanent folder.
44 static const char kBookmarkBarFolderServerTag[] = "bookmark_bar";
45 static const char kBookmarkBarFolderName[] = "Bookmark Bar";
46
47 // Properties of the other bookmarks permanent folder.
48 static const char kOtherBookmarksFolderServerTag[] = "other_bookmarks";
49 static const char kOtherBookmarksFolderName[] = "Other Bookmarks";
50
51 // Properties of the synced bookmarks permanent folder.
52 static const char kSyncedBookmarksFolderServerTag[] = "synced_bookmarks";
53 static const char kSyncedBookmarksFolderName[] = "Synced Bookmarks";
54
55 // A filter used during GetUpdates calls to determine what information to
56 // send back to the client; filtering out old entities and tracking versions to
57 // use in response progress markers. Note that only the GetUpdatesMessage's
58 // from_progress_marker is used to determine this; legacy fields are ignored.
59 class UpdateSieve {
60 public:
61 explicit UpdateSieve(const sync_pb::GetUpdatesMessage& message)
62 : UpdateSieve(MessageToVersionMap(message)) {}
63 ~UpdateSieve() {}
64
65 // Sets the progress markers in |get_updates_response| based on the highest
66 // version between request progress markers and response entities.
67 void SetProgressMarkers(
68 sync_pb::GetUpdatesResponse* get_updates_response) const {
69 for (const auto& kv : response_version_map_) {
70 sync_pb::DataTypeProgressMarker* new_marker =
71 get_updates_response->add_new_progress_marker();
72 new_marker->set_data_type_id(
73 GetSpecificsFieldNumberFromModelType(kv.first));
74 new_marker->set_token(base::Int64ToString(kv.second));
75 }
76 }
77
78 // Determines whether the server should send an |entity| to the client as
79 // part of a GetUpdatesResponse. Update internal tracking of max versions as a
80 // side effect which will later be used to set response progress markers.
81 bool ClientWantsItem(const FakeServerEntity& entity) {
82 int64_t version = entity.GetVersion();
83 ModelType type = entity.model_type();
84 response_version_map_[type] =
85 std::max(response_version_map_[type], version);
86 auto it = request_version_map_.find(type);
87 return it == request_version_map_.end() ? false : it->second < version;
88 }
89
90 private:
91 using ModelTypeToVersionMap = std::map<ModelType, int64_t>;
92
93 static UpdateSieve::ModelTypeToVersionMap MessageToVersionMap(
94 const sync_pb::GetUpdatesMessage& get_updates_message) {
95 CHECK_GT(get_updates_message.from_progress_marker_size(), 0)
96 << "A GetUpdates request must have at least one progress marker.";
97 ModelTypeToVersionMap request_version_map;
98
99 for (int i = 0; i < get_updates_message.from_progress_marker_size(); i++) {
100 sync_pb::DataTypeProgressMarker marker =
101 get_updates_message.from_progress_marker(i);
102
103 int64_t version = 0;
104 // Let the version remain zero if there is no token or an empty token (the
105 // first request for this type).
106 if (marker.has_token() && !marker.token().empty()) {
107 bool parsed = base::StringToInt64(marker.token(), &version);
108 CHECK(parsed) << "Unable to parse progress marker token.";
109 }
110
111 ModelType model_type =
112 syncer::GetModelTypeFromSpecificsFieldNumber(marker.data_type_id());
113 DCHECK(request_version_map.find(model_type) == request_version_map.end());
114 request_version_map[model_type] = version;
115 }
116 return request_version_map;
117 }
118
119 explicit UpdateSieve(const ModelTypeToVersionMap request_version_map)
120 : request_version_map_(request_version_map),
121 response_version_map_(request_version_map) {}
122
123 // The largest versions the client has seen before this request, and is used
124 // to filter entities to send back to clients. The values in this map are not
125 // updated after being initially set. The presence of a type in this map is a
126 // proxy for the desire to receive results about this type.
127 const ModelTypeToVersionMap request_version_map_;
128
129 // The largest versions seen between client and server, ultimately used to
130 // send progress markers back to the client.
131 ModelTypeToVersionMap response_version_map_;
132 };
133
134 // Returns whether |entity| is deleted or permanent.
135 bool IsDeletedOrPermanent(const FakeServerEntity& entity) {
136 return entity.IsDeleted() || entity.IsPermanent();
137 }
138
139 } // namespace
140
35 FakeServer::FakeServer() 141 FakeServer::FakeServer()
36 : authenticated_(true), 142 : version_(0),
143 store_birthday_(0),
144 authenticated_(true),
37 error_type_(sync_pb::SyncEnums::SUCCESS), 145 error_type_(sync_pb::SyncEnums::SUCCESS),
38 alternate_triggered_errors_(false), 146 alternate_triggered_errors_(false),
39 request_counter_(0), 147 request_counter_(0),
40 network_enabled_(true), 148 network_enabled_(true),
41 weak_ptr_factory_(this) { 149 weak_ptr_factory_(this) {
42 loopback_server_storage_ = base::MakeUnique<base::ScopedTempDir>(); 150 Init();
43 base::ThreadRestrictions::SetIOAllowed(true);
44 DCHECK(loopback_server_storage_->CreateUniqueTempDir());
45 loopback_server_ = base::MakeUnique<syncer::LoopbackServer>(
46 loopback_server_storage_->GetPath().AppendASCII("profile.pb"));
47 loopback_server_->set_observer_for_tests(this);
48 } 151 }
49 152
50 FakeServer::~FakeServer() {} 153 FakeServer::~FakeServer() {}
51 154
155 void FakeServer::Init() {
156 keystore_keys_.push_back(kDefaultKeystoreKey);
157
158 const bool create_result = CreateDefaultPermanentItems();
159 DCHECK(create_result) << "Permanent items were not created successfully.";
160 }
161
162 bool FakeServer::CreatePermanentBookmarkFolder(const std::string& server_tag,
163 const std::string& name) {
164 DCHECK(thread_checker_.CalledOnValidThread());
165 std::unique_ptr<FakeServerEntity> entity =
166 PermanentEntity::Create(syncer::BOOKMARKS, server_tag, name,
167 ModelTypeToRootTag(syncer::BOOKMARKS));
168 if (!entity)
169 return false;
170
171 SaveEntity(std::move(entity));
172 return true;
173 }
174
175 bool FakeServer::CreateDefaultPermanentItems() {
176 // Permanent folders are always required for Bookmarks (hierarchical
177 // structure) and Nigori (data stored in permanent root folder).
178 ModelTypeSet permanent_folder_types =
179 ModelTypeSet(syncer::BOOKMARKS, syncer::NIGORI);
180
181 for (ModelTypeSet::Iterator it = permanent_folder_types.First(); it.Good();
182 it.Inc()) {
183 ModelType model_type = it.Get();
184
185 std::unique_ptr<FakeServerEntity> top_level_entity =
186 PermanentEntity::CreateTopLevel(model_type);
187 if (!top_level_entity) {
188 return false;
189 }
190 SaveEntity(std::move(top_level_entity));
191
192 if (model_type == syncer::BOOKMARKS) {
193 if (!CreatePermanentBookmarkFolder(kBookmarkBarFolderServerTag,
194 kBookmarkBarFolderName))
195 return false;
196 if (!CreatePermanentBookmarkFolder(kOtherBookmarksFolderServerTag,
197 kOtherBookmarksFolderName))
198 return false;
199 }
200 }
201
202 return true;
203 }
204
205 void FakeServer::UpdateEntityVersion(FakeServerEntity* entity) {
206 entity->SetVersion(++version_);
207 }
208
209 void FakeServer::SaveEntity(std::unique_ptr<FakeServerEntity> entity) {
210 UpdateEntityVersion(entity.get());
211 entities_[entity->id()] = std::move(entity);
212 }
213
52 void FakeServer::HandleCommand(const string& request, 214 void FakeServer::HandleCommand(const string& request,
53 const base::Closure& completion_closure, 215 const base::Closure& completion_closure,
54 int* error_code, 216 int* error_code,
55 int* response_code, 217 int* response_code,
56 std::string* response) { 218 std::string* response) {
57 DCHECK(thread_checker_.CalledOnValidThread()); 219 DCHECK(thread_checker_.CalledOnValidThread());
58
59 if (!network_enabled_) { 220 if (!network_enabled_) {
60 *error_code = net::ERR_FAILED; 221 *error_code = net::ERR_FAILED;
61 *response_code = net::ERR_FAILED; 222 *response_code = net::ERR_FAILED;
62 *response = string(); 223 *response = string();
63 completion_closure.Run(); 224 completion_closure.Run();
64 return; 225 return;
65 } 226 }
66 request_counter_++; 227 request_counter_++;
67 228
68 if (!authenticated_) { 229 if (!authenticated_) {
69 *error_code = 0; 230 *error_code = 0;
70 *response_code = net::HTTP_UNAUTHORIZED; 231 *response_code = net::HTTP_UNAUTHORIZED;
71 *response = string(); 232 *response = string();
72 completion_closure.Run(); 233 completion_closure.Run();
73 return; 234 return;
74 } 235 }
75 236
237 sync_pb::ClientToServerMessage message;
238 bool parsed = message.ParseFromString(request);
239 CHECK(parsed) << "Unable to parse the ClientToServerMessage.";
240
76 sync_pb::ClientToServerResponse response_proto; 241 sync_pb::ClientToServerResponse response_proto;
77 *response_code = 200; 242
78 *error_code = 0; 243 if (message.has_store_birthday() &&
79 if (error_type_ != sync_pb::SyncEnums::SUCCESS && 244 message.store_birthday() != GetStoreBirthday()) {
80 ShouldSendTriggeredError()) { 245 response_proto.set_error_code(sync_pb::SyncEnums::NOT_MY_BIRTHDAY);
246 } else if (error_type_ != sync_pb::SyncEnums::SUCCESS &&
247 ShouldSendTriggeredError()) {
81 response_proto.set_error_code(error_type_); 248 response_proto.set_error_code(error_type_);
82 } else if (triggered_actionable_error_.get() && ShouldSendTriggeredError()) { 249 } else if (triggered_actionable_error_.get() && ShouldSendTriggeredError()) {
83 sync_pb::ClientToServerResponse_Error* error = 250 sync_pb::ClientToServerResponse_Error* error =
84 response_proto.mutable_error(); 251 response_proto.mutable_error();
85 error->CopyFrom(*(triggered_actionable_error_.get())); 252 error->CopyFrom(*(triggered_actionable_error_.get()));
86 } else { 253 } else {
87 sync_pb::ClientToServerMessage message; 254 bool success = false;
88 bool parsed = message.ParseFromString(request);
89 CHECK(parsed) << "Unable to parse the ClientToServerMessage.";
90 switch (message.message_contents()) { 255 switch (message.message_contents()) {
91 case sync_pb::ClientToServerMessage::GET_UPDATES: 256 case sync_pb::ClientToServerMessage::GET_UPDATES:
92 last_getupdates_message_ = message; 257 last_getupdates_message_ = message;
258 success = HandleGetUpdatesRequest(message.get_updates(),
259 response_proto.mutable_get_updates());
93 break; 260 break;
94 case sync_pb::ClientToServerMessage::COMMIT: 261 case sync_pb::ClientToServerMessage::COMMIT:
95 last_commit_message_ = message; 262 last_commit_message_ = message;
263 success = HandleCommitRequest(message.commit(),
264 message.invalidator_client_id(),
265 response_proto.mutable_commit());
266 break;
267 case sync_pb::ClientToServerMessage::CLEAR_SERVER_DATA:
268 ClearServerData();
269 response_proto.mutable_clear_server_data();
270 success = true;
96 break; 271 break;
97 default: 272 default:
98 break; 273 *error_code = net::ERR_NOT_IMPLEMENTED;
99 // Don't care. 274 *response_code = 0;
275 *response = string();
276 completion_closure.Run();
277 return;
100 } 278 }
101 279
102 int64_t response_code_large; 280 if (!success) {
103 syncer::HttpResponse::ServerConnectionCode server_status; 281 // TODO(pvalenzuela): Add logging here so that tests have more info about
104 base::ThreadRestrictions::SetIOAllowed(true); 282 // the failure.
105 loopback_server_->HandleCommand(request, &server_status, 283 *error_code = net::ERR_FAILED;
106 &response_code_large, response); 284 *response_code = 0;
107 *response_code = static_cast<int>(response_code_large); 285 *response = string();
108 completion_closure.Run(); 286 completion_closure.Run();
109 return; 287 return;
288 }
289
290 response_proto.set_error_code(sync_pb::SyncEnums::SUCCESS);
110 } 291 }
111 292
112 response_proto.set_store_birthday(loopback_server_->GetStoreBirthday()); 293 response_proto.set_store_birthday(GetStoreBirthday());
294
295 *error_code = 0;
296 *response_code = net::HTTP_OK;
113 *response = response_proto.SerializeAsString(); 297 *response = response_proto.SerializeAsString();
114 completion_closure.Run(); 298 completion_closure.Run();
115 } 299 }
116 300
117 bool FakeServer::GetLastCommitMessage(sync_pb::ClientToServerMessage* message) { 301 bool FakeServer::GetLastCommitMessage(sync_pb::ClientToServerMessage* message) {
118 if (!last_commit_message_.has_commit()) 302 if (!last_commit_message_.has_commit())
119 return false; 303 return false;
120 304
121 message->CopyFrom(last_commit_message_); 305 message->CopyFrom(last_commit_message_);
122 return true; 306 return true;
123 } 307 }
124 308
125 bool FakeServer::GetLastGetUpdatesMessage( 309 bool FakeServer::GetLastGetUpdatesMessage(
126 sync_pb::ClientToServerMessage* message) { 310 sync_pb::ClientToServerMessage* message) {
127 if (!last_getupdates_message_.has_get_updates()) 311 if (!last_getupdates_message_.has_get_updates())
128 return false; 312 return false;
129 313
130 message->CopyFrom(last_getupdates_message_); 314 message->CopyFrom(last_getupdates_message_);
131 return true; 315 return true;
132 } 316 }
133 317
318 bool FakeServer::HandleGetUpdatesRequest(
319 const sync_pb::GetUpdatesMessage& get_updates,
320 sync_pb::GetUpdatesResponse* response) {
321 // TODO(pvalenzuela): Implement batching instead of sending all information
322 // at once.
323 response->set_changes_remaining(0);
324
325 auto sieve = base::MakeUnique<UpdateSieve>(get_updates);
326
327 // This folder is called "Synced Bookmarks" by sync and is renamed
328 // "Mobile Bookmarks" by the mobile client UIs.
329 if (get_updates.create_mobile_bookmarks_folder() &&
330 !CreatePermanentBookmarkFolder(kSyncedBookmarksFolderServerTag,
331 kSyncedBookmarksFolderName)) {
332 return false;
333 }
334
335 bool send_encryption_keys_based_on_nigori = false;
336 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
337 ++it) {
338 const FakeServerEntity& entity = *it->second;
339 if (sieve->ClientWantsItem(entity)) {
340 sync_pb::SyncEntity* response_entity = response->add_entries();
341 entity.SerializeAsProto(response_entity);
342
343 if (entity.model_type() == syncer::NIGORI) {
344 send_encryption_keys_based_on_nigori =
345 response_entity->specifics().nigori().passphrase_type() ==
346 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
347 }
348 }
349 }
350
351 if (send_encryption_keys_based_on_nigori ||
352 get_updates.need_encryption_key()) {
353 for (vector<string>::iterator it = keystore_keys_.begin();
354 it != keystore_keys_.end(); ++it) {
355 response->add_encryption_keys(*it);
356 }
357 }
358
359 sieve->SetProgressMarkers(response);
360 return true;
361 }
362
363 string FakeServer::CommitEntity(
364 const sync_pb::SyncEntity& client_entity,
365 sync_pb::CommitResponse_EntryResponse* entry_response,
366 const string& client_guid,
367 const string& parent_id) {
368 if (client_entity.version() == 0 && client_entity.deleted()) {
369 return string();
370 }
371
372 std::unique_ptr<FakeServerEntity> entity;
373 if (client_entity.deleted()) {
374 entity = TombstoneEntity::Create(client_entity.id_string(),
375 client_entity.client_defined_unique_tag());
376 DeleteChildren(client_entity.id_string());
377 } else if (GetModelType(client_entity) == syncer::NIGORI) {
378 // NIGORI is the only permanent item type that should be updated by the
379 // client.
380 EntityMap::const_iterator iter = entities_.find(client_entity.id_string());
381 CHECK(iter != entities_.end());
382 entity = PermanentEntity::CreateUpdatedNigoriEntity(client_entity,
383 *iter->second);
384 } else if (client_entity.has_client_defined_unique_tag()) {
385 entity = UniqueClientEntity::Create(client_entity);
386 } else {
387 // TODO(pvalenzuela): Validate entity's parent ID.
388 EntityMap::const_iterator iter = entities_.find(client_entity.id_string());
389 if (iter != entities_.end()) {
390 entity = BookmarkEntity::CreateUpdatedVersion(client_entity,
391 *iter->second, parent_id);
392 } else {
393 entity = BookmarkEntity::CreateNew(client_entity, parent_id, client_guid);
394 }
395 }
396
397 if (!entity) {
398 // TODO(pvalenzuela): Add logging so that it is easier to determine why
399 // creation failed.
400 return string();
401 }
402
403 const std::string id = entity->id();
404 SaveEntity(std::move(entity));
405 BuildEntryResponseForSuccessfulCommit(id, entry_response);
406 return id;
407 }
408
409 void FakeServer::BuildEntryResponseForSuccessfulCommit(
410 const std::string& entity_id,
411 sync_pb::CommitResponse_EntryResponse* entry_response) {
412 EntityMap::const_iterator iter = entities_.find(entity_id);
413 CHECK(iter != entities_.end());
414 const FakeServerEntity& entity = *iter->second;
415 entry_response->set_response_type(sync_pb::CommitResponse::SUCCESS);
416 entry_response->set_id_string(entity.id());
417
418 if (entity.IsDeleted()) {
419 entry_response->set_version(entity.GetVersion() + 1);
420 } else {
421 entry_response->set_version(entity.GetVersion());
422 entry_response->set_name(entity.GetName());
423 }
424 }
425
426 bool FakeServer::IsChild(const string& id, const string& potential_parent_id) {
427 EntityMap::const_iterator iter = entities_.find(id);
428 if (iter == entities_.end()) {
429 // We've hit an ID (probably the imaginary root entity) that isn't stored
430 // by the server, so it can't be a child.
431 return false;
432 }
433
434 const FakeServerEntity& entity = *iter->second;
435 if (entity.GetParentId() == potential_parent_id)
436 return true;
437
438 // Recursively look up the tree.
439 return IsChild(entity.GetParentId(), potential_parent_id);
440 }
441
442 void FakeServer::DeleteChildren(const string& id) {
443 std::vector<std::unique_ptr<FakeServerEntity>> tombstones;
444 // Find all the children of id.
445 for (const auto& entity : entities_) {
446 if (IsChild(entity.first, id)) {
447 tombstones.push_back(TombstoneEntity::Create(
448 entity.first, entity.second->client_defined_unique_tag()));
449 }
450 }
451
452 for (auto& tombstone : tombstones) {
453 SaveEntity(std::move(tombstone));
454 }
455 }
456
457 bool FakeServer::HandleCommitRequest(const sync_pb::CommitMessage& commit,
458 const std::string& invalidator_client_id,
459 sync_pb::CommitResponse* response) {
460 std::map<string, string> client_to_server_ids;
461 string guid = commit.cache_guid();
462 ModelTypeSet committed_model_types;
463
464 // TODO(pvalenzuela): Add validation of CommitMessage.entries.
465 ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>::const_iterator it;
466 for (it = commit.entries().begin(); it != commit.entries().end(); ++it) {
467 sync_pb::CommitResponse_EntryResponse* entry_response =
468 response->add_entryresponse();
469
470 sync_pb::SyncEntity client_entity = *it;
471 string parent_id = client_entity.parent_id_string();
472 if (client_to_server_ids.find(parent_id) != client_to_server_ids.end()) {
473 parent_id = client_to_server_ids[parent_id];
474 }
475
476 const string entity_id =
477 CommitEntity(client_entity, entry_response, guid, parent_id);
478 if (entity_id.empty()) {
479 return false;
480 }
481
482 // Record the ID if it was renamed.
483 if (entity_id != client_entity.id_string()) {
484 client_to_server_ids[client_entity.id_string()] = entity_id;
485 }
486
487 EntityMap::const_iterator iter = entities_.find(entity_id);
488 CHECK(iter != entities_.end());
489 committed_model_types.Put(iter->second->model_type());
490 }
491
492 for (auto& observer : observers_)
493 observer.OnCommit(invalidator_client_id, committed_model_types);
494
495 return true;
496 }
497
134 std::unique_ptr<base::DictionaryValue> 498 std::unique_ptr<base::DictionaryValue>
135 FakeServer::GetEntitiesAsDictionaryValue() { 499 FakeServer::GetEntitiesAsDictionaryValue() {
136 DCHECK(thread_checker_.CalledOnValidThread()); 500 DCHECK(thread_checker_.CalledOnValidThread());
137 return loopback_server_->GetEntitiesAsDictionaryValue(); 501 std::unique_ptr<base::DictionaryValue> dictionary(
502 new base::DictionaryValue());
503
504 // Initialize an empty ListValue for all ModelTypes.
505 ModelTypeSet all_types = ModelTypeSet::All();
506 for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) {
507 dictionary->Set(ModelTypeToString(it.Get()),
508 base::MakeUnique<base::ListValue>());
509 }
510
511 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
512 ++it) {
513 const FakeServerEntity& entity = *it->second;
514 if (IsDeletedOrPermanent(entity)) {
515 // Tombstones are ignored as they don't represent current data. Folders
516 // are also ignored as current verification infrastructure does not
517 // consider them.
518 continue;
519 }
520 base::ListValue* list_value;
521 if (!dictionary->GetList(ModelTypeToString(entity.model_type()),
522 &list_value)) {
523 return std::unique_ptr<base::DictionaryValue>();
524 }
525 // TODO(pvalenzuela): Store more data for each entity so additional
526 // verification can be performed. One example of additional verification
527 // is checking the correctness of the bookmark hierarchy.
528 list_value->AppendString(entity.GetName());
529 }
530
531 return dictionary;
138 } 532 }
139 533
140 std::vector<sync_pb::SyncEntity> FakeServer::GetSyncEntitiesByModelType( 534 std::vector<sync_pb::SyncEntity> FakeServer::GetSyncEntitiesByModelType(
141 ModelType model_type) { 535 ModelType model_type) {
142 DCHECK(thread_checker_.CalledOnValidThread()); 536 std::vector<sync_pb::SyncEntity> sync_entities;
143 return loopback_server_->GetSyncEntitiesByModelType(model_type); 537 DCHECK(thread_checker_.CalledOnValidThread());
144 } 538 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
145 539 ++it) {
146 void FakeServer::InjectEntity(std::unique_ptr<LoopbackServerEntity> entity) { 540 const FakeServerEntity& entity = *it->second;
147 DCHECK(thread_checker_.CalledOnValidThread()); 541 if (!IsDeletedOrPermanent(entity) && entity.model_type() == model_type) {
148 loopback_server_->SaveEntity(std::move(entity)); 542 sync_pb::SyncEntity sync_entity;
543 entity.SerializeAsProto(&sync_entity);
544 sync_entities.push_back(sync_entity);
545 }
546 }
547 return sync_entities;
548 }
549
550 void FakeServer::InjectEntity(std::unique_ptr<FakeServerEntity> entity) {
551 DCHECK(thread_checker_.CalledOnValidThread());
552 SaveEntity(std::move(entity));
149 } 553 }
150 554
151 bool FakeServer::ModifyEntitySpecifics( 555 bool FakeServer::ModifyEntitySpecifics(
152 const std::string& id, 556 const std::string& id,
153 const sync_pb::EntitySpecifics& updated_specifics) { 557 const sync_pb::EntitySpecifics& updated_specifics) {
154 return loopback_server_->ModifyEntitySpecifics(id, updated_specifics); 558 EntityMap::const_iterator iter = entities_.find(id);
559 if (iter == entities_.end() ||
560 iter->second->model_type() !=
561 GetModelTypeFromSpecifics(updated_specifics)) {
562 return false;
563 }
564
565 FakeServerEntity* entity = iter->second.get();
566 entity->SetSpecifics(updated_specifics);
567 UpdateEntityVersion(entity);
568 return true;
155 } 569 }
156 570
157 bool FakeServer::ModifyBookmarkEntity( 571 bool FakeServer::ModifyBookmarkEntity(
158 const std::string& id, 572 const std::string& id,
159 const std::string& parent_id, 573 const std::string& parent_id,
160 const sync_pb::EntitySpecifics& updated_specifics) { 574 const sync_pb::EntitySpecifics& updated_specifics) {
161 return loopback_server_->ModifyBookmarkEntity(id, parent_id, 575 EntityMap::const_iterator iter = entities_.find(id);
162 updated_specifics); 576 if (iter == entities_.end() ||
577 iter->second->model_type() != syncer::BOOKMARKS ||
578 GetModelTypeFromSpecifics(updated_specifics) != syncer::BOOKMARKS) {
579 return false;
580 }
581
582 BookmarkEntity* entity = static_cast<BookmarkEntity*>(iter->second.get());
583
584 entity->SetParentId(parent_id);
585 entity->SetSpecifics(updated_specifics);
586 if (updated_specifics.has_bookmark()) {
587 entity->SetName(updated_specifics.bookmark().title());
588 }
589 UpdateEntityVersion(entity);
590 return true;
163 } 591 }
164 592
165 void FakeServer::ClearServerData() { 593 void FakeServer::ClearServerData() {
166 DCHECK(thread_checker_.CalledOnValidThread()); 594 DCHECK(thread_checker_.CalledOnValidThread());
167 loopback_server_->ClearServerData(); 595 entities_.clear();
596 keystore_keys_.clear();
597 ++store_birthday_;
598 Init();
168 } 599 }
169 600
170 void FakeServer::SetAuthenticated() { 601 void FakeServer::SetAuthenticated() {
171 DCHECK(thread_checker_.CalledOnValidThread()); 602 DCHECK(thread_checker_.CalledOnValidThread());
172 authenticated_ = true; 603 authenticated_ = true;
173 } 604 }
174 605
175 void FakeServer::SetUnauthenticated() { 606 void FakeServer::SetUnauthenticated() {
176 DCHECK(thread_checker_.CalledOnValidThread()); 607 DCHECK(thread_checker_.CalledOnValidThread());
177 authenticated_ = false; 608 authenticated_ = false;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 void FakeServer::AddObserver(Observer* observer) { 666 void FakeServer::AddObserver(Observer* observer) {
236 DCHECK(thread_checker_.CalledOnValidThread()); 667 DCHECK(thread_checker_.CalledOnValidThread());
237 observers_.AddObserver(observer); 668 observers_.AddObserver(observer);
238 } 669 }
239 670
240 void FakeServer::RemoveObserver(Observer* observer) { 671 void FakeServer::RemoveObserver(Observer* observer) {
241 DCHECK(thread_checker_.CalledOnValidThread()); 672 DCHECK(thread_checker_.CalledOnValidThread());
242 observers_.RemoveObserver(observer); 673 observers_.RemoveObserver(observer);
243 } 674 }
244 675
245 void FakeServer::OnCommit(const std::string& committer_id,
246 syncer::ModelTypeSet committed_model_types) {
247 for (auto& observer : observers_)
248 observer.OnCommit(committer_id, committed_model_types);
249 }
250
251 void FakeServer::EnableNetwork() { 676 void FakeServer::EnableNetwork() {
252 DCHECK(thread_checker_.CalledOnValidThread()); 677 DCHECK(thread_checker_.CalledOnValidThread());
253 network_enabled_ = true; 678 network_enabled_ = true;
254 } 679 }
255 680
256 void FakeServer::DisableNetwork() { 681 void FakeServer::DisableNetwork() {
257 DCHECK(thread_checker_.CalledOnValidThread()); 682 DCHECK(thread_checker_.CalledOnValidThread());
258 network_enabled_ = false; 683 network_enabled_ = false;
259 } 684 }
260 685
686 std::string FakeServer::GetBookmarkBarFolderId() const {
687 DCHECK(thread_checker_.CalledOnValidThread());
688 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
689 ++it) {
690 FakeServerEntity* entity = it->second.get();
691 if (entity->GetName() == kBookmarkBarFolderName && entity->IsFolder() &&
692 entity->model_type() == syncer::BOOKMARKS) {
693 return entity->id();
694 }
695 }
696 NOTREACHED() << "Bookmark Bar entity not found.";
697 return "";
698 }
699
261 base::WeakPtr<FakeServer> FakeServer::AsWeakPtr() { 700 base::WeakPtr<FakeServer> FakeServer::AsWeakPtr() {
262 DCHECK(thread_checker_.CalledOnValidThread()); 701 DCHECK(thread_checker_.CalledOnValidThread());
263 return weak_ptr_factory_.GetWeakPtr(); 702 return weak_ptr_factory_.GetWeakPtr();
264 } 703 }
265 704
705 std::string FakeServer::GetStoreBirthday() const {
706 DCHECK(thread_checker_.CalledOnValidThread());
707 return base::Int64ToString(store_birthday_);
708 }
709
266 } // namespace fake_server 710 } // namespace fake_server
OLDNEW
« no previous file with comments | « components/sync/test/fake_server/fake_server.h ('k') | components/sync/test/fake_server/fake_server_entity.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698