| Index: sync/engine/non_blocking_type_processor_core_unittest.cc
|
| diff --git a/sync/engine/non_blocking_type_processor_core_unittest.cc b/sync/engine/non_blocking_type_processor_core_unittest.cc
|
| deleted file mode 100644
|
| index c775a331d3b311cf5cb1d73ab379ccda79bac97d..0000000000000000000000000000000000000000
|
| --- a/sync/engine/non_blocking_type_processor_core_unittest.cc
|
| +++ /dev/null
|
| @@ -1,604 +0,0 @@
|
| -// 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/engine/non_blocking_type_processor_core.h"
|
| -
|
| -#include "sync/engine/commit_contribution.h"
|
| -#include "sync/engine/non_blocking_sync_common.h"
|
| -#include "sync/engine/non_blocking_type_processor_interface.h"
|
| -#include "sync/internal_api/public/base/model_type.h"
|
| -#include "sync/protocol/sync.pb.h"
|
| -#include "sync/sessions/status_controller.h"
|
| -#include "sync/syncable/syncable_util.h"
|
| -#include "sync/test/engine/mock_non_blocking_type_processor.h"
|
| -#include "sync/test/engine/single_type_mock_server.h"
|
| -
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -static const std::string kTypeParentId = "PrefsRootNodeID";
|
| -static const syncer::ModelType kModelType = syncer::PREFERENCES;
|
| -
|
| -namespace syncer {
|
| -
|
| -// Tests the NonBlockingTypeProcessorCore.
|
| -//
|
| -// This class passes messages between the model thread and sync server.
|
| -// As such, its code is subject to lots of different race conditions. This
|
| -// test harness lets us exhaustively test all possible races. We try to
|
| -// focus on just a few interesting cases.
|
| -//
|
| -// Inputs:
|
| -// - Initial data type state from the model thread.
|
| -// - Commit requests from the model thread.
|
| -// - Update responses from the server.
|
| -// - Commit responses from the server.
|
| -//
|
| -// Outputs:
|
| -// - Commit requests to the server.
|
| -// - Commit responses to the model thread.
|
| -// - Update responses to the model thread.
|
| -// - Nudges to the sync scheduler.
|
| -//
|
| -// We use the MockNonBlockingTypeProcessor to stub out all communication
|
| -// with the model thread. That interface is synchronous, which makes it
|
| -// much easier to test races.
|
| -//
|
| -// The interface with the server is built around "pulling" data from this
|
| -// class, so we don't have to mock out any of it. We wrap it with some
|
| -// convenience functions to we can emulate server behavior.
|
| -class NonBlockingTypeProcessorCoreTest : public ::testing::Test {
|
| - public:
|
| - NonBlockingTypeProcessorCoreTest();
|
| - virtual ~NonBlockingTypeProcessorCoreTest();
|
| -
|
| - // One of these Initialize functions should be called at the beginning of
|
| - // each test.
|
| -
|
| - // Initializes with no data type state. We will be unable to perform any
|
| - // significant server action until we receive an update response that
|
| - // contains the type root node for this type.
|
| - void FirstInitialize();
|
| -
|
| - // Initializes with some existing data type state. Allows us to start
|
| - // committing items right away.
|
| - void NormalInitialize();
|
| -
|
| - // Initialize with a custom initial DataTypeState.
|
| - void InitializeWithState(const DataTypeState& state);
|
| -
|
| - // Modifications on the model thread that get sent to the core under test.
|
| - void CommitRequest(const std::string& tag, const std::string& value);
|
| - void DeleteRequest(const std::string& tag);
|
| -
|
| - // Pretends to receive update messages from the server.
|
| - void TriggerTypeRootUpdateFromServer();
|
| - void TriggerUpdateFromServer(int64 version_offset,
|
| - const std::string& tag,
|
| - const std::string& value);
|
| - void TriggerTombstoneFromServer(int64 version_offset, const std::string& tag);
|
| -
|
| - // By default, this harness behaves as if all tasks posted to the model
|
| - // thread are executed immediately. However, this is not necessarily true.
|
| - // The model's TaskRunner has a queue, and the tasks we post to it could
|
| - // linger there for a while. In the meantime, the model thread could
|
| - // continue posting tasks to the core based on its stale state.
|
| - //
|
| - // If you want to test those race cases, then these functions are for you.
|
| - void SetModelThreadIsSynchronous(bool is_synchronous);
|
| - void PumpModelThread();
|
| -
|
| - // Returns true if the |core_| is ready to commit something.
|
| - bool WillCommit();
|
| -
|
| - // Pretend to successfully commit all outstanding unsynced items.
|
| - // It is safe to call this only if WillCommit() returns true.
|
| - void DoSuccessfulCommit();
|
| -
|
| - // Read commit messages the core_ sent to the emulated server.
|
| - size_t GetNumCommitMessagesOnServer() const;
|
| - sync_pb::ClientToServerMessage GetNthCommitMessageOnServer(size_t n) const;
|
| -
|
| - // Read the latest version of sync entities committed to the emulated server.
|
| - bool HasCommitEntityOnServer(const std::string& tag) const;
|
| - sync_pb::SyncEntity GetLatestCommitEntityOnServer(
|
| - const std::string& tag) const;
|
| -
|
| - // Read the latest update messages received on the model thread.
|
| - // Note that if the model thread is in non-blocking mode, this data will not
|
| - // be updated until the response is actually processed by the model thread.
|
| - size_t GetNumModelThreadUpdateResponses() const;
|
| - UpdateResponseDataList GetNthModelThreadUpdateResponse(size_t n) const;
|
| - DataTypeState GetNthModelThreadUpdateState(size_t n) const;
|
| -
|
| - // Reads the latest update response datas on the model thread.
|
| - // Note that if the model thread is in non-blocking mode, this data will not
|
| - // be updated until the response is actually processed by the model thread.
|
| - bool HasUpdateResponseOnModelThread(const std::string& tag) const;
|
| - UpdateResponseData GetUpdateResponseOnModelThread(
|
| - const std::string& tag) const;
|
| -
|
| - // Read the latest commit messages received on the model thread.
|
| - // Note that if the model thread is in non-blocking mode, this data will not
|
| - // be updated until the response is actually processed by the model thread.
|
| - size_t GetNumModelThreadCommitResponses() const;
|
| - CommitResponseDataList GetNthModelThreadCommitResponse(size_t n) const;
|
| - DataTypeState GetNthModelThreadCommitState(size_t n) const;
|
| -
|
| - // Reads the latest commit response datas on the model thread.
|
| - // Note that if the model thread is in non-blocking mode, this data will not
|
| - // be updated until the response is actually processed by the model thread.
|
| - bool HasCommitResponseOnModelThread(const std::string& tag) const;
|
| - CommitResponseData GetCommitResponseOnModelThread(
|
| - const std::string& tag) const;
|
| -
|
| - // Helpers for building various messages and structures.
|
| - static std::string GenerateTagHash(const std::string& tag);
|
| - static sync_pb::EntitySpecifics GenerateSpecifics(const std::string& tag,
|
| - const std::string& value);
|
| -
|
| - private:
|
| - // The NonBlockingTypeProcessorCore being tested.
|
| - scoped_ptr<NonBlockingTypeProcessorCore> core_;
|
| -
|
| - // Non-owned, possibly NULL pointer. This object belongs to the
|
| - // NonBlockingTypeProcessorCore under test.
|
| - MockNonBlockingTypeProcessor* mock_processor_;
|
| -
|
| - // A mock that emulates enough of the sync server that it can be used
|
| - // a single UpdateHandler and CommitContributor pair. In this test
|
| - // harness, the |core_| is both of them.
|
| - SingleTypeMockServer mock_server_;
|
| -};
|
| -
|
| -NonBlockingTypeProcessorCoreTest::NonBlockingTypeProcessorCoreTest()
|
| - : mock_processor_(NULL), mock_server_(kModelType) {
|
| -}
|
| -
|
| -NonBlockingTypeProcessorCoreTest::~NonBlockingTypeProcessorCoreTest() {
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::FirstInitialize() {
|
| - DataTypeState initial_state;
|
| - initial_state.progress_marker.set_data_type_id(
|
| - GetSpecificsFieldNumberFromModelType(kModelType));
|
| - initial_state.next_client_id = 0;
|
| -
|
| - InitializeWithState(initial_state);
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::NormalInitialize() {
|
| - DataTypeState initial_state;
|
| - initial_state.progress_marker.set_data_type_id(
|
| - GetSpecificsFieldNumberFromModelType(kModelType));
|
| - initial_state.progress_marker.set_token("some_saved_progress_token");
|
| -
|
| - initial_state.next_client_id = 10;
|
| - initial_state.type_root_id = kTypeParentId;
|
| - initial_state.initial_sync_done = true;
|
| -
|
| - InitializeWithState(initial_state);
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::InitializeWithState(
|
| - const DataTypeState& state) {
|
| - DCHECK(!core_);
|
| -
|
| - // We don't get to own this interace. The |core_| keeps a scoped_ptr to it.
|
| - mock_processor_ = new MockNonBlockingTypeProcessor();
|
| - scoped_ptr<NonBlockingTypeProcessorInterface> interface(mock_processor_);
|
| -
|
| - core_.reset(
|
| - new NonBlockingTypeProcessorCore(kModelType, state, interface.Pass()));
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::CommitRequest(const std::string& name,
|
| - const std::string& value) {
|
| - const std::string tag_hash = GenerateTagHash(name);
|
| - CommitRequestData data =
|
| - mock_processor_->CommitRequest(tag_hash, GenerateSpecifics(name, value));
|
| - CommitRequestDataList list;
|
| - list.push_back(data);
|
| - core_->EnqueueForCommit(list);
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::DeleteRequest(const std::string& tag) {
|
| - const std::string tag_hash = GenerateTagHash(tag);
|
| - CommitRequestData data = mock_processor_->DeleteRequest(tag_hash);
|
| - CommitRequestDataList list;
|
| - list.push_back(data);
|
| - core_->EnqueueForCommit(list);
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::TriggerTypeRootUpdateFromServer() {
|
| - sync_pb::SyncEntity entity = mock_server_.TypeRootUpdate();
|
| - SyncEntityList entity_list;
|
| - entity_list.push_back(&entity);
|
| -
|
| - sessions::StatusController dummy_status;
|
| -
|
| - core_->ProcessGetUpdatesResponse(mock_server_.GetProgress(),
|
| - mock_server_.GetContext(),
|
| - entity_list,
|
| - &dummy_status);
|
| - core_->ApplyUpdates(&dummy_status);
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::TriggerUpdateFromServer(
|
| - int64 version_offset,
|
| - const std::string& tag,
|
| - const std::string& value) {
|
| - sync_pb::SyncEntity entity = mock_server_.UpdateFromServer(
|
| - version_offset, GenerateTagHash(tag), GenerateSpecifics(tag, value));
|
| - SyncEntityList entity_list;
|
| - entity_list.push_back(&entity);
|
| -
|
| - sessions::StatusController dummy_status;
|
| -
|
| - core_->ProcessGetUpdatesResponse(mock_server_.GetProgress(),
|
| - mock_server_.GetContext(),
|
| - entity_list,
|
| - &dummy_status);
|
| - core_->ApplyUpdates(&dummy_status);
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::TriggerTombstoneFromServer(
|
| - int64 version_offset,
|
| - const std::string& tag) {
|
| - sync_pb::SyncEntity entity =
|
| - mock_server_.TombstoneFromServer(version_offset, GenerateTagHash(tag));
|
| - SyncEntityList entity_list;
|
| - entity_list.push_back(&entity);
|
| -
|
| - sessions::StatusController dummy_status;
|
| -
|
| - core_->ProcessGetUpdatesResponse(mock_server_.GetProgress(),
|
| - mock_server_.GetContext(),
|
| - entity_list,
|
| - &dummy_status);
|
| - core_->ApplyUpdates(&dummy_status);
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::SetModelThreadIsSynchronous(
|
| - bool is_synchronous) {
|
| - mock_processor_->SetSynchronousExecution(is_synchronous);
|
| -}
|
| -
|
| -void NonBlockingTypeProcessorCoreTest::PumpModelThread() {
|
| - mock_processor_->RunQueuedTasks();
|
| -}
|
| -
|
| -bool NonBlockingTypeProcessorCoreTest::WillCommit() {
|
| - scoped_ptr<CommitContribution> contribution(core_->GetContribution(INT_MAX));
|
| -
|
| - if (contribution) {
|
| - contribution->CleanUp(); // Gracefully abort the commit.
|
| - return true;
|
| - } else {
|
| - return false;
|
| - }
|
| -}
|
| -
|
| -// Conveniently, this is all one big synchronous operation. The sync thread
|
| -// remains blocked while the commit is in progress, so we don't need to worry
|
| -// about other tasks being run between the time when the commit request is
|
| -// issued and the time when the commit response is received.
|
| -void NonBlockingTypeProcessorCoreTest::DoSuccessfulCommit() {
|
| - DCHECK(WillCommit());
|
| - scoped_ptr<CommitContribution> contribution(core_->GetContribution(INT_MAX));
|
| -
|
| - sync_pb::ClientToServerMessage message;
|
| - contribution->AddToCommitMessage(&message);
|
| -
|
| - sync_pb::ClientToServerResponse response =
|
| - mock_server_.DoSuccessfulCommit(message);
|
| -
|
| - sessions::StatusController dummy_status;
|
| - contribution->ProcessCommitResponse(response, &dummy_status);
|
| - contribution->CleanUp();
|
| -}
|
| -
|
| -size_t NonBlockingTypeProcessorCoreTest::GetNumCommitMessagesOnServer() const {
|
| - return mock_server_.GetNumCommitMessages();
|
| -}
|
| -
|
| -sync_pb::ClientToServerMessage
|
| -NonBlockingTypeProcessorCoreTest::GetNthCommitMessageOnServer(size_t n) const {
|
| - DCHECK_LT(n, GetNumCommitMessagesOnServer());
|
| - return mock_server_.GetNthCommitMessage(n);
|
| -}
|
| -
|
| -bool NonBlockingTypeProcessorCoreTest::HasCommitEntityOnServer(
|
| - const std::string& tag) const {
|
| - const std::string tag_hash = GenerateTagHash(tag);
|
| - return mock_server_.HasCommitEntity(tag_hash);
|
| -}
|
| -
|
| -sync_pb::SyncEntity
|
| -NonBlockingTypeProcessorCoreTest::GetLatestCommitEntityOnServer(
|
| - const std::string& tag) const {
|
| - DCHECK(HasCommitEntityOnServer(tag));
|
| - const std::string tag_hash = GenerateTagHash(tag);
|
| - return mock_server_.GetLastCommittedEntity(tag_hash);
|
| -}
|
| -
|
| -size_t NonBlockingTypeProcessorCoreTest::GetNumModelThreadUpdateResponses()
|
| - const {
|
| - return mock_processor_->GetNumUpdateResponses();
|
| -}
|
| -
|
| -UpdateResponseDataList
|
| -NonBlockingTypeProcessorCoreTest::GetNthModelThreadUpdateResponse(
|
| - size_t n) const {
|
| - DCHECK_LT(n, GetNumModelThreadUpdateResponses());
|
| - return mock_processor_->GetNthUpdateResponse(n);
|
| -}
|
| -
|
| -DataTypeState NonBlockingTypeProcessorCoreTest::GetNthModelThreadUpdateState(
|
| - size_t n) const {
|
| - DCHECK_LT(n, GetNumModelThreadUpdateResponses());
|
| - return mock_processor_->GetNthTypeStateReceivedInUpdateResponse(n);
|
| -}
|
| -
|
| -bool NonBlockingTypeProcessorCoreTest::HasUpdateResponseOnModelThread(
|
| - const std::string& tag) const {
|
| - const std::string tag_hash = GenerateTagHash(tag);
|
| - return mock_processor_->HasUpdateResponse(tag_hash);
|
| -}
|
| -
|
| -UpdateResponseData
|
| -NonBlockingTypeProcessorCoreTest::GetUpdateResponseOnModelThread(
|
| - const std::string& tag) const {
|
| - const std::string tag_hash = GenerateTagHash(tag);
|
| - return mock_processor_->GetUpdateResponse(tag_hash);
|
| -}
|
| -
|
| -size_t NonBlockingTypeProcessorCoreTest::GetNumModelThreadCommitResponses()
|
| - const {
|
| - return mock_processor_->GetNumCommitResponses();
|
| -}
|
| -
|
| -CommitResponseDataList
|
| -NonBlockingTypeProcessorCoreTest::GetNthModelThreadCommitResponse(
|
| - size_t n) const {
|
| - DCHECK_LT(n, GetNumModelThreadCommitResponses());
|
| - return mock_processor_->GetNthCommitResponse(n);
|
| -}
|
| -
|
| -DataTypeState NonBlockingTypeProcessorCoreTest::GetNthModelThreadCommitState(
|
| - size_t n) const {
|
| - DCHECK_LT(n, GetNumModelThreadCommitResponses());
|
| - return mock_processor_->GetNthTypeStateReceivedInCommitResponse(n);
|
| -}
|
| -
|
| -bool NonBlockingTypeProcessorCoreTest::HasCommitResponseOnModelThread(
|
| - const std::string& tag) const {
|
| - const std::string tag_hash = GenerateTagHash(tag);
|
| - return mock_processor_->HasCommitResponse(tag_hash);
|
| -}
|
| -
|
| -CommitResponseData
|
| -NonBlockingTypeProcessorCoreTest::GetCommitResponseOnModelThread(
|
| - const std::string& tag) const {
|
| - DCHECK(HasCommitResponseOnModelThread(tag));
|
| - const std::string tag_hash = GenerateTagHash(tag);
|
| - return mock_processor_->GetCommitResponse(tag_hash);
|
| -}
|
| -
|
| -std::string NonBlockingTypeProcessorCoreTest::GenerateTagHash(
|
| - const std::string& tag) {
|
| - const std::string& client_tag_hash =
|
| - syncable::GenerateSyncableHash(kModelType, tag);
|
| - return client_tag_hash;
|
| -}
|
| -
|
| -sync_pb::EntitySpecifics NonBlockingTypeProcessorCoreTest::GenerateSpecifics(
|
| - const std::string& tag,
|
| - const std::string& value) {
|
| - sync_pb::EntitySpecifics specifics;
|
| - specifics.mutable_preference()->set_name(tag);
|
| - specifics.mutable_preference()->set_value(value);
|
| - return specifics;
|
| -}
|
| -
|
| -// Requests a commit and verifies the messages sent to the client and server as
|
| -// a result.
|
| -//
|
| -// This test performs sanity checks on most of the fields in these messages.
|
| -// For the most part this is checking that the test code behaves as expected
|
| -// and the |core_| doesn't mess up its simple task of moving around these
|
| -// values. It makes sense to have one or two tests that are this thorough, but
|
| -// we shouldn't be this verbose in all tests.
|
| -TEST_F(NonBlockingTypeProcessorCoreTest, SimpleCommit) {
|
| - NormalInitialize();
|
| -
|
| - EXPECT_FALSE(WillCommit());
|
| - EXPECT_EQ(0U, GetNumCommitMessagesOnServer());
|
| - EXPECT_EQ(0U, GetNumModelThreadCommitResponses());
|
| -
|
| - CommitRequest("tag1", "value1");
|
| -
|
| - ASSERT_TRUE(WillCommit());
|
| - DoSuccessfulCommit();
|
| -
|
| - const std::string& client_tag_hash = GenerateTagHash("tag1");
|
| -
|
| - // Exhaustively verify the SyncEntity sent in the commit message.
|
| - ASSERT_EQ(1U, GetNumCommitMessagesOnServer());
|
| - EXPECT_EQ(1, GetNthCommitMessageOnServer(0).commit().entries_size());
|
| - ASSERT_TRUE(HasCommitEntityOnServer("tag1"));
|
| - const sync_pb::SyncEntity& entity = GetLatestCommitEntityOnServer("tag1");
|
| - EXPECT_FALSE(entity.id_string().empty());
|
| - EXPECT_EQ(kTypeParentId, entity.parent_id_string());
|
| - EXPECT_EQ(kUncommittedVersion, entity.version());
|
| - EXPECT_NE(0, entity.mtime());
|
| - EXPECT_NE(0, entity.ctime());
|
| - EXPECT_FALSE(entity.name().empty());
|
| - EXPECT_EQ(client_tag_hash, entity.client_defined_unique_tag());
|
| - EXPECT_EQ("tag1", entity.specifics().preference().name());
|
| - EXPECT_FALSE(entity.deleted());
|
| - EXPECT_EQ("value1", entity.specifics().preference().value());
|
| -
|
| - // Exhaustively verify the commit response returned to the model thread.
|
| - ASSERT_EQ(1U, GetNumModelThreadCommitResponses());
|
| - EXPECT_EQ(1U, GetNthModelThreadCommitResponse(0).size());
|
| - ASSERT_TRUE(HasCommitResponseOnModelThread("tag1"));
|
| - const CommitResponseData& commit_response =
|
| - GetCommitResponseOnModelThread("tag1");
|
| -
|
| - // The ID changes in a commit response to initial commit.
|
| - EXPECT_FALSE(commit_response.id.empty());
|
| - EXPECT_NE(entity.id_string(), commit_response.id);
|
| -
|
| - EXPECT_EQ(client_tag_hash, commit_response.client_tag_hash);
|
| - EXPECT_LT(0, commit_response.response_version);
|
| -}
|
| -
|
| -TEST_F(NonBlockingTypeProcessorCoreTest, SimpleDelete) {
|
| - NormalInitialize();
|
| -
|
| - // We can't delete an entity that was never committed.
|
| - // Step 1 is to create and commit a new entity.
|
| - CommitRequest("tag1", "value1");
|
| - ASSERT_TRUE(WillCommit());
|
| - DoSuccessfulCommit();
|
| -
|
| - ASSERT_TRUE(HasCommitResponseOnModelThread("tag1"));
|
| - const CommitResponseData& initial_commit_response =
|
| - GetCommitResponseOnModelThread("tag1");
|
| - int64 base_version = initial_commit_response.response_version;
|
| -
|
| - // Now that we have an entity, we can delete it.
|
| - DeleteRequest("tag1");
|
| - ASSERT_TRUE(WillCommit());
|
| - DoSuccessfulCommit();
|
| -
|
| - // Verify the SyncEntity sent in the commit message.
|
| - ASSERT_EQ(2U, GetNumCommitMessagesOnServer());
|
| - EXPECT_EQ(1, GetNthCommitMessageOnServer(1).commit().entries_size());
|
| - ASSERT_TRUE(HasCommitEntityOnServer("tag1"));
|
| - const sync_pb::SyncEntity& entity = GetLatestCommitEntityOnServer("tag1");
|
| - EXPECT_FALSE(entity.id_string().empty());
|
| - EXPECT_EQ(GenerateTagHash("tag1"), entity.client_defined_unique_tag());
|
| - EXPECT_EQ(base_version, entity.version());
|
| - EXPECT_TRUE(entity.deleted());
|
| -
|
| - // Deletions should contain enough specifics to identify the type.
|
| - EXPECT_TRUE(entity.has_specifics());
|
| - EXPECT_EQ(kModelType, GetModelTypeFromSpecifics(entity.specifics()));
|
| -
|
| - // Verify the commit response returned to the model thread.
|
| - ASSERT_EQ(2U, GetNumModelThreadCommitResponses());
|
| - EXPECT_EQ(1U, GetNthModelThreadCommitResponse(1).size());
|
| - ASSERT_TRUE(HasCommitResponseOnModelThread("tag1"));
|
| - const CommitResponseData& commit_response =
|
| - GetCommitResponseOnModelThread("tag1");
|
| -
|
| - EXPECT_EQ(entity.id_string(), commit_response.id);
|
| - EXPECT_EQ(entity.client_defined_unique_tag(),
|
| - commit_response.client_tag_hash);
|
| - EXPECT_EQ(entity.version(), commit_response.response_version);
|
| -}
|
| -
|
| -// The server doesn't like it when we try to delete an entity it's never heard
|
| -// of before. This test helps ensure we avoid that scenario.
|
| -TEST_F(NonBlockingTypeProcessorCoreTest, NoDeleteUncommitted) {
|
| - NormalInitialize();
|
| -
|
| - // Request the commit of a new, never-before-seen item.
|
| - CommitRequest("tag1", "value1");
|
| - EXPECT_TRUE(WillCommit());
|
| -
|
| - // Request a deletion of that item before we've had a chance to commit it.
|
| - DeleteRequest("tag1");
|
| - EXPECT_FALSE(WillCommit());
|
| -}
|
| -
|
| -// Verifies the sending of an "initial sync done" signal.
|
| -TEST_F(NonBlockingTypeProcessorCoreTest, SendInitialSyncDone) {
|
| - FirstInitialize(); // Initialize with no saved sync state.
|
| - EXPECT_EQ(0U, GetNumModelThreadUpdateResponses());
|
| -
|
| - // Receive an update response that contains only the type root node.
|
| - TriggerTypeRootUpdateFromServer();
|
| -
|
| - // Two updates:
|
| - // - One triggered by process updates to forward the type root ID.
|
| - // - One triggered by apply updates, which the core interprets to mean
|
| - // "initial sync done". This triggers a model thread update, too.
|
| - EXPECT_EQ(2U, GetNumModelThreadUpdateResponses());
|
| -
|
| - // The type root and initial sync done updates both contain no entities.
|
| - EXPECT_EQ(0U, GetNthModelThreadUpdateResponse(0).size());
|
| - EXPECT_EQ(0U, GetNthModelThreadUpdateResponse(1).size());
|
| -
|
| - const DataTypeState& state = GetNthModelThreadUpdateState(1);
|
| - EXPECT_FALSE(state.progress_marker.token().empty());
|
| - EXPECT_FALSE(state.type_root_id.empty());
|
| - EXPECT_TRUE(state.initial_sync_done);
|
| -}
|
| -
|
| -// Commit two new entities in two separate commit messages.
|
| -TEST_F(NonBlockingTypeProcessorCoreTest, TwoNewItemsCommittedSeparately) {
|
| - NormalInitialize();
|
| -
|
| - // Commit the first of two entities.
|
| - CommitRequest("tag1", "value1");
|
| - ASSERT_TRUE(WillCommit());
|
| - DoSuccessfulCommit();
|
| - ASSERT_EQ(1U, GetNumCommitMessagesOnServer());
|
| - EXPECT_EQ(1, GetNthCommitMessageOnServer(0).commit().entries_size());
|
| - ASSERT_TRUE(HasCommitEntityOnServer("tag1"));
|
| - const sync_pb::SyncEntity& tag1_entity =
|
| - GetLatestCommitEntityOnServer("tag1");
|
| -
|
| - // Commit the second of two entities.
|
| - CommitRequest("tag2", "value2");
|
| - ASSERT_TRUE(WillCommit());
|
| - DoSuccessfulCommit();
|
| - ASSERT_EQ(2U, GetNumCommitMessagesOnServer());
|
| - EXPECT_EQ(1, GetNthCommitMessageOnServer(1).commit().entries_size());
|
| - ASSERT_TRUE(HasCommitEntityOnServer("tag2"));
|
| - const sync_pb::SyncEntity& tag2_entity =
|
| - GetLatestCommitEntityOnServer("tag2");
|
| -
|
| - EXPECT_FALSE(WillCommit());
|
| -
|
| - // The IDs assigned by the |core_| should be unique.
|
| - EXPECT_NE(tag1_entity.id_string(), tag2_entity.id_string());
|
| -
|
| - // Check that the committed specifics values are sane.
|
| - EXPECT_EQ(tag1_entity.specifics().preference().value(), "value1");
|
| - EXPECT_EQ(tag2_entity.specifics().preference().value(), "value2");
|
| -
|
| - // There should have been two separate commit responses sent to the model
|
| - // thread. They should be uninteresting, so we don't bother inspecting them.
|
| - EXPECT_EQ(2U, GetNumModelThreadCommitResponses());
|
| -}
|
| -
|
| -TEST_F(NonBlockingTypeProcessorCoreTest, ReceiveUpdates) {
|
| - NormalInitialize();
|
| -
|
| - const std::string& tag_hash = GenerateTagHash("tag1");
|
| -
|
| - TriggerUpdateFromServer(10, "tag1", "value1");
|
| -
|
| - ASSERT_EQ(1U, GetNumModelThreadUpdateResponses());
|
| - UpdateResponseDataList updates_list = GetNthModelThreadUpdateResponse(0);
|
| - ASSERT_EQ(1U, updates_list.size());
|
| -
|
| - ASSERT_TRUE(HasUpdateResponseOnModelThread("tag1"));
|
| - UpdateResponseData update = GetUpdateResponseOnModelThread("tag1");
|
| -
|
| - EXPECT_FALSE(update.id.empty());
|
| - EXPECT_EQ(tag_hash, update.client_tag_hash);
|
| - EXPECT_LT(0, update.response_version);
|
| - EXPECT_FALSE(update.ctime.is_null());
|
| - EXPECT_FALSE(update.mtime.is_null());
|
| - EXPECT_FALSE(update.non_unique_name.empty());
|
| - EXPECT_FALSE(update.deleted);
|
| - EXPECT_EQ("tag1", update.specifics.preference().name());
|
| - EXPECT_EQ("value1", update.specifics.preference().value());
|
| -}
|
| -
|
| -} // namespace syncer
|
|
|