diff options
-rw-r--r-- | sync/engine/non_blocking_type_processor_unittest.cc | 257 | ||||
-rw-r--r-- | sync/sync_tests.gypi | 4 | ||||
-rw-r--r-- | sync/test/engine/injectable_sync_core_proxy.cc | 51 | ||||
-rw-r--r-- | sync/test/engine/injectable_sync_core_proxy.h | 47 | ||||
-rw-r--r-- | sync/test/engine/mock_non_blocking_type_processor_core.cc | 175 | ||||
-rw-r--r-- | sync/test/engine/mock_non_blocking_type_processor_core.h | 82 |
6 files changed, 385 insertions, 231 deletions
diff --git a/sync/engine/non_blocking_type_processor_unittest.cc b/sync/engine/non_blocking_type_processor_unittest.cc index 3a3ca5c..20ecb24 100644 --- a/sync/engine/non_blocking_type_processor_unittest.cc +++ b/sync/engine/non_blocking_type_processor_unittest.cc @@ -10,103 +10,13 @@ #include "sync/internal_api/public/sync_core_proxy.h" #include "sync/protocol/sync.pb.h" #include "sync/syncable/syncable_util.h" +#include "sync/test/engine/injectable_sync_core_proxy.h" +#include "sync/test/engine/mock_non_blocking_type_processor_core.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { -namespace { - -class MockNonBlockingTypeProcessorCore - : public NonBlockingTypeProcessorCoreInterface { - public: - MockNonBlockingTypeProcessorCore(); - virtual ~MockNonBlockingTypeProcessorCore(); - - virtual void RequestCommits(const CommitRequestDataList& list) OVERRIDE; - - bool is_connected_; - - std::vector<CommitRequestDataList> commit_request_lists_; -}; - -MockNonBlockingTypeProcessorCore::MockNonBlockingTypeProcessorCore() - : is_connected_(false) { -} - -MockNonBlockingTypeProcessorCore::~MockNonBlockingTypeProcessorCore() { -} - -void MockNonBlockingTypeProcessorCore::RequestCommits( - const CommitRequestDataList& list) { - commit_request_lists_.push_back(list); -} - -class MockSyncCoreProxy : public syncer::SyncCoreProxy { - public: - MockSyncCoreProxy(); - virtual ~MockSyncCoreProxy(); - - virtual void ConnectTypeToCore( - syncer::ModelType type, - const DataTypeState& data_type_state, - base::WeakPtr<syncer::NonBlockingTypeProcessor> type_processor) OVERRIDE; - virtual void Disconnect(syncer::ModelType type) OVERRIDE; - virtual scoped_ptr<SyncCoreProxy> Clone() const OVERRIDE; - - MockNonBlockingTypeProcessorCore* GetMockProcessorCore(); - - private: - explicit MockSyncCoreProxy(MockNonBlockingTypeProcessorCore*); - - // The NonBlockingTypeProcessor's contract expects that it gets to own this - // object, so we can retain only a non-owned pointer to it. - // - // This is very unsafe, but we can get away with it since these tests are not - // exercising the processor <-> processor_core connection code. - MockNonBlockingTypeProcessorCore* mock_core_; -}; - -MockSyncCoreProxy::MockSyncCoreProxy() - : mock_core_(new MockNonBlockingTypeProcessorCore) { -} - -MockSyncCoreProxy::MockSyncCoreProxy(MockNonBlockingTypeProcessorCore* core) - : mock_core_(core) { -} - -MockSyncCoreProxy::~MockSyncCoreProxy() { -} - -void MockSyncCoreProxy::ConnectTypeToCore( - syncer::ModelType type, - const DataTypeState& data_type_state, - base::WeakPtr<syncer::NonBlockingTypeProcessor> type_processor) { - // This class is allowed to participate in only one connection. - DCHECK(!mock_core_->is_connected_); - mock_core_->is_connected_ = true; - - // Hands off ownership of our member to the type_processor, while keeping - // an unsafe pointer to it. This is why we can only connect once. - scoped_ptr<NonBlockingTypeProcessorCoreInterface> core(mock_core_); - - type_processor->OnConnect(core.Pass()); -} - -void MockSyncCoreProxy::Disconnect(syncer::ModelType type) { - // This mock object is not meant for connect and disconnect tests. - NOTREACHED() << "Not implemented"; -} - -scoped_ptr<SyncCoreProxy> MockSyncCoreProxy::Clone() const { - // There's no sensible way to clone this MockSyncCoreProxy. - return scoped_ptr<SyncCoreProxy>(new MockSyncCoreProxy(mock_core_)); -} - -MockNonBlockingTypeProcessorCore* MockSyncCoreProxy::GetMockProcessorCore() { - return mock_core_; -} - -} // namespace +static const ModelType kModelType = PREFERENCES; // Tests the sync engine parts of NonBlockingTypeProcessor. // @@ -169,37 +79,32 @@ class NonBlockingTypeProcessorTest : public ::testing::Test { void SuccessfulCommitResponse(const CommitRequestData& request_data); private: - std::string GenerateId(const std::string& tag) const; - std::string GenerateTagHash(const std::string& tag) const; - sync_pb::EntitySpecifics GenerateSpecifics(const std::string& tag, - const std::string& value) const; + static std::string GenerateTagHash(const std::string& tag); + static sync_pb::EntitySpecifics GenerateSpecifics(const std::string& tag, + const std::string& value); int64 GetServerVersion(const std::string& tag); void SetServerVersion(const std::string& tag, int64 version); - const ModelType type_; - - scoped_ptr<MockSyncCoreProxy> mock_sync_core_proxy_; - scoped_ptr<NonBlockingTypeProcessor> processor_; MockNonBlockingTypeProcessorCore* mock_processor_core_; + scoped_ptr<InjectableSyncCoreProxy> injectable_sync_core_proxy_; + scoped_ptr<NonBlockingTypeProcessor> processor_; DataTypeState data_type_state_; - - std::map<const std::string, int64> server_versions_; }; NonBlockingTypeProcessorTest::NonBlockingTypeProcessorTest() - : type_(PREFERENCES), - mock_sync_core_proxy_(new MockSyncCoreProxy()), - processor_(new NonBlockingTypeProcessor(type_)) { + : mock_processor_core_(new MockNonBlockingTypeProcessorCore()), + injectable_sync_core_proxy_( + new InjectableSyncCoreProxy(mock_processor_core_)), + processor_(new NonBlockingTypeProcessor(kModelType)) { } NonBlockingTypeProcessorTest::~NonBlockingTypeProcessorTest() { } void NonBlockingTypeProcessorTest::FirstTimeInitialize() { - processor_->Enable(mock_sync_core_proxy_->Clone()); - mock_processor_core_ = mock_sync_core_proxy_->GetMockProcessorCore(); + processor_->Enable(injectable_sync_core_proxy_->Clone()); } void NonBlockingTypeProcessorTest::InitializeToReadyState() { @@ -232,27 +137,11 @@ void NonBlockingTypeProcessorTest::UpdateFromServer(int64 version_offset, const std::string& tag, const std::string& value) { const std::string tag_hash = GenerateTagHash(tag); - - // Overwrite the existing server version if this is the new highest version. - int64 old_version = GetServerVersion(tag_hash); - int64 version = old_version + version_offset; - if (version > old_version) { - SetServerVersion(tag_hash, version); - } - - UpdateResponseData data; - data.id = GenerateId(tag_hash); - data.client_tag_hash = tag_hash; - data.response_version = version; - data.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1); - data.mtime = data.ctime + base::TimeDelta::FromSeconds(version); - data.non_unique_name = tag; - data.deleted = false; - data.specifics = GenerateSpecifics(tag, value); + UpdateResponseData data = mock_processor_core_->UpdateFromServer( + version_offset, tag_hash, GenerateSpecifics(tag, value)); UpdateResponseDataList list; list.push_back(data); - processor_->OnUpdateReceived(data_type_state_, list); } @@ -260,85 +149,30 @@ void NonBlockingTypeProcessorTest::TombstoneFromServer(int64 version_offset, const std::string& tag) { // Overwrite the existing server version if this is the new highest version. std::string tag_hash = GenerateTagHash(tag); - int64 old_version = GetServerVersion(tag_hash); - int64 version = old_version + version_offset; - if (version > old_version) { - SetServerVersion(tag_hash, version); - } - - UpdateResponseData data; - data.id = GenerateId(tag_hash); - data.client_tag_hash = tag_hash; - data.response_version = version; - data.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1); - data.mtime = data.ctime + base::TimeDelta::FromSeconds(version); - data.non_unique_name = tag; - data.deleted = true; + + UpdateResponseData data = + mock_processor_core_->TombstoneFromServer(version_offset, tag_hash); UpdateResponseDataList list; list.push_back(data); - processor_->OnUpdateReceived(data_type_state_, list); } void NonBlockingTypeProcessorTest::SuccessfulCommitResponse( const CommitRequestData& request_data) { - const std::string& client_tag_hash = request_data.client_tag_hash; - CommitResponseData response_data; - - if (request_data.base_version == 0) { - // Server assigns new ID to newly committed items. - DCHECK(request_data.id.empty()); - response_data.id = request_data.id; - } else { - // Otherwise we reuse the ID from the request. - response_data.id = GenerateId(client_tag_hash); - } - - response_data.client_tag_hash = client_tag_hash; - response_data.sequence_number = request_data.sequence_number; - - // Increment the server version on successful commit. - int64 version = GetServerVersion(client_tag_hash); - version++; - SetServerVersion(client_tag_hash, version); - - response_data.response_version = version; - CommitResponseDataList list; - list.push_back(response_data); - + list.push_back(mock_processor_core_->SuccessfulCommitResponse(request_data)); processor_->OnCommitCompletion(data_type_state_, list); } -int64 NonBlockingTypeProcessorTest::GetServerVersion(const std::string& tag) { - std::map<const std::string, int64>::const_iterator it; - it = server_versions_.find(tag); - if (it == server_versions_.end()) { - return 0; - } else { - return it->second; - } -} - -void NonBlockingTypeProcessorTest::SetServerVersion(const std::string& tag_hash, - int64 version) { - server_versions_[tag_hash] = version; -} - -std::string NonBlockingTypeProcessorTest::GenerateId( - const std::string& tag) const { - return "FakeId:" + tag; -} - std::string NonBlockingTypeProcessorTest::GenerateTagHash( - const std::string& tag) const { - return syncable::GenerateSyncableHash(type_, tag); + const std::string& tag) { + return syncable::GenerateSyncableHash(kModelType, tag); } sync_pb::EntitySpecifics NonBlockingTypeProcessorTest::GenerateSpecifics( const std::string& tag, - const std::string& value) const { + const std::string& value) { sync_pb::EntitySpecifics specifics; specifics.mutable_preference()->set_name(tag); specifics.mutable_preference()->set_value(value); @@ -346,63 +180,24 @@ sync_pb::EntitySpecifics NonBlockingTypeProcessorTest::GenerateSpecifics( } size_t NonBlockingTypeProcessorTest::GetNumCommitRequestLists() { - return mock_processor_core_->commit_request_lists_.size(); + return mock_processor_core_->GetNumCommitRequestLists(); } CommitRequestDataList NonBlockingTypeProcessorTest::GetNthCommitRequestList( size_t n) { - DCHECK_LT(n, GetNumCommitRequestLists()); - return mock_processor_core_->commit_request_lists_[n]; + return mock_processor_core_->GetNthCommitRequestList(n); } bool NonBlockingTypeProcessorTest::HasCommitRequestForTag( const std::string& tag) { const std::string tag_hash = GenerateTagHash(tag); - const std::vector<CommitRequestDataList>& lists = - mock_processor_core_->commit_request_lists_; - - // Iterate backward through the sets of commit requests to find the most - // recent one that applies to the specified tag. - for (std::vector<CommitRequestDataList>::const_reverse_iterator lists_it = - lists.rbegin(); - lists_it != lists.rend(); - ++lists_it) { - for (CommitRequestDataList::const_iterator it = lists_it->begin(); - it != lists_it->end(); - ++it) { - if (it->client_tag_hash == tag_hash) { - return true; - } - } - } - - return false; + return mock_processor_core_->HasCommitRequestForTagHash(tag_hash); } CommitRequestData NonBlockingTypeProcessorTest::GetLatestCommitRequestForTag( const std::string& tag) { const std::string tag_hash = GenerateTagHash(tag); - const std::vector<CommitRequestDataList>& lists = - mock_processor_core_->commit_request_lists_; - - // Iterate backward through the sets of commit requests to find the most - // recent one that applies to the specified tag. - for (std::vector<CommitRequestDataList>::const_reverse_iterator lists_it = - lists.rbegin(); - lists_it != lists.rend(); - ++lists_it) { - for (CommitRequestDataList::const_iterator it = lists_it->begin(); - it != lists_it->end(); - ++it) { - if (it->client_tag_hash == tag_hash) { - return *it; - } - } - } - - NOTREACHED() << "Could not find any commits for given tag " << tag << ". " - << "Test should have checked HasCommitRequestForTag() first."; - return CommitRequestData(); + return mock_processor_core_->GetLatestCommitRequestForTagHash(tag_hash); } // Creates a new item locally. diff --git a/sync/sync_tests.gypi b/sync/sync_tests.gypi index d11dbde..4cb5d17 100644 --- a/sync/sync_tests.gypi +++ b/sync/sync_tests.gypi @@ -40,6 +40,8 @@ 'test/engine/fake_sync_scheduler.h', 'test/engine/mock_connection_manager.cc', 'test/engine/mock_connection_manager.h', + 'test/engine/mock_non_blocking_type_processor_core.cc', + 'test/engine/mock_non_blocking_type_processor_core.h', 'test/engine/mock_update_handler.cc', 'test/engine/mock_update_handler.h', 'test/engine/test_directory_setter_upper.cc', @@ -47,6 +49,8 @@ 'test/engine/test_id_factory.h', 'test/engine/test_syncable_utils.cc', 'test/engine/test_syncable_utils.h', + 'test/engine/injectable_sync_core_proxy.cc', + 'test/engine/injectable_sync_core_proxy.h', 'test/fake_encryptor.cc', 'test/fake_encryptor.h', 'test/fake_sync_encryption_handler.cc', diff --git a/sync/test/engine/injectable_sync_core_proxy.cc b/sync/test/engine/injectable_sync_core_proxy.cc new file mode 100644 index 0000000..ac96ca4 --- /dev/null +++ b/sync/test/engine/injectable_sync_core_proxy.cc @@ -0,0 +1,51 @@ +// 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/engine/injectable_sync_core_proxy.h" + +#include "sync/engine/non_blocking_type_processor.h" +#include "sync/engine/non_blocking_type_processor_core_interface.h" + +namespace syncer { + +InjectableSyncCoreProxy::InjectableSyncCoreProxy( + NonBlockingTypeProcessorCoreInterface* core) + : is_core_connected_(false), processor_core_(core) { +} + +InjectableSyncCoreProxy::~InjectableSyncCoreProxy() { +} + +void InjectableSyncCoreProxy::ConnectTypeToCore( + syncer::ModelType type, + const DataTypeState& data_type_state, + base::WeakPtr<syncer::NonBlockingTypeProcessor> type_processor) { + // This class is allowed to participate in only one connection. + DCHECK(!is_core_connected_); + is_core_connected_ = true; + + // Hands off ownership of our member to the type_processor, while keeping + // an unsafe pointer to it. This is why we can only connect once. + scoped_ptr<NonBlockingTypeProcessorCoreInterface> core(processor_core_); + + type_processor->OnConnect(core.Pass()); +} + +void InjectableSyncCoreProxy::Disconnect(syncer::ModelType type) { + // This mock object is not meant for connect and disconnect tests. + NOTREACHED() << "Not implemented"; +} + +scoped_ptr<SyncCoreProxy> InjectableSyncCoreProxy::Clone() const { + // This confuses ownership. We trust that our callers are well-behaved. + return scoped_ptr<SyncCoreProxy>( + new InjectableSyncCoreProxy(processor_core_)); +} + +NonBlockingTypeProcessorCoreInterface* +InjectableSyncCoreProxy::GetProcessorCore() { + return processor_core_; +} + +} // namespace syncer diff --git a/sync/test/engine/injectable_sync_core_proxy.h b/sync/test/engine/injectable_sync_core_proxy.h new file mode 100644 index 0000000..2dc273d --- /dev/null +++ b/sync/test/engine/injectable_sync_core_proxy.h @@ -0,0 +1,47 @@ +// 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_ENGINE_INJECTABLE_SYNC_CORE_PROXY_H_ +#define SYNC_TEST_ENGINE_INJECTABLE_SYNC_CORE_PROXY_H_ + +#include "sync/internal_api/public/base/model_type.h" +#include "sync/internal_api/public/sync_core_proxy.h" + +namespace syncer { + +struct DataTypeState; +class NonBlockingTypeProcessor; +class NonBlockingTypeProcessorCoreInterface; + +// A SyncCoreProxy implementation that, when a connection request is made, +// initalizes a connection to a previously injected NonBlockingTypeProcessor. +class InjectableSyncCoreProxy : public syncer::SyncCoreProxy { + public: + explicit InjectableSyncCoreProxy(NonBlockingTypeProcessorCoreInterface* core); + virtual ~InjectableSyncCoreProxy(); + + virtual void ConnectTypeToCore( + syncer::ModelType type, + const DataTypeState& data_type_state, + base::WeakPtr<syncer::NonBlockingTypeProcessor> type_processor) OVERRIDE; + virtual void Disconnect(syncer::ModelType type) OVERRIDE; + virtual scoped_ptr<SyncCoreProxy> Clone() const OVERRIDE; + + NonBlockingTypeProcessorCoreInterface* GetProcessorCore(); + + private: + // A flag to ensure ConnectTypeToCore is called at most once. + bool is_core_connected_; + + // The NonBlockingTypeProcessor's contract expects that it gets to own this + // object, so we can retain only a non-owned pointer to it. + // + // This is very unsafe, but we can get away with it since these tests are not + // exercising the processor <-> processor_core connection code. + NonBlockingTypeProcessorCoreInterface* processor_core_; +}; + +} // namespace syncer + +#endif // SYNC_TEST_ENGINE_INJECTABLE_SYNC_CORE_PROXY_H_ diff --git a/sync/test/engine/mock_non_blocking_type_processor_core.cc b/sync/test/engine/mock_non_blocking_type_processor_core.cc new file mode 100644 index 0000000..b164c2a --- /dev/null +++ b/sync/test/engine/mock_non_blocking_type_processor_core.cc @@ -0,0 +1,175 @@ +// 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/engine/mock_non_blocking_type_processor_core.h" + +#include "base/logging.h" + +namespace syncer { + +MockNonBlockingTypeProcessorCore::MockNonBlockingTypeProcessorCore() { +} + +MockNonBlockingTypeProcessorCore::~MockNonBlockingTypeProcessorCore() { +} + +void MockNonBlockingTypeProcessorCore::RequestCommits( + const CommitRequestDataList& list) { + commit_request_lists_.push_back(list); +} + +size_t MockNonBlockingTypeProcessorCore::GetNumCommitRequestLists() const { + return commit_request_lists_.size(); +} + +CommitRequestDataList MockNonBlockingTypeProcessorCore::GetNthCommitRequestList( + size_t n) const { + DCHECK_LT(n, GetNumCommitRequestLists()); + return commit_request_lists_[n]; +} + +bool MockNonBlockingTypeProcessorCore::HasCommitRequestForTagHash( + const std::string& tag_hash) const { + // Iterate backward through the sets of commit requests to find the most + // recent one that applies to the specified tag_hash. + for (std::vector<CommitRequestDataList>::const_reverse_iterator lists_it = + commit_request_lists_.rbegin(); + lists_it != commit_request_lists_.rend(); + ++lists_it) { + for (CommitRequestDataList::const_iterator it = lists_it->begin(); + it != lists_it->end(); + ++it) { + if (it->client_tag_hash == tag_hash) { + return true; + } + } + } + + return false; +} + +CommitRequestData +MockNonBlockingTypeProcessorCore::GetLatestCommitRequestForTagHash( + const std::string& tag_hash) const { + // Iterate backward through the sets of commit requests to find the most + // recent one that applies to the specified tag_hash. + for (std::vector<CommitRequestDataList>::const_reverse_iterator lists_it = + commit_request_lists_.rbegin(); + lists_it != commit_request_lists_.rend(); + ++lists_it) { + for (CommitRequestDataList::const_iterator it = lists_it->begin(); + it != lists_it->end(); + ++it) { + if (it->client_tag_hash == tag_hash) { + return *it; + } + } + } + + NOTREACHED() << "Could not find commit for tag hash " << tag_hash << "."; + return CommitRequestData(); +} + +UpdateResponseData MockNonBlockingTypeProcessorCore::UpdateFromServer( + int64 version_offset, + const std::string& tag_hash, + const sync_pb::EntitySpecifics& specifics) { + // Overwrite the existing server version if this is the new highest version. + int64 old_version = GetServerVersion(tag_hash); + int64 version = old_version + version_offset; + if (version > old_version) { + SetServerVersion(tag_hash, version); + } + + UpdateResponseData data; + data.id = GenerateId(tag_hash); + data.client_tag_hash = tag_hash; + data.response_version = version; + data.deleted = false; + data.specifics = specifics; + + // These elements should have no effect on behavior, but we set them anyway + // so we can test they are properly copied around the system if we want to. + data.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1); + data.mtime = data.ctime + base::TimeDelta::FromSeconds(version); + data.non_unique_name = specifics.preference().name(); + + return data; +} + +UpdateResponseData MockNonBlockingTypeProcessorCore::TombstoneFromServer( + int64 version_offset, + const std::string& tag_hash) { + int64 old_version = GetServerVersion(tag_hash); + int64 version = old_version + version_offset; + if (version > old_version) { + SetServerVersion(tag_hash, version); + } + + UpdateResponseData data; + data.id = GenerateId(tag_hash); + data.client_tag_hash = tag_hash; + data.response_version = version; + data.deleted = true; + + // These elements should have no effect on behavior, but we set them anyway + // so we can test they are properly copied around the system if we want to. + data.ctime = base::Time::UnixEpoch() + base::TimeDelta::FromDays(1); + data.mtime = data.ctime + base::TimeDelta::FromSeconds(version); + data.non_unique_name = "Name Non Unique"; + + return data; +} + +CommitResponseData MockNonBlockingTypeProcessorCore::SuccessfulCommitResponse( + const CommitRequestData& request_data) { + const std::string& client_tag_hash = request_data.client_tag_hash; + + CommitResponseData response_data; + + if (request_data.base_version == 0) { + // Server assigns new ID to newly committed items. + DCHECK(request_data.id.empty()); + response_data.id = request_data.id; + } else { + // Otherwise we reuse the ID from the request. + response_data.id = GenerateId(client_tag_hash); + } + + response_data.client_tag_hash = client_tag_hash; + response_data.sequence_number = request_data.sequence_number; + + // Increment the server version on successful commit. + int64 version = GetServerVersion(client_tag_hash); + version++; + SetServerVersion(client_tag_hash, version); + + response_data.response_version = version; + + return response_data; +} + +std::string MockNonBlockingTypeProcessorCore::GenerateId( + const std::string& tag_hash) { + return "FakeId:" + tag_hash; +} + +int64 MockNonBlockingTypeProcessorCore::GetServerVersion( + const std::string& tag_hash) { + std::map<const std::string, int64>::const_iterator it; + it = server_versions_.find(tag_hash); + if (it == server_versions_.end()) { + return 0; + } else { + return it->second; + } +} + +void MockNonBlockingTypeProcessorCore::SetServerVersion( + const std::string& tag_hash, + int64 version) { + server_versions_[tag_hash] = version; +} + +} // namespace syncer diff --git a/sync/test/engine/mock_non_blocking_type_processor_core.h b/sync/test/engine/mock_non_blocking_type_processor_core.h new file mode 100644 index 0000000..2ee73a4 --- /dev/null +++ b/sync/test/engine/mock_non_blocking_type_processor_core.h @@ -0,0 +1,82 @@ +// 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_ENGINE_MOCK_NON_BLOCKING_TYPE_PROCESSOR_CORE_H_ +#define SYNC_TEST_ENGINE_MOCK_NON_BLOCKING_TYPE_PROCESSOR_CORE_H_ + +#include <vector> + +#include "base/macros.h" +#include "sync/engine/non_blocking_sync_common.h" +#include "sync/engine/non_blocking_type_processor_core_interface.h" + +namespace syncer { + +// Receives and records commit requests sent through the +// NonBlockingTypeProcessorCoreInterface. +// +// This class also includes features intended to help mock out server behavior. +// It has some basic functionality to keep track of server state and generate +// plausible UpdateResponseData and CommitResponseData messages. +class MockNonBlockingTypeProcessorCore + : public NonBlockingTypeProcessorCoreInterface { + public: + MockNonBlockingTypeProcessorCore(); + virtual ~MockNonBlockingTypeProcessorCore(); + + // Implementation of NonBlockingTypeProcessorCoreInterface. + virtual void RequestCommits(const CommitRequestDataList& list) OVERRIDE; + + // Getters to inspect the requests sent to this object. + size_t GetNumCommitRequestLists() const; + CommitRequestDataList GetNthCommitRequestList(size_t n) const; + bool HasCommitRequestForTagHash(const std::string& tag_hash) const; + CommitRequestData GetLatestCommitRequestForTagHash( + const std::string& tag_hash) const; + + // Functions to produce state as though it came from a real server and had + // been filtered through a real NonBlockinTypeProcessorCore. + + // Returns an UpdateResponseData representing an update received from + // the server. Updates server state accordingly. + // + // The |version_offset| field can be used to emulate stale data (ie. versions + // going backwards), reflections and redeliveries (ie. several instances of + // the same version) or new updates. + UpdateResponseData UpdateFromServer( + int64 version_offset, + const std::string& tag_hash, + const sync_pb::EntitySpecifics& specifics); + + // Returns an UpdateResponseData representing a tombstone update from the + // server. Updates server state accordingly. + UpdateResponseData TombstoneFromServer(int64 version_offset, + const std::string& tag_hash); + + // Returns a commit response that indicates a successful commit of the + // given |request_data|. Updates server state accordingly. + CommitResponseData SuccessfulCommitResponse( + const CommitRequestData& request_data); + + private: + // Generate an ID string. + static std::string GenerateId(const std::string& tag_hash); + + // Retrieve or set the server version. + int64 GetServerVersion(const std::string& tag_hash); + void SetServerVersion(const std::string& tag_hash, int64 version); + + // A record of past commits requests. + std::vector<CommitRequestDataList> commit_request_lists_; + + // Map of versions by client tag. + // This is an essential part of the mocked server state. + std::map<const std::string, int64> server_versions_; + + DISALLOW_COPY_AND_ASSIGN(MockNonBlockingTypeProcessorCore); +}; + +} // namespace syncer + +#endif // SYNC_TEST_ENGINE_MOCK_NON_BLOCKING_TYPE_PROCESSOR_CORE_H_ |