// Copyright 2019 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 "components/sync/nigori/nigori_model_type_processor.h"

#include <memory>
#include <string>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "components/sync/base/time.h"
#include "components/sync/engine/commit_queue.h"
#include "components/sync/nigori/nigori_sync_bridge.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace syncer {

namespace {

using testing::_;
using testing::Eq;
using testing::Ne;
using testing::NotNull;

// TODO(mamir): remove those and adjust the code accordingly.
const char kNigoriClientTagHash[] = "NigoriClientTagHash";

const char kNigoriNonUniqueName[] = "nigori";
const char kNigoriServerId[] = "nigori_server_id";
const char kCacheGuid[] = "generated_id";

// |*arg| must be of type base::Optional<EntityData>.
MATCHER_P(OptionalEntityDataHasDecryptorTokenKeyName, expected_key_name, "") {
  return arg->specifics.nigori().keystore_decryptor_token().key_name() ==
         expected_key_name;
}

void CaptureCommitRequest(CommitRequestDataList* dst,
                          CommitRequestDataList&& src) {
  *dst = std::move(src);
}

sync_pb::ModelTypeState CreateDummyModelTypeState() {
  sync_pb::ModelTypeState model_type_state;
  model_type_state.set_cache_guid(kCacheGuid);
  model_type_state.set_initial_sync_done(true);
  return model_type_state;
}

// Creates a dummy Nigori UpdateResponseData that has the keystore decryptor
// token key name set.
std::unique_ptr<syncer::UpdateResponseData> CreateDummyNigoriUpdateResponseData(
    const std::string keystore_decryptor_token_key_name,
    int response_version) {
  auto entity_data = std::make_unique<syncer::EntityData>();
  entity_data->is_folder = true;
  entity_data->id = kNigoriServerId;
  sync_pb::NigoriSpecifics* nigori_specifics =
      entity_data->specifics.mutable_nigori();
  nigori_specifics->mutable_keystore_decryptor_token()->set_key_name(
      keystore_decryptor_token_key_name);
  entity_data->non_unique_name = kNigoriNonUniqueName;

  auto response_data = std::make_unique<syncer::UpdateResponseData>();
  response_data->entity = std::move(entity_data);
  response_data->response_version = response_version;
  return response_data;
}

CommitResponseData CreateNigoriCommitResponseData(
    const CommitRequestData& commit_request_data,
    int response_version) {
  CommitResponseData commit_response_data;
  commit_response_data.id = kNigoriServerId;
  commit_response_data.client_tag_hash = kNigoriClientTagHash;
  commit_response_data.sequence_number = commit_request_data.sequence_number;
  commit_response_data.response_version = response_version;
  commit_response_data.specifics_hash = commit_request_data.specifics_hash;
  commit_response_data.unsynced_time = commit_request_data.unsynced_time;
  return commit_response_data;
}

class MockNigoriSyncBridge : public NigoriSyncBridge {
 public:
  MockNigoriSyncBridge() = default;
  ~MockNigoriSyncBridge() = default;

  MOCK_METHOD1(MergeSyncData,
               base::Optional<ModelError>(base::Optional<EntityData> data));
  MOCK_METHOD1(ApplySyncChanges,
               base::Optional<ModelError>(base::Optional<EntityData> data));
  MOCK_METHOD0(GetData, std::unique_ptr<EntityData>());
  MOCK_METHOD2(ResolveConflict,
               ConflictResolution(const EntityData& local_data,
                                  const EntityData& remote_data));
  MOCK_METHOD0(ApplyDisableSyncChanges, void());
};

class MockCommitQueue : public CommitQueue {
 public:
  MockCommitQueue() = default;
  ~MockCommitQueue() = default;

  MOCK_METHOD0(NudgeForCommit, void());
};

class NigoriModelTypeProcessorTest : public testing::Test {
 public:
  NigoriModelTypeProcessorTest() {
    mock_commit_queue_ = std::make_unique<testing::NiceMock<MockCommitQueue>>();
    mock_commit_queue_ptr_ = mock_commit_queue_.get();
  }

  void SimulateModelReadyToSync(bool initial_sync_done, int server_version) {
    NigoriMetadataBatch nigori_metadata_batch;
    nigori_metadata_batch.model_type_state.set_initial_sync_done(
        initial_sync_done);
    nigori_metadata_batch.entity_metadata = sync_pb::EntityMetadata();
    nigori_metadata_batch.entity_metadata->set_creation_time(
        TimeToProtoTime(base::Time::Now()));
    nigori_metadata_batch.entity_metadata->set_sequence_number(0);
    nigori_metadata_batch.entity_metadata->set_acked_sequence_number(0);
    nigori_metadata_batch.entity_metadata->set_server_version(server_version);
    processor_.ModelReadyToSync(mock_nigori_sync_bridge(),
                                std::move(nigori_metadata_batch));
  }

  void SimulateModelReadyToSync(bool initial_sync_done) {
    SimulateModelReadyToSync(initial_sync_done, /*server_version=*/1);
  }

  void SimulateConnectSync() {
    processor_.ConnectSync(std::move(mock_commit_queue_));
  }

  MockNigoriSyncBridge* mock_nigori_sync_bridge() {
    return &mock_nigori_sync_bridge_;
  }

  MockCommitQueue* mock_commit_queue() { return mock_commit_queue_ptr_; }

  NigoriModelTypeProcessor* processor() { return &processor_; }

 private:
  // This sets SequencedTaskRunnerHandle on the current thread, which the type
  // processor will pick up as the sync task runner.
  base::test::ScopedTaskEnvironment task_environment_;

  testing::NiceMock<MockNigoriSyncBridge> mock_nigori_sync_bridge_;
  std::unique_ptr<testing::NiceMock<MockCommitQueue>> mock_commit_queue_;
  MockCommitQueue* mock_commit_queue_ptr_;
  NigoriModelTypeProcessor processor_;
};

TEST_F(NigoriModelTypeProcessorTest,
       ShouldTrackTheMetadataWhenInitialSyncDone) {
  // Build a model type state with a specific cache guid.
  const std::string kCacheGuid = "cache_guid";
  sync_pb::ModelTypeState model_type_state;
  model_type_state.set_initial_sync_done(true);
  model_type_state.set_cache_guid(kCacheGuid);

  // Build entity metadata with a specific sequence number.
  const int kSequenceNumber = 100;
  sync_pb::EntityMetadata entity_metadata;
  entity_metadata.set_sequence_number(kSequenceNumber);
  entity_metadata.set_creation_time(TimeToProtoTime(base::Time::Now()));

  NigoriMetadataBatch nigori_metadata_batch;
  nigori_metadata_batch.model_type_state = model_type_state;
  nigori_metadata_batch.entity_metadata = entity_metadata;

  processor()->ModelReadyToSync(mock_nigori_sync_bridge(),
                                std::move(nigori_metadata_batch));

  // The model type state and the metadata should have been stored in the
  // processor.
  NigoriMetadataBatch processor_metadata_batch = processor()->GetMetadata();
  EXPECT_THAT(processor_metadata_batch.model_type_state.cache_guid(),
              Eq(kCacheGuid));
  ASSERT_TRUE(processor_metadata_batch.entity_metadata);
  EXPECT_THAT(processor_metadata_batch.entity_metadata->sequence_number(),
              Eq(kSequenceNumber));
}

TEST_F(NigoriModelTypeProcessorTest, ShouldIncrementSequenceNumberWhenPut) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);
  base::Optional<sync_pb::EntityMetadata> entity_metadata1 =
      processor()->GetMetadata().entity_metadata;
  ASSERT_TRUE(entity_metadata1);

  auto entity_data = std::make_unique<syncer::EntityData>();
  entity_data->specifics.mutable_nigori();
  entity_data->non_unique_name = kNigoriNonUniqueName;
  entity_data->is_folder = true;

  processor()->Put(std::move(entity_data));

  base::Optional<sync_pb::EntityMetadata> entity_metadata2 =
      processor()->GetMetadata().entity_metadata;
  ASSERT_TRUE(entity_metadata1);

  EXPECT_THAT(entity_metadata2->sequence_number(),
              Eq(entity_metadata1->sequence_number() + 1));
}

TEST_F(NigoriModelTypeProcessorTest, ShouldGetEmptyLocalChanges) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);
  CommitRequestDataList commit_request;
  processor()->GetLocalChanges(
      /*max_entries=*/10,
      base::BindOnce(&CaptureCommitRequest, &commit_request));
  EXPECT_EQ(0U, commit_request.size());
}

TEST_F(NigoriModelTypeProcessorTest, ShouldGetLocalChangesWhenPut) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);

  auto entity_data = std::make_unique<syncer::EntityData>();
  entity_data->specifics.mutable_nigori();
  entity_data->non_unique_name = kNigoriNonUniqueName;
  entity_data->is_folder = true;

  processor()->Put(std::move(entity_data));
  CommitRequestDataList commit_request;
  processor()->GetLocalChanges(
      /*max_entries=*/10,
      base::BindOnce(&CaptureCommitRequest, &commit_request));
  ASSERT_EQ(1U, commit_request.size());
  EXPECT_EQ(kNigoriNonUniqueName, commit_request[0]->entity->non_unique_name);
}

TEST_F(NigoriModelTypeProcessorTest,
       ShouldSquashCommitRequestUponCommitCompleted) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);

  auto entity_data = std::make_unique<syncer::EntityData>();
  entity_data->specifics.mutable_nigori();
  entity_data->non_unique_name = kNigoriNonUniqueName;
  entity_data->is_folder = true;

  processor()->Put(std::move(entity_data));
  CommitRequestDataList commit_request_list;
  processor()->GetLocalChanges(
      /*max_entries=*/10,
      base::BindOnce(&CaptureCommitRequest, &commit_request_list));
  ASSERT_EQ(1U, commit_request_list.size());

  CommitResponseDataList commit_response_list;
  commit_response_list.push_back(CreateNigoriCommitResponseData(
      *commit_request_list[0], /*response_version=*/processor()
                                       ->GetMetadata()
                                       .entity_metadata->server_version() +
                                   1));

  // ApplySyncChanges() should be called to trigger persistence of the metadata.
  EXPECT_CALL(*mock_nigori_sync_bridge(), ApplySyncChanges(Eq(base::nullopt)));
  processor()->OnCommitCompleted(CreateDummyModelTypeState(),
                                 std::move(commit_response_list));

  // There should be no more local changes.
  commit_response_list.clear();
  processor()->GetLocalChanges(
      /*max_entries=*/10,
      base::BindOnce(&CaptureCommitRequest, &commit_request_list));
  EXPECT_TRUE(commit_request_list.empty());
}

TEST_F(NigoriModelTypeProcessorTest,
       ShouldNotSquashCommitRequestUponEmptyCommitResponse) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);

  auto entity_data = std::make_unique<syncer::EntityData>();
  entity_data->specifics.mutable_nigori();
  entity_data->non_unique_name = kNigoriNonUniqueName;
  entity_data->is_folder = true;

  processor()->Put(std::move(entity_data));
  CommitRequestDataList commit_request_list;
  processor()->GetLocalChanges(
      /*max_entries=*/10,
      base::BindOnce(&CaptureCommitRequest, &commit_request_list));
  ASSERT_EQ(1U, commit_request_list.size());

  // ApplySyncChanges() should be called to trigger persistence of the metadata.
  EXPECT_CALL(*mock_nigori_sync_bridge(), ApplySyncChanges(Eq(base::nullopt)));
  processor()->OnCommitCompleted(CreateDummyModelTypeState(),
                                 CommitResponseDataList());

  // Data has been moved into the previous request, so the processor will ask
  // for the commit data once more.
  ON_CALL(*mock_nigori_sync_bridge(), GetData()).WillByDefault([&]() {
    auto entity_data = std::make_unique<syncer::EntityData>();
    entity_data->specifics.mutable_nigori();
    entity_data->non_unique_name = kNigoriNonUniqueName;
    entity_data->is_folder = true;
    return entity_data;
  });

  // The commit should still be pending.
  CommitResponseDataList commit_response_list;
  processor()->GetLocalChanges(
      /*max_entries=*/10,
      base::BindOnce(&CaptureCommitRequest, &commit_request_list));
  EXPECT_EQ(1U, commit_request_list.size());
}

TEST_F(NigoriModelTypeProcessorTest,
       ShouldKeepAnotherCommitRequestUponCommitCompleted) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);

  auto entity_data = std::make_unique<syncer::EntityData>();
  sync_pb::NigoriSpecifics* nigori_specifics =
      entity_data->specifics.mutable_nigori();
  nigori_specifics->set_encrypt_bookmarks(true);
  entity_data->non_unique_name = kNigoriNonUniqueName;
  entity_data->is_folder = true;

  processor()->Put(std::move(entity_data));
  CommitRequestDataList commit_request_list;
  processor()->GetLocalChanges(
      /*max_entries=*/10,
      base::BindOnce(&CaptureCommitRequest, &commit_request_list));
  ASSERT_EQ(1U, commit_request_list.size());

  CommitResponseDataList commit_response_list;
  commit_response_list.push_back(CreateNigoriCommitResponseData(
      *commit_request_list[0], /*response_version=*/processor()
                                       ->GetMetadata()
                                       .entity_metadata->server_version() +
                                   1));

  // Make another local change before the commit response is received.
  entity_data = std::make_unique<syncer::EntityData>();
  nigori_specifics = entity_data->specifics.mutable_nigori();
  entity_data->non_unique_name = kNigoriNonUniqueName;
  entity_data->is_folder = true;
  nigori_specifics->set_encrypt_preferences(true);
  processor()->Put(std::move(entity_data));

  // ApplySyncChanges() should be called to trigger persistence of the metadata.
  EXPECT_CALL(*mock_nigori_sync_bridge(), ApplySyncChanges(Eq(base::nullopt)));
  // Receive the commit response of the first request.
  processor()->OnCommitCompleted(CreateDummyModelTypeState(),
                                 std::move(commit_response_list));

  // There should still be a local change.
  commit_response_list.clear();
  processor()->GetLocalChanges(
      /*max_entries=*/10,
      base::BindOnce(&CaptureCommitRequest, &commit_request_list));
  EXPECT_EQ(1U, commit_request_list.size());
}

TEST_F(NigoriModelTypeProcessorTest,
       ShouldNudgeForCommitUponConnectSyncIfReadyToSyncAndLocalChanges) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);

  auto entity_data = std::make_unique<syncer::EntityData>();
  entity_data->specifics.mutable_nigori();
  entity_data->non_unique_name = kNigoriNonUniqueName;
  entity_data->is_folder = true;

  processor()->Put(std::move(entity_data));

  EXPECT_CALL(*mock_commit_queue(), NudgeForCommit());
  SimulateConnectSync();
}

TEST_F(NigoriModelTypeProcessorTest, ShouldNudgeForCommitUponPutIfReadyToSync) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);
  SimulateConnectSync();

  auto entity_data = std::make_unique<syncer::EntityData>();
  entity_data->specifics.mutable_nigori();
  entity_data->non_unique_name = kNigoriNonUniqueName;
  entity_data->is_folder = true;

  EXPECT_CALL(*mock_commit_queue(), NudgeForCommit());
  processor()->Put(std::move(entity_data));
}

TEST_F(NigoriModelTypeProcessorTest, ShouldInvokeSyncStartCallback) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);

  syncer::DataTypeActivationRequest request;
  request.error_handler = base::DoNothing();
  request.cache_guid = kCacheGuid;

  base::MockCallback<ModelTypeControllerDelegate::StartCallback> start_callback;
  std::unique_ptr<DataTypeActivationResponse> captured_response;
  EXPECT_CALL(start_callback, Run)
      .WillOnce(testing::Invoke(
          [&captured_response](
              std::unique_ptr<DataTypeActivationResponse> response) {
            captured_response = std::move(response);
          }));
  processor()->OnSyncStarting(request, start_callback.Get());
  ASSERT_THAT(captured_response, NotNull());
  EXPECT_EQ(kCacheGuid, captured_response->model_type_state.cache_guid());

  // Test that the |processor()| has been set in the activation response.
  ASSERT_FALSE(processor()->IsConnectedForTest());
  captured_response->type_processor->ConnectSync(
      std::make_unique<testing::NiceMock<MockCommitQueue>>());
  // RunUntilIdle() is needed because ModelTypeProcessorProxy() is used and it
  // internally does posting of tasks.
  base::RunLoop().RunUntilIdle();
  EXPECT_TRUE(processor()->IsConnectedForTest());
}

TEST_F(NigoriModelTypeProcessorTest, ShouldMergeSyncData) {
  SimulateModelReadyToSync(/*initial_sync_done=*/false);

  const std::string kDecryptorTokenKeyName = "key_name";
  UpdateResponseDataList updates;
  updates.push_back(CreateDummyNigoriUpdateResponseData(kDecryptorTokenKeyName,
                                                        /*server_version=*/1));

  EXPECT_CALL(*mock_nigori_sync_bridge(),
              MergeSyncData(OptionalEntityDataHasDecryptorTokenKeyName(
                  kDecryptorTokenKeyName)));

  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                std::move(updates));
}

TEST_F(NigoriModelTypeProcessorTest, ShouldApplySyncChanges) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true, /*server_version=*/1);

  const std::string kDecryptorTokenKeyName = "key_name";
  UpdateResponseDataList updates;
  updates.push_back(CreateDummyNigoriUpdateResponseData(kDecryptorTokenKeyName,
                                                        /*server_version=*/2));

  EXPECT_CALL(*mock_nigori_sync_bridge(),
              ApplySyncChanges(OptionalEntityDataHasDecryptorTokenKeyName(
                  kDecryptorTokenKeyName)));

  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                std::move(updates));
}

TEST_F(NigoriModelTypeProcessorTest, ShouldApplySyncChangesWhenEmptyUpdates) {
  const int kServerVersion = 1;
  SimulateModelReadyToSync(/*initial_sync_done=*/true, kServerVersion);

  // ApplySyncChanges() should still be called to trigger persistence of the
  // metadata.
  EXPECT_CALL(*mock_nigori_sync_bridge(), ApplySyncChanges(Eq(base::nullopt)));

  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                UpdateResponseDataList());
}

TEST_F(NigoriModelTypeProcessorTest, ShouldApplySyncChangesWhenReflection) {
  const int kServerVersion = 1;
  SimulateModelReadyToSync(/*initial_sync_done=*/true, kServerVersion);

  UpdateResponseDataList updates;
  updates.push_back(CreateDummyNigoriUpdateResponseData(
      /*keystore_decryptor_token_key_name=*/"key_name", kServerVersion));

  // ApplySyncChanges() should still be called to trigger persistence of the
  // metadata.
  EXPECT_CALL(*mock_nigori_sync_bridge(), ApplySyncChanges(Eq(base::nullopt)));

  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                std::move(updates));
}

TEST_F(NigoriModelTypeProcessorTest, ShouldStopSyncingAndKeepMetadata) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);
  syncer::DataTypeActivationRequest request;
  request.error_handler = base::DoNothing();
  request.cache_guid = kCacheGuid;
  processor()->OnSyncStarting(request, base::DoNothing());
  SimulateConnectSync();

  ASSERT_TRUE(processor()->IsConnectedForTest());
  EXPECT_CALL(*mock_nigori_sync_bridge(), ApplyDisableSyncChanges()).Times(0);
  processor()->OnSyncStopping(syncer::KEEP_METADATA);
  EXPECT_FALSE(processor()->IsConnectedForTest());
}

TEST_F(NigoriModelTypeProcessorTest, ShouldStopSyncingAndClearMetadata) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true);
  syncer::DataTypeActivationRequest request;
  request.error_handler = base::DoNothing();
  request.cache_guid = kCacheGuid;
  processor()->OnSyncStarting(request, base::DoNothing());
  SimulateConnectSync();

  ASSERT_TRUE(processor()->IsConnectedForTest());
  EXPECT_CALL(*mock_nigori_sync_bridge(), ApplyDisableSyncChanges());
  processor()->OnSyncStopping(syncer::CLEAR_METADATA);
  EXPECT_FALSE(processor()->IsConnectedForTest());
}

TEST_F(NigoriModelTypeProcessorTest, ShouldDisconnectWhenMergeSyncDataFails) {
  SimulateModelReadyToSync(/*initial_sync_done=*/false);

  syncer::DataTypeActivationRequest request;
  base::MockCallback<ModelErrorHandler> error_handler_callback;
  request.error_handler = error_handler_callback.Get();
  request.cache_guid = kCacheGuid;
  processor()->OnSyncStarting(request, base::DoNothing());
  SimulateConnectSync();

  // Simulate returning error at MergeSyncData()
  ON_CALL(*mock_nigori_sync_bridge(), MergeSyncData(_))
      .WillByDefault([&](const base::Optional<EntityData>& data) {
        return ModelError(FROM_HERE, "some error");
      });

  UpdateResponseDataList updates;
  updates.push_back(CreateDummyNigoriUpdateResponseData(
      /*keystore_decryptor_token_key_name=*/"some key",
      /*server_version=*/1));

  ASSERT_TRUE(processor()->IsConnectedForTest());
  EXPECT_CALL(error_handler_callback, Run(_));
  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                std::move(updates));
  EXPECT_FALSE(processor()->IsConnectedForTest());
}

TEST_F(NigoriModelTypeProcessorTest,
       ShouldDisconnectWhenApplySyncChangesFails) {
  SimulateModelReadyToSync(/*initial_sync_done=*/true, /*server_version=*/1);

  syncer::DataTypeActivationRequest request;
  base::MockCallback<ModelErrorHandler> error_handler_callback;
  request.error_handler = error_handler_callback.Get();
  request.cache_guid = kCacheGuid;
  processor()->OnSyncStarting(request, base::DoNothing());
  SimulateConnectSync();

  // Simulate returning error at ApplySyncChanges()
  ON_CALL(*mock_nigori_sync_bridge(), ApplySyncChanges(_))
      .WillByDefault([&](const base::Optional<EntityData>& data) {
        return ModelError(FROM_HERE, "some error");
      });

  UpdateResponseDataList updates;
  updates.push_back(CreateDummyNigoriUpdateResponseData(
      /*keystore_decryptor_token_key_name=*/"some key",
      /*server_version=*/2));

  ASSERT_TRUE(processor()->IsConnectedForTest());
  EXPECT_CALL(error_handler_callback, Run(_));
  processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                std::move(updates));
  EXPECT_FALSE(processor()->IsConnectedForTest());
}

TEST_F(NigoriModelTypeProcessorTest,
       ShouldCallErrorHandlerIfModelErrorBeforeSyncStarts) {
  processor()->ReportError(ModelError(FROM_HERE, "some error"));

  syncer::DataTypeActivationRequest request;
  base::MockCallback<ModelErrorHandler> error_handler_callback;
  request.error_handler = error_handler_callback.Get();
  request.cache_guid = kCacheGuid;

  EXPECT_CALL(error_handler_callback, Run(_));
  processor()->OnSyncStarting(request, base::DoNothing());
}

}  // namespace

}  // namespace syncer
