summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sync/engine/non_blocking_type_processor_unittest.cc257
-rw-r--r--sync/sync_tests.gypi4
-rw-r--r--sync/test/engine/injectable_sync_core_proxy.cc51
-rw-r--r--sync/test/engine/injectable_sync_core_proxy.h47
-rw-r--r--sync/test/engine/mock_non_blocking_type_processor_core.cc175
-rw-r--r--sync/test/engine/mock_non_blocking_type_processor_core.h82
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_