chromium/components/sync/model/client_tag_based_data_type_processor_unittest.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/sync/model/client_tag_based_data_type_processor.h"

#include <stddef.h>
#include <stdint.h>

#include <optional>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/protobuf_matchers.h"
#include "base/test/task_environment.h"
#include "base/threading/platform_thread.h"
#include "components/sync/base/client_tag_hash.h"
#include "components/sync/base/data_type.h"
#include "components/sync/base/deletion_origin.h"
#include "components/sync/base/sync_mode.h"
#include "components/sync/base/unique_position.h"
#include "components/sync/engine/commit_and_get_updates_types.h"
#include "components/sync/engine/data_type_activation_response.h"
#include "components/sync/model/conflict_resolution.h"
#include "components/sync/model/data_type_activation_request.h"
#include "components/sync/model/processor_entity.h"
#include "components/sync/model/type_entities_count.h"
#include "components/sync/protocol/data_type_state.pb.h"
#include "components/sync/protocol/entity_metadata.pb.h"
#include "components/sync/protocol/entity_specifics.pb.h"
#include "components/sync/protocol/unique_position.pb.h"
#include "components/sync/test/fake_data_type_sync_bridge.h"
#include "components/sync/test/mock_data_type_worker.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace syncer {

namespace {

EqualsProto;
DataTypeState;
EntityMetadata;
EntitySpecifics;
Not;
NotNull;

const char kDefaultAuthenticatedAccountId[] =;

const char kKey1[] =;
const char kKey2[] =;
const char kKey3[] =;
const char kKey4[] =;
const char kKey5[] =;
const char kValue1[] =;
const char kValue2[] =;
const char kValue3[] =;

const char kCacheGuid[] =;

// Typically used for verification after a delete. The specifics given to the
// worker/processor will not have been initialized and thus empty.
const EntitySpecifics kEmptySpecifics;

ClientTagHash GetHash(DataType type, const std::string& key) {}

ClientTagHash GetPrefHash(const std::string& key) {}

ClientTagHash GetSharedTabHash(const std::string& key) {}

EntitySpecifics GeneratePrefSpecifics(const std::string& key,
                                      const std::string& value) {}

EntitySpecifics GenerateUserEventSpecifics(int64_t event_time_usec,
                                           int64_t navigation_id) {}

EntitySpecifics GenerateSharedTabSpecifics(
    std::string guid,
    sync_pb::UniquePosition unique_position) {}

std::unique_ptr<EntityData> GenerateEntityData(
    DataType type,
    const std::string& key,
    const EntitySpecifics& specifics) {}

std::unique_ptr<EntityData> GeneratePrefEntityData(const std::string& key,
                                                   const std::string& value) {}

std::unique_ptr<EntityData> GenerateSharedTabGroupEntityData(
    const std::string& guid,
    sync_pb::UniquePosition unique_position) {}

EntitySpecifics WritePrefItem(FakeDataTypeSyncBridge* bridge,
                              const std::string& key,
                              const std::string& value) {}

const std::string& GetPrefValue(const EntityData& entity_data) {}

EntitySpecifics WriteUserEventItem(FakeDataTypeSyncBridge* bridge,
                                   int64_t event_time,
                                   int64_t navigation_id) {}

void CaptureCommitRequest(CommitRequestDataList* dst,
                          CommitRequestDataList&& src) {}

void CaptureTypeEntitiesCount(TypeEntitiesCount* dst,
                              const TypeEntitiesCount& count) {}

sync_pb::UniquePosition ExtractUniquePositionFromSharedTab(
    const sync_pb::EntitySpecifics& specifics) {}

class TestDataTypeSyncBridge : public FakeDataTypeSyncBridge {};

}  // namespace

// Tests the various functionality of ClientTagBasedDataTypeProcessor.
//
// The processor sits between the bridge (implemented by this test class) and
// the worker, which is represented by a MockDataTypeWorker. This test suite
// exercises the initialization flows (whether initial sync is done, performing
// the initial merge, etc) as well as normal functionality:
//
// - Initialization before the initial sync and merge correctly performs a merge
//   and initializes the metadata in storage.
// - Initialization after the initial sync correctly loads metadata and queues
//   any pending commits.
// - Put and Delete calls from the bridge result in the correct metadata in
//   storage and the correct commit requests on the worker side.
// - Updates and commit responses from the worker correctly affect data and
//   metadata in storage on the bridge side.
class ClientTagBasedDataTypeProcessorTest : public ::testing::Test {};

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldExposeNewlyTrackedAccountId) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldExposePreviouslyTrackedAccountId) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldExposeNewlyTrackedAccountIdIfChanged) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldExposeNewlyAddedInvalidations) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldExposeNewlyTrackedCacheGuid) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldExposePreviouslyTrackedCacheGuid) {}

// Test that an initial sync handles local and remote items properly.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldMergeLocalAndRemoteChanges) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldExposePossiblyTrimmedRemoteSpecifics) {}

// Test that an initial sync filters out tombstones in the processor.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldFilterOutInitialTombstones) {}

// Test that an initial sync filters out updates for root nodes in the
// processor.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldFilterOutInitialRootNodes) {}

// Test that subsequent starts don't call MergeFullSyncData.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldApplyIncrementalUpdates) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldReportErrorDuringActivation) {}

// Test that an error during the merge is propagated to the error handler.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldReportErrorDuringMerge) {}

// Test that errors before it's called are passed to |start_callback| correctly.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldDeferErrorsBeforeStart) {}

// Tests cases where pending data loads synchronously.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldHandleSynchronousDataLoad) {}

// This test covers race conditions during loading a pending delete. All cases
// start with no processor and one item with a pending delete. There are two
// different events that can occur in any order once metadata is loaded, since
// for a deletion there is no data to load:
//
// - Sync gets connected.
// - Optionally, a put or delete happens to the item (repeated deletes should be
//   handled properly).
//
// This results in 1 + 4 = 5 orderings of the events.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldLoadPendingDelete) {}

// Test that loading a committed item does not queue another commit.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotQueueAnotherCommitIfAlreadyCommitted) {}

// Creates a new item locally.
// Thoroughly tests the data generated by a local item creation.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldCommitLocalCreation) {}

// Creates a new item locally while another item exists for the same client tag
// hash.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       CommitShouldOverwriteExistingItem) {}

// Test that an error applying metadata changes from a commit response is
// propagated to the error handler.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldReportErrorApplyingAck) {}

// The purpose of this test case is to test setting |client_tag_hash| and |id|
// on the EntityData object as we pass it into the Put method of the processor.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldOverrideFieldsForLocalUpdate) {}

// Creates a new local item, then modifies it after it has been acked.
// Thoroughly tests data generated by modification of server-unknown item.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldCommitLocalUpdate) {}

// Same as above, but modifies the item BEFORE it has been acked.
// Thoroughly tests data generated by modification of server-unknown item.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldCommitLocalUpdateBeforeCreationAck) {}

// Tests that a local update that doesn't change specifics doesn't generate a
// commit request.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldIgnoreRedundantLocalUpdate) {}

// Test that an error applying changes from a server update is
// propagated to the error handler.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldReportErrorApplyingUpdate) {}

// Tests locally deleting an acknowledged item.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldCommitLocalDeletion) {}

// Tests that item created and deleted before sync cycle doesn't get committed.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotCommitLocalDeletionOfUncommittedEntity) {}

// Tests creating and deleting an item locally before receiving a commit
// response, then getting the commit responses.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldHandleLocalDeletionDuringLocalCreationCommit) {}

TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldProcessRemoteDeletion) {}

// Deletes an item we've never seen before.
// Should have no effect and not crash.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldIgnoreLocalDeletionOfUnknownEntity) {}

// Tests that after committing entity fails, processor includes this entity in
// consecutive commits.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldRetryCommitAfterServerError) {}

// Tests that after committing entity fails, processor includes this entity in
// consecutive commits. This test differs from the above one for the case when
// there is an HTTP error.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldRetryCommitAfterFullCommitFailure) {}

// Tests that GetLocalChanges honors max_entries parameter.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldTruncateLocalChangesToMaxSize) {}

// Creates two different sync items.
// Verifies that the second has no effect on the first.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldHandleTwoIndependentItems) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotTreatMatchingChangesAsConflict) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResolveConflictToLocalVersion) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResolveConflictToLocalUndeletion) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResolveConflictToRemoteUndeletion) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResolveConflictToRemoteUndeletionWithUpdateStorageKey) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResolveConflictToRemoteVersion) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResolveConflictToRemoteDeletion) {}

// Test proper handling of disconnect and reconnect.
//
// Creates items in various states of commit and verifies they re-attempt to
// commit on reconnect.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldDisconnectAndReconnect) {}

// Test proper handling of stop (without disabling sync) and re-enable.
//
// Creates items in various states of commit and verifies they do NOT attempt to
// commit on re-enable.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldStopAndKeepMetadata) {}

// Test proper handling of disable and re-enable.
//
// Creates items in various states of commit and verifies they re-attempt to
// commit on re-enable.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldStopAndClearMetadata) {}

// Test proper handling of disable-sync before initial sync done.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotClearBridgeMetadataPriorToMergeFullSyncData) {}

// Test re-encrypt everything when desired encryption key changes.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldReencryptCommitsWithNewKey) {}

// Test that an error loading pending commit data for re-encryption is
// propagated to the error handler.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldHandleErrorWhileReencrypting) {}

// Test receipt of updates with new and old keys.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldReencryptUpdatesWithNewKey) {}

// Test that re-encrypting enqueues the right data for kUseLocal conflicts.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResolveConflictToLocalDuringReencryption) {}

// Test that re-encrypting enqueues the right data for kUseRemote conflicts.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResolveConflictToRemoteDuringReencryption) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldHandleConflictWhileLoadingForReencryption) {}

// Tests that a real remote change wins over a local encryption-only change.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldIgnoreLocalEncryptionChange) {}

// Tests that updates without client tags get dropped.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldDropRemoteUpdatesWithoutClientTags) {}

// Tests that initial updates for transport-only mode (called "ephemeral
// storage" for historical reasons) result in reporting setup duration.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldReportEphemeralConfigurationTime) {}

// Tests that initial updates for full-sync mode (called "persistent storage"
// for historical reasons) do not result in reporting setup duration.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldReportPersistentConfigurationTime) {}

class FullUpdateClientTagBasedDataTypeProcessorTest
    : public ClientTagBasedDataTypeProcessorTest {};

// Tests that ClientTagBasedDataTypeProcessor can do garbage collection by
// version.
// Garbage collection by version is used by the server to replace all data on
// the client, and is implemented by calling MergeFullSyncData on the bridge.
TEST_F(FullUpdateClientTagBasedDataTypeProcessorTest,
       ShouldApplyGarbageCollectionByVersionFullUpdate) {}
// Tests that full updates for transport-only mode (called "ephemeral storage"
// for historical reasons) result in reporting setup duration.
TEST_F(FullUpdateClientTagBasedDataTypeProcessorTest,
       ShouldReportEphemeralConfigurationTimeOnlyForFirstFullUpdate) {}

// Tests that the processor reports an error for updates without a version GC
// directive that are received for types that don't support incremental updates.
TEST_F(FullUpdateClientTagBasedDataTypeProcessorTest,
       ShouldReportErrorForUnsupportedIncrementalUpdate) {}

// Tests that empty updates without a version GC are processed for types that
// don't support incremental updates. The only outcome if these updates should
// be storing an updated progress marker.
TEST_F(FullUpdateClientTagBasedDataTypeProcessorTest,
       ShouldProcessEmptyUpdate) {}

// Tests that the processor correctly handles an initial (non-empty) update
// without any gc directives (as it happens in the migration to USS).
TEST_F(FullUpdateClientTagBasedDataTypeProcessorTest,
       ShouldProcessInitialUpdate) {}

// Tests that a real local change wins over a remote encryption-only change.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldIgnoreRemoteEncryption) {}

// Same as above but with two commit requests before one ack.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldIgnoreRemoteEncryptionInterleaved) {}

// Tests that UpdateStorageKey propagates storage key to ProcessorEntity
// and updates corresponding entity's metadata in MetadataChangeList, and
// UntrackEntity will remove corresponding ProcessorEntity and do not add
// any entity's metadata into MetadataChangeList.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldUpdateStorageKey) {}

// Tests that reencryption scenario works correctly for types that don't support
// GetStorageKey(). When update from server delivers updated encryption key, all
// entities should be reencrypted including new entity that just got received
// from server.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldReencryptDatatypeWithoutStorageKeySupport) {}

// Tests that UntrackEntity won't propagate storage key to
// ProcessorEntity, and no entity's metadata are added into
// MetadataChangeList.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldUntrackEntity) {}

// Tests that UntrackEntityForStorage won't propagate storage key to
// ProcessorEntity, and no entity's metadata are added into
// MetadataChangeList.
TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldUntrackEntityForStorageKey) {}

// Tests that UntrackEntityForStorage does not crash if no such entity is being
// tracked.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldIgnoreUntrackEntityForInexistentStorageKey) {}

// Tests that UntrackEntityForClientTagHash won't propagate storage key to
// ProcessorEntity, and no entity's metadata are added into MetadataChangeList.
// This test is pretty same as ShouldUntrackEntityForStorageKey.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldUntrackEntityForClientTagHash) {}

// Tests that the processor reports an error for updates with a version GC
// directive that are received for types that support incremental updates.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotApplyGarbageCollectionByVersion) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldDeleteMetadataWhenCacheGuidMismatch) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldDeleteMetadataWhenDataTypeIdMismatch) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldClearOrphanMetadataInGetLocalChangesWhenDataIsMissing) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotReportOrphanMetadataInGetLocalChangesWhenDataIsPresent) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldRecordNumUnsyncedEntitiesOnModelReady) {}

// This tests the case when the bridge deletes an item, and before it's
// committed to the server, it created again with a different storage key.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldDeleteItemAndRecreaeItWithDifferentStorageKey) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldPropagateFailedCommitItemsToBridgeWhenCommitCompleted) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotPropagateFailedCommitAttemptToBridgeWhenNoFailedItems) {}

TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldPropagateFullCommitFailure) {}

class CommitOnlyClientTagBasedDataTypeProcessorTest
    : public ClientTagBasedDataTypeProcessorTest {};

TEST_F(CommitOnlyClientTagBasedDataTypeProcessorTest,
       ShouldExposeNewlyTrackedAccountId) {}

TEST_F(CommitOnlyClientTagBasedDataTypeProcessorTest,
       ShouldExposePreviouslyTrackedAccountId) {}

TEST_F(CommitOnlyClientTagBasedDataTypeProcessorTest,
       ShouldCallMergeWhenSyncEnabled) {}

TEST_F(CommitOnlyClientTagBasedDataTypeProcessorTest,
       ShouldNotCallMergeAfterRestart) {}

// Test that commit only types are deleted after commit response.
TEST_F(CommitOnlyClientTagBasedDataTypeProcessorTest,
       ShouldCommitAndDeleteWhenAcked) {}

// Test that commit only types maintain tracking of entities while unsynced
// changes exist.
TEST_F(CommitOnlyClientTagBasedDataTypeProcessorTest,
       ShouldTrackUnsyncedChangesAfterPartialCommit) {}

TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldResetOnInvalidCacheGuid) {}

TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldResetOnInvalidDataTypeId) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResetForEntityMetadataWithoutInitialSyncDone) {}

// Regression test for crbug.com/1427000.
TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotResetWhenInitialSyncPartiallyDone) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldResetForDuplicateClientTagHash) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotProcessInvalidRemoteIncrementalUpdate) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotProcessInvalidRemoteFullUpdate) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotReportErrorAfterOnSyncStopping) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotInvokeBridgeOnSyncStartingFromOnSyncStopping) {}

TEST_F(ClientTagBasedDataTypeProcessorTest, ShouldClearMetadataIfStopped) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldClearMetadataIfStoppedUponModelReadyToSync) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldClearMetadataWhileStoppedUponModelReadyToSyncWithoutEntities) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotClearMetadataIfNotStopped) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotClearMetadataIfStoppedIfNotTracking) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotClearMetadataIfStoppedWithoutMetadataInitially) {}

TEST_F(ClientTagBasedDataTypeProcessorTest,
       ShouldNotClearMetadataIfStoppedUponModelReadyToSyncWithoutMetadata) {}

class PasswordsClientTagBasedDataTypeProcessorTest
    : public ClientTagBasedDataTypeProcessorTest {};

TEST_F(PasswordsClientTagBasedDataTypeProcessorTest,
       ShouldSetPasswordsRedownloadedForNotesFlag) {}

// Test suite for testing the bridge with UniquePosition support.
// SHARED_TAB_GROUP_DATA is used as an example data type with unique_position
// in specifics.
class ClientTagBasedDataTypeProcessorWithUniquePositionTest
    : public ClientTagBasedDataTypeProcessorTest {};

TEST_F(ClientTagBasedDataTypeProcessorWithUniquePositionTest,
       ShouldProcessUniquePositionForNewEntity) {}

TEST_F(ClientTagBasedDataTypeProcessorWithUniquePositionTest,
       ShouldUpdateUniquePositionForExistingEntity) {}

TEST_F(ClientTagBasedDataTypeProcessorWithUniquePositionTest,
       ShouldUpdateUniquePositionAfterDeletion) {}

TEST_F(ClientTagBasedDataTypeProcessorWithUniquePositionTest,
       ShouldStoreRemoteUniquePositionOnFullUpdate) {}

TEST_F(ClientTagBasedDataTypeProcessorWithUniquePositionTest,
       ShouldGenerateUniquePositionForInitialEntity) {}

TEST_F(ClientTagBasedDataTypeProcessorWithUniquePositionTest,
       ShouldGenerateUniquePositionsBeforeAndAfter) {}

TEST_F(ClientTagBasedDataTypeProcessorWithUniquePositionTest,
       ShouldGenerateUniquePositionBetween) {}

TEST_F(ClientTagBasedDataTypeProcessorWithUniquePositionTest,
       ShouldReturnUniquePosition) {}

}  // namespace syncer