diff options
author | pvalenzuela@chromium.org <pvalenzuela@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-04 01:45:11 +0000 |
---|---|---|
committer | pvalenzuela@chromium.org <pvalenzuela@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-04 01:45:11 +0000 |
commit | 6e5bfcb7a0ea2af3d57cf9a2c5bf7de8e5841e0d (patch) | |
tree | 92652221d1bf4bcaebc64d6a602243db8cdd30f2 /sync/test | |
parent | d4a94b9491525574ca9d24b38a3575df2b7c7d0e (diff) | |
download | chromium_src-6e5bfcb7a0ea2af3d57cf9a2c5bf7de8e5841e0d.zip chromium_src-6e5bfcb7a0ea2af3d57cf9a2c5bf7de8e5841e0d.tar.gz chromium_src-6e5bfcb7a0ea2af3d57cf9a2c5bf7de8e5841e0d.tar.bz2 |
Implement Commit in the Sync C++ fake server
In addition to adding commit functionality, some of the existing
FakeServer code has been restructured. Most notably, FakeServerEntity
has been introduced to ease the pain of serializing/deserializing
SyncEntity protos. Also, SyncEntity IDs now include the entity's
ModelType so that tombstones sent from the client will have their
type known on the server. Another important change is correctly sending
tombstones back in GetUpdatesResponse.
This CL also starts to use FakeServer in SingleClientBookmarksSyncTest
(all test cases are still run against the Python server). Since the C++
server is now being used a real test, PrototypeFakeServerTest has been
deleted.
BUG=323265
Review URL: https://codereview.chromium.org/156883007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@254634 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync/test')
-rw-r--r-- | sync/test/fake_server/bookmark_entity.cc | 140 | ||||
-rw-r--r-- | sync/test/fake_server/bookmark_entity.h | 72 | ||||
-rw-r--r-- | sync/test/fake_server/fake_server.cc | 324 | ||||
-rw-r--r-- | sync/test/fake_server/fake_server.h | 58 | ||||
-rw-r--r-- | sync/test/fake_server/fake_server_entity.cc | 102 | ||||
-rw-r--r-- | sync/test/fake_server/fake_server_entity.h | 70 | ||||
-rw-r--r-- | sync/test/fake_server/fake_server_http_post_provider.cc | 6 | ||||
-rw-r--r-- | sync/test/fake_server/fake_server_http_post_provider.h | 13 | ||||
-rw-r--r-- | sync/test/fake_server/fake_server_network_resources.cc | 12 | ||||
-rw-r--r-- | sync/test/fake_server/fake_server_network_resources.h | 13 | ||||
-rw-r--r-- | sync/test/fake_server/permanent_entity.cc | 88 | ||||
-rw-r--r-- | sync/test/fake_server/permanent_entity.h | 53 | ||||
-rw-r--r-- | sync/test/fake_server/tombstone_entity.cc | 53 | ||||
-rw-r--r-- | sync/test/fake_server/tombstone_entity.h | 37 | ||||
-rw-r--r-- | sync/test/fake_server/unique_client_entity.cc | 87 | ||||
-rw-r--r-- | sync/test/fake_server/unique_client_entity.h | 50 |
16 files changed, 1011 insertions, 167 deletions
diff --git a/sync/test/fake_server/bookmark_entity.cc b/sync/test/fake_server/bookmark_entity.cc new file mode 100644 index 0000000..7a39f45 --- /dev/null +++ b/sync/test/fake_server/bookmark_entity.cc @@ -0,0 +1,140 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sync/test/fake_server/bookmark_entity.h" + +#include <string> + +#include "base/basictypes.h" +#include "base/guid.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/fake_server_entity.h" + +using std::string; + +using syncer::ModelType; + +namespace fake_server { + +BookmarkEntity::~BookmarkEntity() { } + +// static +FakeServerEntity* BookmarkEntity::CreateNew( + const sync_pb::SyncEntity& client_entity, + const string& parent_id, + const string& client_guid) { + if (client_entity.version() != 0) { + return NULL; + } + + ModelType model_type = + syncer::GetModelTypeFromSpecifics(client_entity.specifics()); + string id = FakeServerEntity::CreateId(model_type, base::GenerateGUID()); + string originator_cache_guid = client_guid; + string originator_client_item_id = client_entity.id_string(); + + return new BookmarkEntity(id, + model_type, + client_entity.version(), + client_entity.name(), + originator_cache_guid, + originator_client_item_id, + client_entity.unique_position(), + client_entity.specifics(), + client_entity.folder(), + parent_id, + client_entity.ctime(), + client_entity.mtime()); +} + +// static +FakeServerEntity* BookmarkEntity::CreateUpdatedVersion( + const sync_pb::SyncEntity& client_entity, + FakeServerEntity* current_server_entity, + const string& parent_id) { + if (client_entity.version() == 0 || current_server_entity == NULL) { + return NULL; + } + + BookmarkEntity* current_bookmark_entity = + static_cast<BookmarkEntity*>(current_server_entity); + string originator_cache_guid = + current_bookmark_entity->originator_cache_guid_; + string originator_client_item_id = + current_bookmark_entity->originator_client_item_id_; + ModelType model_type = + syncer::GetModelTypeFromSpecifics(client_entity.specifics()); + + return new BookmarkEntity(client_entity.id_string(), + model_type, + client_entity.version(), + client_entity.name(), + originator_cache_guid, + originator_client_item_id, + client_entity.unique_position(), + client_entity.specifics(), + client_entity.folder(), + parent_id, + client_entity.ctime(), + client_entity.mtime()); +} + +BookmarkEntity::BookmarkEntity( + const string& id, + const ModelType& model_type, + int64 version, + const string& name, + const string& originator_cache_guid, + const string& originator_client_item_id, + const sync_pb::UniquePosition& unique_position, + const sync_pb::EntitySpecifics& specifics, + bool is_folder, + const string& parent_id, + int64 creation_time, + int64 last_modified_time) + : FakeServerEntity(id, model_type, version, name), + originator_cache_guid_(originator_cache_guid), + originator_client_item_id_(originator_client_item_id), + unique_position_(unique_position), + specifics_(specifics), + is_folder_(is_folder), + parent_id_(parent_id), + creation_time_(creation_time), + last_modified_time_(last_modified_time) { } + +string BookmarkEntity::GetParentId() const { + return parent_id_; +} + +sync_pb::SyncEntity* BookmarkEntity::SerializeAsProto() { + sync_pb::SyncEntity* sync_entity = new sync_pb::SyncEntity(); + FakeServerEntity::SerializeBaseProtoFields(sync_entity); + + sync_pb::EntitySpecifics* specifics = sync_entity->mutable_specifics(); + specifics->CopyFrom(specifics_); + + sync_entity->set_originator_cache_guid(originator_cache_guid_); + sync_entity->set_originator_client_item_id(originator_client_item_id_); + + sync_entity->set_parent_id_string(parent_id_); + sync_entity->set_ctime(creation_time_); + sync_entity->set_mtime(last_modified_time_); + + sync_pb::UniquePosition* unique_position = + sync_entity->mutable_unique_position(); + unique_position->CopyFrom(unique_position_); + + return sync_entity; +} + +bool BookmarkEntity::IsDeleted() const { + return false; +} + +bool BookmarkEntity::IsFolder() const { + return is_folder_; +} + +} // namespace fake_server diff --git a/sync/test/fake_server/bookmark_entity.h b/sync/test/fake_server/bookmark_entity.h new file mode 100644 index 0000000..8c68a81 --- /dev/null +++ b/sync/test/fake_server/bookmark_entity.h @@ -0,0 +1,72 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SYNC_TEST_FAKE_SERVER_BOOKMARK_ENTITY_H_ +#define SYNC_TEST_FAKE_SERVER_BOOKMARK_ENTITY_H_ + +#include <map> +#include <string> + +#include "base/basictypes.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/fake_server_entity.h" + +namespace fake_server { + +// A bookmark version of FakeServerEntity. This type represents entities that +// are non-deleted, client-created, and not unique per client account. +class BookmarkEntity : public FakeServerEntity { + public: + virtual ~BookmarkEntity(); + + // Factory function for BookmarkEntity. This factory should be used only for + // the first time that a specific bookmark is seen by the server. + static FakeServerEntity* CreateNew(const sync_pb::SyncEntity& client_entity, + const std::string& parent_id, + const std::string& client_guid); + + // Factory function for BookmarkEntity. The server's current entity for this + // ID, |current_server_entity|, is passed here because the client does not + // always send the complete entity over the wire. This requires copying of + // some of the existing entity when creating a new entity. + static FakeServerEntity* CreateUpdatedVersion( + const sync_pb::SyncEntity& client_entity, + FakeServerEntity* current_server_entity, + const std::string& parent_id); + + // FakeServerEntity implementation. + virtual std::string GetParentId() const OVERRIDE; + virtual sync_pb::SyncEntity* SerializeAsProto() OVERRIDE; + virtual bool IsDeleted() const OVERRIDE; + virtual bool IsFolder() const OVERRIDE; + + private: + BookmarkEntity(const std::string& id, + const syncer::ModelType& model_type, + int64 version, + const std::string& name, + const std::string& originator_cache_guid, + const std::string& originator_client_item_id, + const sync_pb::UniquePosition& unique_position, + const sync_pb::EntitySpecifics& specifics, + bool is_folder, + const std::string& parent_id, + int64 creation_time, + int64 last_modified_time); + + // All member values have equivalent fields in SyncEntity. + std::string originator_cache_guid_; + std::string originator_client_item_id_; + sync_pb::UniquePosition unique_position_; + sync_pb::EntitySpecifics specifics_; + bool is_folder_; + std::string parent_id_; + int64 creation_time_; + int64 last_modified_time_; +}; + +} // namespace fake_server + +#endif // SYNC_TEST_FAKE_SERVER_BOOKMARK_ENTITY_H_ diff --git a/sync/test/fake_server/fake_server.cc b/sync/test/fake_server/fake_server.cc index 4c1ea65..f49578a 100644 --- a/sync/test/fake_server/fake_server.cc +++ b/sync/test/fake_server/fake_server.cc @@ -9,18 +9,26 @@ #include <vector> #include "base/basictypes.h" +#include "base/guid.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "net/base/net_errors.h" #include "net/http/http_status_code.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/bookmark_entity.h" +#include "sync/test/fake_server/permanent_entity.h" +#include "sync/test/fake_server/tombstone_entity.h" +#include "sync/test/fake_server/unique_client_entity.h" using std::string; +using std::vector; -// The parent tag for childen of the root node. -static const char kRootParentTag[] = "0"; +using syncer::ModelType; // The default birthday value. static const char kDefaultBirthday[] = "1234567890"; @@ -28,10 +36,10 @@ static const char kDefaultBirthday[] = "1234567890"; // The default keystore key. static const char kDefaultKeystoreKey[] = "1111111111111111"; -// A dummy value to use for the position_in_parent field of SyncEntity. -static const int64 kDummyBookmarkPositionInParent = 1337; +namespace fake_server { + +class FakeServerEntity; -namespace syncer { namespace { // A filter used during GetUpdates calls to determine what information to @@ -64,14 +72,20 @@ class UpdateSieve { } } - // Determines whether the server should send |entity| to the client based - // on its type and version. - bool ClientWantsItem(const sync_pb::SyncEntity& entity) const { + // Determines whether the server should send an |entity| to the client as + // part of a GetUpdatesResponse. + bool ClientWantsItem(FakeServerEntity* entity) const { + int64 version = entity->GetVersion(); + if (version <= min_version_) { + return false; + } else if (entity->IsDeleted()) { + return true; + } + ModelTypeToVersionMap::const_iterator it = - request_from_version_.find(GetModelType(entity)); + request_from_version_.find(entity->GetModelType()); - return it == request_from_version_.end() ? - false : it->second < entity.version(); + return it == request_from_version_.end() ? false : it->second < version; } // Returns the mininum version seen across all types. @@ -80,8 +94,8 @@ class UpdateSieve { } // Returns the data type IDs of types being synced for the first time. - std::vector<ModelType> GetFirstTimeTypes() const { - std::vector<ModelType> types; + vector<ModelType> GetFirstTimeTypes() const { + vector<ModelType> types; ModelTypeToVersionMap::const_iterator it; for (it = request_from_version_.begin(); it != request_from_version_.end(); @@ -127,7 +141,7 @@ scoped_ptr<UpdateSieve> UpdateSieve::Create( DCHECK(parsed); } - ModelType model_type = GetModelTypeFromSpecificsFieldNumber( + ModelType model_type = syncer::GetModelTypeFromSpecificsFieldNumber( marker.data_type_id()); request_from_version[model_type] = version; @@ -145,79 +159,58 @@ FakeServer::FakeServer() : version_(0), birthday_(kDefaultBirthday) { keystore_keys_.push_back(kDefaultKeystoreKey); } -FakeServer::~FakeServer() { } +FakeServer::~FakeServer() { + STLDeleteContainerPairSecondPointers(entities_.begin(), entities_.end()); +} -void FakeServer::CreateDefaultPermanentItems( - const std::vector<ModelType>& first_time_types) { - for (std::vector<ModelType>::const_iterator it = first_time_types.begin(); +bool FakeServer::CreateDefaultPermanentItems( + const vector<ModelType>& first_time_types) { + for (vector<ModelType>::const_iterator it = first_time_types.begin(); it != first_time_types.end(); ++it) { - if (!ModelTypeSet::All().Has(*it)) { + if (!syncer::ModelTypeSet::All().Has(*it)) { NOTREACHED() << "An unexpected ModelType was encountered."; } ModelType model_type = *it; - CreateSyncEntity(model_type, - ModelTypeToRootTag(model_type), - ModelTypeToString(model_type), - kRootParentTag); - - if (model_type == BOOKMARKS) { - CreateSyncEntity(BOOKMARKS, - "bookmark_bar", - "Bookmark Bar", - ModelTypeToRootTag(BOOKMARKS)); - CreateSyncEntity(BOOKMARKS, - "other_bookmarks", - "Other Bookmarks", - ModelTypeToRootTag(BOOKMARKS)); + FakeServerEntity* top_level_entity = + PermanentEntity::CreateTopLevel(model_type); + if (top_level_entity == NULL) { + return false; + } + SaveEntity(top_level_entity); + + if (model_type == syncer::BOOKMARKS) { + FakeServerEntity* bookmark_bar_entity = + PermanentEntity::Create(syncer::BOOKMARKS, + "bookmark_bar", + "Bookmark Bar", + ModelTypeToRootTag(syncer::BOOKMARKS)); + if (bookmark_bar_entity == NULL) { + return false; + } + SaveEntity(bookmark_bar_entity); + + FakeServerEntity* other_bookmarks_entity = + PermanentEntity::Create(syncer::BOOKMARKS, + "other_bookmarks", + "Other Bookmarks", + ModelTypeToRootTag(syncer::BOOKMARKS)); + if (other_bookmarks_entity == NULL) { + return false; + } + SaveEntity(other_bookmarks_entity); } } - // TODO(pvalenzuela): Create the mobile bookmarks folder when the fake server // is used by mobile tests. + return true; } -void FakeServer::CreateSyncEntity(ModelType model_type, - const std::string& id, - const std::string& name, - const std::string& parent_tag) { - DCHECK(!id.empty()); - DCHECK(!name.empty()); - DCHECK(!parent_tag.empty()); - - sync_pb::SyncEntity entity; - entity.set_id_string(id); - entity.set_non_unique_name(name); - entity.set_name(name); - entity.set_server_defined_unique_tag(id); - entity.set_folder(true); - entity.set_deleted(false); - - entity.set_parent_id_string(parent_tag); - - if (parent_tag != kRootParentTag && model_type == BOOKMARKS) { - // Use a dummy value here. - entity.set_position_in_parent(kDummyBookmarkPositionInParent); - } - - sync_pb::EntitySpecifics* specifics = entity.mutable_specifics(); - AddDefaultFieldValue(model_type, specifics); - - SaveEntity(&entity); -} - -void FakeServer::SaveEntity(sync_pb::SyncEntity* entity) { - version_++; - entity->set_version(version_); - entity->set_sync_timestamp(version_); - - sync_pb::SyncEntity original_entity = entities_[entity->id_string()]; - entity->set_originator_cache_guid(original_entity.originator_cache_guid()); - entity->set_originator_client_item_id( - original_entity.originator_client_item_id()); - - entities_[entity->id_string()] = *entity; +void FakeServer::SaveEntity(FakeServerEntity* entity) { + delete entities_[entity->GetId()]; + entity->SetVersion(++version_); + entities_[entity->GetId()] = entity; } int FakeServer::HandleCommand(const string& request, @@ -228,57 +221,57 @@ int FakeServer::HandleCommand(const string& request, DCHECK(parsed); sync_pb::ClientToServerResponse response_proto; + bool success; switch (message.message_contents()) { case sync_pb::ClientToServerMessage::GET_UPDATES: - response_proto = HandleGetUpdatesRequest(message); + success = HandleGetUpdatesRequest(message.get_updates(), + response_proto.mutable_get_updates()); break; case sync_pb::ClientToServerMessage::COMMIT: - response_proto = HandleCommitRequest(message); + success = HandleCommitRequest(message.commit(), + response_proto.mutable_commit()); break; default: return net::ERR_NOT_IMPLEMENTED; } + if (!success) { + // TODO(pvalenzuela): Add logging here so that tests have more info about + // the failure. + return net::HTTP_BAD_REQUEST; + } + + response_proto.set_error_code(sync_pb::SyncEnums::SUCCESS); + response_proto.set_store_birthday(birthday_); *response_code = net::HTTP_OK; *response = response_proto.SerializeAsString(); return 0; } -bool SyncEntityVersionComparator(const sync_pb::SyncEntity& first, - const sync_pb::SyncEntity& second) { - return first.version() < second.version(); -} - -sync_pb::ClientToServerResponse FakeServer::HandleGetUpdatesRequest( - const sync_pb::ClientToServerMessage& message) { - sync_pb::ClientToServerResponse response; - response.set_error_code(sync_pb::SyncEnums::SUCCESS); - response.set_store_birthday(birthday_); - - sync_pb::GetUpdatesResponse* get_updates_response = - response.mutable_get_updates(); +bool FakeServer::HandleGetUpdatesRequest( + const sync_pb::GetUpdatesMessage& get_updates, + sync_pb::GetUpdatesResponse* response) { // TODO(pvalenzuela): Implement batching instead of sending all information // at once. - get_updates_response->set_changes_remaining(0); - - scoped_ptr<UpdateSieve> sieve = UpdateSieve::Create(message.get_updates()); - CreateDefaultPermanentItems(sieve->GetFirstTimeTypes()); + response->set_changes_remaining(0); - int64 min_version = sieve->GetMinVersion(); + scoped_ptr<UpdateSieve> sieve = UpdateSieve::Create(get_updates); + if (!CreateDefaultPermanentItems(sieve->GetFirstTimeTypes())) { + return false; + } bool send_encryption_keys_based_on_nigori = false; int64 max_response_version = 0; for (EntityMap::iterator it = entities_.begin(); it != entities_.end(); ++it) { - sync_pb::SyncEntity entity = it->second; - if (entity.version() > min_version && sieve->ClientWantsItem(entity)) { - sync_pb::SyncEntity* response_entity = - get_updates_response->add_entries(); - response_entity->CopyFrom(entity); + FakeServerEntity* entity = it->second; + if (sieve->ClientWantsItem(entity)) { + sync_pb::SyncEntity* response_entity = response->add_entries(); + response_entity->CopyFrom(*(entity->SerializeAsProto())); max_response_version = std::max(max_response_version, response_entity->version()); - if (response_entity->name() == ModelTypeToString(NIGORI)) { + if (entity->GetModelType() == syncer::NIGORI) { send_encryption_keys_based_on_nigori = response_entity->specifics().nigori().passphrase_type() == sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE; @@ -287,49 +280,128 @@ sync_pb::ClientToServerResponse FakeServer::HandleGetUpdatesRequest( } if (send_encryption_keys_based_on_nigori || - message.get_updates().need_encryption_key()) { - for (std::vector<std::string>::iterator it = keystore_keys_.begin(); + get_updates.need_encryption_key()) { + for (vector<string>::iterator it = keystore_keys_.begin(); it != keystore_keys_.end(); ++it) { - get_updates_response->add_encryption_keys(*it); + response->add_encryption_keys(*it); + } + } + + sieve->UpdateProgressMarkers(max_response_version, response); + return true; +} + +bool FakeServer::CommitEntity( + const sync_pb::SyncEntity& client_entity, + sync_pb::CommitResponse_EntryResponse* entry_response, + string client_guid, + std::map<string, string>* client_to_server_ids) { + if (client_entity.version() == 0 && client_entity.deleted()) { + return false; + } + + FakeServerEntity* entity; + if (client_entity.deleted()) { + entity = TombstoneEntity::Create(client_entity.id_string()); + // TODO(pvalenzuela): Change the behavior of DeleteChilden so that it does + // not modify server data if it fails. + if (!DeleteChildren(client_entity.id_string())) { + return false; + } + } else if (client_entity.has_client_defined_unique_tag()) { + entity = UniqueClientEntity::Create(client_entity); + } else { + string parent_id = client_entity.parent_id_string(); + if (client_to_server_ids->find(parent_id) != + client_to_server_ids->end()) { + parent_id = (*client_to_server_ids)[parent_id]; + } + // TODO(pvalenzuela): Validate entity's parent ID. + if (entities_.find(client_entity.id_string()) != entities_.end()) { + entity = BookmarkEntity::CreateUpdatedVersion( + client_entity, + entities_[client_entity.id_string()], + parent_id); + } else { + entity = BookmarkEntity::CreateNew(client_entity, parent_id, client_guid); } } - sieve->UpdateProgressMarkers(max_response_version, get_updates_response); + if (entity == NULL) { + // TODO(pvalenzuela): Add logging so that it is easier to determine why + // creation failed. + return false; + } - return response; + // Record the ID if it was renamed. + if (client_entity.id_string() != entity->GetId()) { + (*client_to_server_ids)[client_entity.id_string()] = entity->GetId(); + } + + SaveEntity(entity); + BuildEntryResponseForSuccessfulCommit(entry_response, entity); + return true; } -sync_pb::SyncEntity FakeServer::CommitEntity(const sync_pb::SyncEntity& entity, - string guid) { - // TODO(pvalenzuela): Implement this. Right now this method cheats and - // doesn't actually commit. - return entity; +void FakeServer::BuildEntryResponseForSuccessfulCommit( + sync_pb::CommitResponse_EntryResponse* entry_response, + FakeServerEntity* entity) { + entry_response->set_response_type(sync_pb::CommitResponse::SUCCESS); + entry_response->set_id_string(entity->GetId()); + + if (entity->IsDeleted()) { + entry_response->set_version(entity->GetVersion() + 1); + } else { + entry_response->set_version(entity->GetVersion()); + entry_response->set_name(entity->GetName()); + } } -sync_pb::ClientToServerResponse FakeServer::HandleCommitRequest( - const sync_pb::ClientToServerMessage& message) { - sync_pb::ClientToServerResponse response; - response.set_error_code(sync_pb::SyncEnums::SUCCESS); - response.set_store_birthday(birthday_); +bool FakeServer::IsChild(const string& id, const string& potential_parent_id) { + if (entities_.find(id) == entities_.end()) { + // We've hit an ID (probably the imaginary root entity) that isn't stored + // by the server, so it can't be a child. + return false; + } else if (entities_[id]->GetParentId() == potential_parent_id) { + return true; + } else { + // Recursively look up the tree. + return IsChild(entities_[id]->GetParentId(), potential_parent_id); + } +} - sync_pb::CommitMessage commit = message.commit(); - string guid = commit.cache_guid(); +bool FakeServer::DeleteChildren(const string& id) { + for (EntityMap::iterator it = entities_.begin(); it != entities_.end(); + ++it) { + if (IsChild(it->first, id)) { + FakeServerEntity* tombstone = TombstoneEntity::Create(it->first); + if (tombstone == NULL) { + return false; + } + SaveEntity(tombstone); + } + } + return true; +} - sync_pb::CommitResponse* commit_response = response.mutable_commit(); +bool FakeServer::HandleCommitRequest( + const sync_pb::CommitMessage& commit, + sync_pb::CommitResponse* response) { + std::map<string, string> client_to_server_ids; + string guid = commit.cache_guid(); + // TODO(pvalenzuela): Add validation of CommitMessage.entries. ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>::const_iterator it; for (it = commit.entries().begin(); it != commit.entries().end(); ++it) { sync_pb::CommitResponse_EntryResponse* entry_response = - commit_response->add_entryresponse(); + response->add_entryresponse(); - sync_pb::SyncEntity server_entity = CommitEntity(*it, guid); - - entry_response->set_id_string(server_entity.id_string()); - entry_response->set_response_type(sync_pb::CommitResponse::SUCCESS); - entry_response->set_version(it->version() + 1); + if (!CommitEntity(*it, entry_response, guid, &client_to_server_ids)) { + return false; + } } - return response; + return true; } -} // namespace syncer +} // namespace fake_server diff --git a/sync/test/fake_server/fake_server.h b/sync/test/fake_server/fake_server.h index 1e0f4d7..61c14ee 100644 --- a/sync/test/fake_server/fake_server.h +++ b/sync/test/fake_server/fake_server.h @@ -12,8 +12,9 @@ #include "base/memory/scoped_ptr.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/fake_server_entity.h" -namespace syncer { +namespace fake_server { // A fake version of the Sync server used for testing. class FakeServer { @@ -29,35 +30,46 @@ class FakeServer { std::string* response); private: - typedef std::map<std::string, sync_pb::SyncEntity> EntityMap; + typedef std::map<std::string, FakeServerEntity*> EntityMap; // Processes a GetUpdates call. - sync_pb::ClientToServerResponse HandleGetUpdatesRequest( - const sync_pb::ClientToServerMessage& message); + bool HandleGetUpdatesRequest(const sync_pb::GetUpdatesMessage& get_updates, + sync_pb::GetUpdatesResponse* response); // Processes a Commit call. - sync_pb::ClientToServerResponse HandleCommitRequest( - const sync_pb::ClientToServerMessage& message); + bool HandleCommitRequest(const sync_pb::CommitMessage& commit, + sync_pb::CommitResponse* response); // Inserts the appropriate permanent items in |entities_|. - void CreateDefaultPermanentItems( - const std::vector<ModelType>& first_time_types); - - // Creates and saves a SyncEntity of the given |model_type|. The entity's - // id_string and server_defined_unique_tag fields are set to |id|. The - // non_unique_name and name fields are set to |name|. Since tags are used as - // ids, the parent_id_string field is set to |parent_tag|. - void CreateSyncEntity(ModelType model_type, - const std::string& id, - const std::string& name, - const std::string& parent_tag); + bool CreateDefaultPermanentItems( + const std::vector<syncer::ModelType>& first_time_types); // Saves a |entity| to |entities_|. - void SaveEntity(sync_pb::SyncEntity* entity); - - // Commits a client-side |entity| to |entities_|. - sync_pb::SyncEntity CommitEntity(const sync_pb::SyncEntity& entity, - std::string guid); + void SaveEntity(FakeServerEntity* entity); + + // Commits a client-side SyncEntity to the server as a FakeServerEntity. + // The client that sent the commit is identified via |client_guid| and all + // entity ID renaming is tracked with |client_to_server_ids|. If the commit + // is successful, true is returned and the server's version of the SyncEntity + // is stored in |server_entity|. + bool CommitEntity(const sync_pb::SyncEntity& client_entity, + sync_pb::CommitResponse_EntryResponse* entry_response, + std::string client_guid, + std::map<std::string, std::string>* client_to_server_ids); + + // Populates |entry_response| based on |entity|. It is assumed that + // SaveEntity has already been called on |entity|. + void BuildEntryResponseForSuccessfulCommit( + sync_pb::CommitResponse_EntryResponse* entry_response, + FakeServerEntity* entity); + + // Determines whether the SyncEntity with id_string |id| is a child of an + // entity with id_string |potential_parent_id|. + bool IsChild(const std::string& id, const std::string& potential_parent_id); + + // Creates and saves tombstones for all children of the entity with the given + // |id|. A tombstone is not created for the entity itself. + bool DeleteChildren(const std::string& id); // This is the last version number assigned to an entity. The next entity will // have a version number of version_ + 1. @@ -74,6 +86,6 @@ class FakeServer { std::vector<std::string> keystore_keys_; }; -} // namespace syncer +} // namespace fake_server #endif // SYNC_TEST_FAKE_SERVER_FAKE_SERVER_H_ diff --git a/sync/test/fake_server/fake_server_entity.cc b/sync/test/fake_server/fake_server_entity.cc new file mode 100644 index 0000000..4d96a80 --- /dev/null +++ b/sync/test/fake_server/fake_server_entity.cc @@ -0,0 +1,102 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sync/test/fake_server/fake_server_entity.h" + +#include <limits> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/guid.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "net/base/net_errors.h" +#include "net/http/http_status_code.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" + +using std::string; +using std::vector; + +using syncer::ModelType; + +// The separator used when formatting IDs. +const char kIdSeparator[] = "/"; + +namespace fake_server { + +FakeServerEntity::~FakeServerEntity() { } + +const std::string& FakeServerEntity::GetId() const { + return id_; +} + +ModelType FakeServerEntity::GetModelType() const { + return model_type_; +} + +int64 FakeServerEntity::GetVersion() const { + return version_; +} + +void FakeServerEntity::SetVersion(int64 version) { + version_ = version; +} + +const std::string& FakeServerEntity::GetName() const { + return name_; +} + +// static +string FakeServerEntity::CreateId(const ModelType& model_type, + const string& inner_id) { + int field_number = GetSpecificsFieldNumberFromModelType(model_type); + return base::StringPrintf("%d%s%s", + field_number, + kIdSeparator, + inner_id.c_str()); +} + +// static +ModelType FakeServerEntity::GetModelTypeFromId(const string& id) { + vector<string> tokens; + size_t token_count = Tokenize(id, kIdSeparator, &tokens); + + int field_number; + if (token_count != 2 || !base::StringToInt(tokens[0], &field_number)) { + return syncer::UNSPECIFIED; + } + + return syncer::GetModelTypeFromSpecificsFieldNumber(field_number); +} + +FakeServerEntity::FakeServerEntity(const string& id, + const ModelType& model_type, + int64 version, + const string& name) + : id_(id), + model_type_(model_type), + version_(version), + name_(name) {} + +void FakeServerEntity::SerializeBaseProtoFields( + sync_pb::SyncEntity* sync_entity) { + DCHECK(sync_entity); + + // FakeServerEntity fields + sync_entity->set_id_string(id_); + sync_entity->set_version(version_); + sync_entity->set_name(name_); + + // Data via accessors + sync_entity->set_deleted(IsDeleted()); + sync_entity->set_folder(IsFolder()); +} + +} // namespace fake_server diff --git a/sync/test/fake_server/fake_server_entity.h b/sync/test/fake_server/fake_server_entity.h new file mode 100644 index 0000000..dd2cc75 --- /dev/null +++ b/sync/test/fake_server/fake_server_entity.h @@ -0,0 +1,70 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SYNC_TEST_FAKE_SERVER_FAKE_SERVER_ENTITY_H_ +#define SYNC_TEST_FAKE_SERVER_FAKE_SERVER_ENTITY_H_ + +#include <map> +#include <string> + +#include "base/basictypes.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" + +namespace fake_server { + +// The representation of a Sync entity for the fake server. +class FakeServerEntity { + public: + virtual ~FakeServerEntity(); + const std::string& GetId() const; + syncer::ModelType GetModelType() const; + int64 GetVersion() const; + void SetVersion(int64 version); + const std::string& GetName() const; + + // Common data items needed by server + virtual std::string GetParentId() const = 0; + virtual sync_pb::SyncEntity* SerializeAsProto() = 0; + virtual bool IsDeleted() const = 0; + virtual bool IsFolder() const = 0; + + protected: + // Creates an ID of the form <type><separator><inner-id> where + // <type> is the EntitySpecifics field number for |model_type|, <separator> + // is kIdSeparator, and <inner-id> is |inner_id|. + // + // If |inner_id| is globally unique, then the returned ID will also be + // globally unique. + static std::string CreateId(const syncer::ModelType& model_type, + const std::string& inner_id); + + // Extracts the ModelType from |id|. If |id| is malformed or does not contain + // a valid ModelType, UNSPECIFIED is returned. + static syncer::ModelType GetModelTypeFromId(const std::string& id); + + FakeServerEntity(const std::string& id, + const syncer::ModelType& model_type, + int64 version, + const std::string& name); + + void SerializeBaseProtoFields(sync_pb::SyncEntity* sync_entity); + + private: + // The entity's ID. + std::string id_; + + // The ModelType that categorizes this entity. + syncer::ModelType model_type_; + + // The version of this entity. + int64 version_; + + // The name of the entity. + std::string name_; +}; + +} // namespace fake_server + +#endif // SYNC_TEST_FAKE_SERVER_FAKE_SERVER_ENTITY_H_ diff --git a/sync/test/fake_server/fake_server_http_post_provider.cc b/sync/test/fake_server/fake_server_http_post_provider.cc index 5e8a99e..e0b3436 100644 --- a/sync/test/fake_server/fake_server_http_post_provider.cc +++ b/sync/test/fake_server/fake_server_http_post_provider.cc @@ -8,7 +8,9 @@ #include "sync/test/fake_server/fake_server.h" -namespace syncer { +using syncer::HttpPostProviderInterface; + +namespace fake_server { FakeServerHttpPostProviderFactory::FakeServerHttpPostProviderFactory( FakeServer* fake_server) : fake_server_(fake_server) { } @@ -77,4 +79,4 @@ const std::string FakeServerHttpPostProvider::GetResponseHeaderValue( void FakeServerHttpPostProvider::Abort() { } -} // namespace syncer +} // namespace fake_server diff --git a/sync/test/fake_server/fake_server_http_post_provider.h b/sync/test/fake_server/fake_server_http_post_provider.h index 4fc13e1..63f1eda 100644 --- a/sync/test/fake_server/fake_server_http_post_provider.h +++ b/sync/test/fake_server/fake_server_http_post_provider.h @@ -11,12 +11,12 @@ #include "sync/internal_api/public/http_post_provider_factory.h" #include "sync/internal_api/public/http_post_provider_interface.h" -namespace syncer { +namespace fake_server { class FakeServer; class FakeServerHttpPostProvider - : public HttpPostProviderInterface, + : public syncer::HttpPostProviderInterface, public base::RefCountedThreadSafe<FakeServerHttpPostProvider> { public: explicit FakeServerHttpPostProvider(FakeServer* fake_server); @@ -50,15 +50,16 @@ class FakeServerHttpPostProvider DISALLOW_COPY_AND_ASSIGN(FakeServerHttpPostProvider); }; -class FakeServerHttpPostProviderFactory : public HttpPostProviderFactory { +class FakeServerHttpPostProviderFactory + : public syncer::HttpPostProviderFactory { public: explicit FakeServerHttpPostProviderFactory(FakeServer* fake_server); virtual ~FakeServerHttpPostProviderFactory(); // HttpPostProviderFactory: virtual void Init(const std::string& user_agent) OVERRIDE; - virtual HttpPostProviderInterface* Create() OVERRIDE; - virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE; + virtual syncer::HttpPostProviderInterface* Create() OVERRIDE; + virtual void Destroy(syncer::HttpPostProviderInterface* http) OVERRIDE; private: FakeServer* const fake_server_; @@ -66,6 +67,6 @@ class FakeServerHttpPostProviderFactory : public HttpPostProviderFactory { DISALLOW_COPY_AND_ASSIGN(FakeServerHttpPostProviderFactory); }; -} // namespace syncer +} // namespace fake_server #endif // SYNC_TEST_FAKE_SERVER_FAKE_SERVER_HTTP_POST_PROVIDER_H_ diff --git a/sync/test/fake_server/fake_server_network_resources.cc b/sync/test/fake_server/fake_server_network_resources.cc index 1f5d308..56d5ea2 100644 --- a/sync/test/fake_server/fake_server_network_resources.cc +++ b/sync/test/fake_server/fake_server_network_resources.cc @@ -11,20 +11,24 @@ #include "sync/test/fake_server/fake_server.h" #include "sync/test/fake_server/fake_server_http_post_provider.h" -namespace syncer { +using syncer::CancelationSignal; +using syncer::HttpPostProviderFactory; +using syncer::NetworkTimeUpdateCallback; + +namespace fake_server { FakeServerNetworkResources::FakeServerNetworkResources(FakeServer* fake_server) : fake_server_(fake_server) { } FakeServerNetworkResources::~FakeServerNetworkResources() {} -scoped_ptr<HttpPostProviderFactory> +scoped_ptr<syncer::HttpPostProviderFactory> FakeServerNetworkResources::GetHttpPostProviderFactory( net::URLRequestContextGetter* baseline_context_getter, const NetworkTimeUpdateCallback& network_time_update_callback, CancelationSignal* cancelation_signal) { - return make_scoped_ptr<HttpPostProviderFactory>( + return make_scoped_ptr<syncer::HttpPostProviderFactory>( new FakeServerHttpPostProviderFactory(fake_server_)); } -} // namespace syncer +} // namespace fake_server diff --git a/sync/test/fake_server/fake_server_network_resources.h b/sync/test/fake_server/fake_server_network_resources.h index eda2fdf..5a4e89d 100644 --- a/sync/test/fake_server/fake_server_network_resources.h +++ b/sync/test/fake_server/fake_server_network_resources.h @@ -13,26 +13,27 @@ namespace net { class URLRequestContextGetter; } // namespace net -namespace syncer { +namespace fake_server { class FakeServer; class HttpPostProviderFactory; -class FakeServerNetworkResources : public NetworkResources { +class FakeServerNetworkResources : public syncer::NetworkResources { public: FakeServerNetworkResources(FakeServer* fake_server); virtual ~FakeServerNetworkResources(); // NetworkResources - virtual scoped_ptr<HttpPostProviderFactory> GetHttpPostProviderFactory( + virtual + scoped_ptr<syncer::HttpPostProviderFactory> GetHttpPostProviderFactory( net::URLRequestContextGetter* baseline_context_getter, - const NetworkTimeUpdateCallback& network_time_update_callback, - CancelationSignal* cancelation_signal) OVERRIDE; + const syncer::NetworkTimeUpdateCallback& network_time_update_callback, + syncer::CancelationSignal* cancelation_signal) OVERRIDE; private: FakeServer* const fake_server_; }; -} // namespace syncer +} // namespace fake_server #endif // SYNC_TEST_FAKE_SERVER_FAKE_SERVER_NETWORK_RESOURCES_H_ diff --git a/sync/test/fake_server/permanent_entity.cc b/sync/test/fake_server/permanent_entity.cc new file mode 100644 index 0000000..2aa371a --- /dev/null +++ b/sync/test/fake_server/permanent_entity.cc @@ -0,0 +1,88 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sync/test/fake_server/permanent_entity.h" + +#include <string> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/fake_server_entity.h" + +using std::string; + +using syncer::ModelType; + +// The parent tag for children of the root entity. Entities with this parent are +// referred to as top level enities. +static const char kRootParentTag[] = "0"; + +namespace fake_server { + +PermanentEntity::~PermanentEntity() { } + +// static +FakeServerEntity* PermanentEntity::Create(const ModelType& model_type, + const string& server_tag, + const string& name, + const string& parent_server_tag) { + DCHECK(model_type != syncer::UNSPECIFIED); + DCHECK(!server_tag.empty()); + DCHECK(!name.empty()); + DCHECK(!parent_server_tag.empty()); + if (parent_server_tag == kRootParentTag) { + return NULL; + } + + string id = FakeServerEntity::CreateId(model_type, server_tag); + string parent_id = FakeServerEntity::CreateId(model_type, parent_server_tag); + return new PermanentEntity(id, model_type, name, parent_id, server_tag); +} + +// static +FakeServerEntity* PermanentEntity::CreateTopLevel( + const ModelType& model_type) { + string server_tag = syncer::ModelTypeToRootTag(model_type); + string name = syncer::ModelTypeToString(model_type); + string id = FakeServerEntity::CreateId(model_type, server_tag); + return new PermanentEntity(id, model_type, name, kRootParentTag, server_tag); +} + +PermanentEntity::PermanentEntity(const string& id, + const ModelType& model_type, + const string& name, + const string& parent_id, + const string& server_defined_unique_tag) + : FakeServerEntity(id, model_type, 0, name), + server_defined_unique_tag_(server_defined_unique_tag), + parent_id_(parent_id) { } + +string PermanentEntity::GetParentId() const { + return parent_id_; +} + +sync_pb::SyncEntity* PermanentEntity::SerializeAsProto() { + sync_pb::SyncEntity* sync_entity = new sync_pb::SyncEntity(); + FakeServerEntity::SerializeBaseProtoFields(sync_entity); + + sync_pb::EntitySpecifics* specifics = sync_entity->mutable_specifics(); + AddDefaultFieldValue(FakeServerEntity::GetModelType(), specifics); + + sync_entity->set_parent_id_string(parent_id_); + sync_entity->set_server_defined_unique_tag(server_defined_unique_tag_); + + return sync_entity; +} + +bool PermanentEntity::IsDeleted() const { + return false; +} + +bool PermanentEntity::IsFolder() const { + return true; +} + +} // namespace fake_server diff --git a/sync/test/fake_server/permanent_entity.h b/sync/test/fake_server/permanent_entity.h new file mode 100644 index 0000000..3579720 --- /dev/null +++ b/sync/test/fake_server/permanent_entity.h @@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SYNC_TEST_FAKE_SERVER_PERMANENT_ENTITY_H_ +#define SYNC_TEST_FAKE_SERVER_PERMANENT_ENTITY_H_ + +#include <string> + +#include "base/basictypes.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/fake_server_entity.h" + +namespace fake_server { + +// A server-created, permanent entity. +class PermanentEntity : public FakeServerEntity { + public: + virtual ~PermanentEntity(); + + // Factory function for PermanentEntity. |server_tag| should be a globally + // unique identifier. + static FakeServerEntity* Create(const syncer::ModelType& model_type, + const std::string& server_tag, + const std::string& name, + const std::string& parent_server_tag); + + // Factory function for a top level BookmarkEntity. Top level means that the + // entity's parent is the root entity (no PermanentEntity exists for root). + static FakeServerEntity* CreateTopLevel(const syncer::ModelType& model_type); + + // FakeServerEntity implementation. + virtual std::string GetParentId() const OVERRIDE; + virtual sync_pb::SyncEntity* SerializeAsProto() OVERRIDE; + virtual bool IsDeleted() const OVERRIDE; + virtual bool IsFolder() const OVERRIDE; + + private: + PermanentEntity(const std::string& id, + const syncer::ModelType& model_type, + const std::string& name, + const std::string& parent_id, + const std::string& server_defined_unique_tag); + + // All member values have equivalent fields in SyncEntity. + std::string server_defined_unique_tag_; + std::string parent_id_; +}; + +} // namespace fake_server + +#endif // SYNC_TEST_FAKE_SERVER_PERMANENT_ENTITY_H_ diff --git a/sync/test/fake_server/tombstone_entity.cc b/sync/test/fake_server/tombstone_entity.cc new file mode 100644 index 0000000..e68deb3e --- /dev/null +++ b/sync/test/fake_server/tombstone_entity.cc @@ -0,0 +1,53 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sync/test/fake_server/tombstone_entity.h" + +#include <string> + +#include "base/basictypes.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/fake_server_entity.h" + +using std::string; + +using syncer::ModelType; + +namespace fake_server { + +TombstoneEntity::~TombstoneEntity() { } + +// static +FakeServerEntity* TombstoneEntity::Create(const string& id) { + return new TombstoneEntity(id, GetModelTypeFromId(id)); +} + +TombstoneEntity::TombstoneEntity(const string& id, + const ModelType& model_type) + : FakeServerEntity(id, model_type, 0, string()) { } + +string TombstoneEntity::GetParentId() const { + return string(); +} + +sync_pb::SyncEntity* TombstoneEntity::SerializeAsProto() { + sync_pb::SyncEntity* sync_entity = new sync_pb::SyncEntity(); + FakeServerEntity::SerializeBaseProtoFields(sync_entity); + + sync_pb::EntitySpecifics* specifics = sync_entity->mutable_specifics(); + AddDefaultFieldValue(FakeServerEntity::GetModelType(), specifics); + + return sync_entity; +} + +bool TombstoneEntity::IsDeleted() const { + return true; +} + +bool TombstoneEntity::IsFolder() const { + return false; +} + +} // namespace fake_server diff --git a/sync/test/fake_server/tombstone_entity.h b/sync/test/fake_server/tombstone_entity.h new file mode 100644 index 0000000..d670fc3 --- /dev/null +++ b/sync/test/fake_server/tombstone_entity.h @@ -0,0 +1,37 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SYNC_TEST_FAKE_SERVER_TOMBSTONE_ENTITY_H_ +#define SYNC_TEST_FAKE_SERVER_TOMBSTONE_ENTITY_H_ + +#include <string> + +#include "base/basictypes.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/fake_server_entity.h" + +namespace fake_server { + +// A Sync entity that represents a deleted item. +class TombstoneEntity : public FakeServerEntity { + public: + virtual ~TombstoneEntity(); + + // Factory function for TombstoneEntity. + static FakeServerEntity* Create(const std::string& id); + + // FakeServerEntity implementation. + virtual std::string GetParentId() const OVERRIDE; + virtual sync_pb::SyncEntity* SerializeAsProto() OVERRIDE; + virtual bool IsDeleted() const OVERRIDE; + virtual bool IsFolder() const OVERRIDE; + + private: + TombstoneEntity(const std::string& id, const syncer::ModelType& model_type); +}; + +} // namespace fake_server + +#endif // SYNC_TEST_FAKE_SERVER_TOMBSTONE_ENTITY_H_ diff --git a/sync/test/fake_server/unique_client_entity.cc b/sync/test/fake_server/unique_client_entity.cc new file mode 100644 index 0000000..06fc082 --- /dev/null +++ b/sync/test/fake_server/unique_client_entity.cc @@ -0,0 +1,87 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "sync/test/fake_server/unique_client_entity.h" + +#include <string> + +#include "base/basictypes.h" +#include "base/guid.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/fake_server_entity.h" + +using std::string; + +using syncer::ModelType; + +namespace fake_server { + +UniqueClientEntity::~UniqueClientEntity() { } + +// static +FakeServerEntity* UniqueClientEntity::Create( + const sync_pb::SyncEntity& client_entity) { + DCHECK(client_entity.has_client_defined_unique_tag()); + DCHECK(!client_entity.folder()); + DCHECK(!client_entity.deleted()); + ModelType model_type = + syncer::GetModelTypeFromSpecifics(client_entity.specifics()); + string id = client_entity.version() == 0 ? + FakeServerEntity::CreateId(model_type, base::GenerateGUID()) : + client_entity.id_string(); + return new UniqueClientEntity(id, + model_type, + client_entity.version(), + client_entity.name(), + client_entity.client_defined_unique_tag(), + client_entity.specifics(), + client_entity.ctime(), + client_entity.mtime()); +} + +UniqueClientEntity::UniqueClientEntity( + const string& id, + const ModelType& model_type, + int64 version, + const string& name, + const string& client_defined_unique_tag, + const sync_pb::EntitySpecifics& specifics, + int64 creation_time, + int64 last_modified_time) + : FakeServerEntity(id, model_type, version, name), + client_defined_unique_tag_(client_defined_unique_tag), + specifics_(specifics), + creation_time_(creation_time), + last_modified_time_(last_modified_time) { } + +string UniqueClientEntity::GetParentId() const { + // Return a dummy value that cannot be a real parent ID. This type should + // never have parents. + return string(); +} + +sync_pb::SyncEntity* UniqueClientEntity::SerializeAsProto() { + sync_pb::SyncEntity* sync_entity = new sync_pb::SyncEntity(); + FakeServerEntity::SerializeBaseProtoFields(sync_entity); + + sync_pb::EntitySpecifics* specifics = sync_entity->mutable_specifics(); + specifics->CopyFrom(specifics_); + + sync_entity->set_client_defined_unique_tag(client_defined_unique_tag_); + sync_entity->set_ctime(creation_time_); + sync_entity->set_mtime(last_modified_time_); + + return sync_entity; +} + +bool UniqueClientEntity::IsDeleted() const { + return false; +} + +bool UniqueClientEntity::IsFolder() const { + return false; +} + +} // namespace fake_server diff --git a/sync/test/fake_server/unique_client_entity.h b/sync/test/fake_server/unique_client_entity.h new file mode 100644 index 0000000..6069222 --- /dev/null +++ b/sync/test/fake_server/unique_client_entity.h @@ -0,0 +1,50 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SYNC_TEST_FAKE_SERVER_UNIQUE_CLIENT_ENTITY_H_ +#define SYNC_TEST_FAKE_SERVER_UNIQUE_CLIENT_ENTITY_H_ + +#include <string> + +#include "base/basictypes.h" +#include "sync/internal_api/public/base/model_type.h" +#include "sync/protocol/sync.pb.h" +#include "sync/test/fake_server/fake_server_entity.h" + +namespace fake_server { + +// An entity that is unique per client account. +class UniqueClientEntity : public FakeServerEntity { + public: + virtual ~UniqueClientEntity(); + + // Factory function for UniqueClientEntity. + static FakeServerEntity* Create(const sync_pb::SyncEntity& client_entity); + + // FakeServerEntity implementation. + virtual std::string GetParentId() const OVERRIDE; + virtual sync_pb::SyncEntity* SerializeAsProto() OVERRIDE; + virtual bool IsDeleted() const OVERRIDE; + virtual bool IsFolder() const OVERRIDE; + + private: + UniqueClientEntity(const std::string& id, + const syncer::ModelType& model_type, + int64 version, + const std::string& name, + const std::string& client_defined_unique_tag, + const sync_pb::EntitySpecifics& specifics, + int64 creation_time, + int64 last_modified_time); + + // All member values have equivalent fields in SyncEntity. + std::string client_defined_unique_tag_; + sync_pb::EntitySpecifics specifics_; + int64 creation_time_; + int64 last_modified_time_; +}; + +} // namespace fake_server + +#endif // SYNC_TEST_FAKE_SERVER_UNIQUE_CLIENT_ENTITY_H_ |