// 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 "components/sync_driver/generic_change_processor.h"

#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "components/sync_driver/data_type_error_handler_mock.h"
#include "components/sync_driver/sync_api_component_factory.h"
#include "sync/api/attachments/attachment_service_impl.h"
#include "sync/api/fake_syncable_service.h"
#include "sync/api/sync_change.h"
#include "sync/api/sync_merge_result.h"
#include "sync/internal_api/public/attachments/fake_attachment_downloader.h"
#include "sync/internal_api/public/attachments/fake_attachment_store.h"
#include "sync/internal_api/public/attachments/fake_attachment_uploader.h"
#include "sync/internal_api/public/base/model_type.h"
#include "sync/internal_api/public/read_node.h"
#include "sync/internal_api/public/read_transaction.h"
#include "sync/internal_api/public/sync_encryption_handler.h"
#include "sync/internal_api/public/test/test_user_share.h"
#include "sync/internal_api/public/user_share.h"
#include "sync/internal_api/public/write_node.h"
#include "sync/internal_api/public/write_transaction.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace browser_sync {

namespace {

const char kTestData[] = "some data";

// A mock that keeps track of attachments passed to StoreAttachments.
class MockAttachmentService : public syncer::AttachmentServiceImpl {
 public:
  MockAttachmentService();
  virtual ~MockAttachmentService();
  virtual void StoreAttachments(const syncer::AttachmentList& attachments,
                                const StoreCallback& callback) OVERRIDE;
  std::vector<syncer::AttachmentList>* attachment_lists();

 private:
  std::vector<syncer::AttachmentList> attachment_lists_;
};

MockAttachmentService::MockAttachmentService()
    : AttachmentServiceImpl(
          scoped_ptr<syncer::AttachmentStore>(new syncer::FakeAttachmentStore(
              base::MessageLoopProxy::current())),
          scoped_ptr<syncer::AttachmentUploader>(
              new syncer::FakeAttachmentUploader),
          scoped_ptr<syncer::AttachmentDownloader>(
              new syncer::FakeAttachmentDownloader),
          NULL) {
}

MockAttachmentService::~MockAttachmentService() {
}

void MockAttachmentService::StoreAttachments(
    const syncer::AttachmentList& attachments,
    const StoreCallback& callback) {
  attachment_lists_.push_back(attachments);
  AttachmentServiceImpl::StoreAttachments(attachments, callback);
}

std::vector<syncer::AttachmentList>* MockAttachmentService::attachment_lists() {
  return &attachment_lists_;
}

// MockSyncApiComponentFactory needed to initialize GenericChangeProcessor and
// pass MockAttachmentService to it.
class MockSyncApiComponentFactory : public SyncApiComponentFactory {
 public:
  MockSyncApiComponentFactory(
      scoped_ptr<syncer::AttachmentService> attachment_service)
      : attachment_service_(attachment_service.Pass()) {}

  virtual base::WeakPtr<syncer::SyncableService> GetSyncableServiceForType(
      syncer::ModelType type) OVERRIDE {
    // Shouldn't be called for this test.
    NOTREACHED();
    return base::WeakPtr<syncer::SyncableService>();
  }

  virtual scoped_ptr<syncer::AttachmentService> CreateAttachmentService(
      syncer::AttachmentService::Delegate* delegate) OVERRIDE {
    EXPECT_TRUE(attachment_service_ != NULL);
    return attachment_service_.Pass();
  }

 private:
  scoped_ptr<syncer::AttachmentService> attachment_service_;
};

class SyncGenericChangeProcessorTest : public testing::Test {
 public:
  // It doesn't matter which type we use.  Just pick one.
  static const syncer::ModelType kType = syncer::PREFERENCES;

  SyncGenericChangeProcessorTest()
      : sync_merge_result_(kType),
        merge_result_ptr_factory_(&sync_merge_result_),
        syncable_service_ptr_factory_(&fake_syncable_service_),
        mock_attachment_service_(NULL) {}

  virtual void SetUp() OVERRIDE {
    test_user_share_.SetUp();
    syncer::ModelTypeSet types = syncer::ProtocolTypes();
    for (syncer::ModelTypeSet::Iterator iter = types.First(); iter.Good();
         iter.Inc()) {
      syncer::TestUserShare::CreateRoot(iter.Get(),
                                        test_user_share_.user_share());
    }
    test_user_share_.encryption_handler()->Init();
    scoped_ptr<MockAttachmentService> mock_attachment_service(
        new MockAttachmentService);
    // GenericChangeProcessor takes ownership of the AttachmentService, but we
    // need to have a pointer to it so we can see that it was used properly.
    // Take a pointer and trust that GenericChangeProcessor does not prematurely
    // destroy it.
    mock_attachment_service_ = mock_attachment_service.get();
    sync_factory_.reset(new MockSyncApiComponentFactory(
        mock_attachment_service.PassAs<syncer::AttachmentService>()));
    change_processor_.reset(
        new GenericChangeProcessor(&data_type_error_handler_,
                                   syncable_service_ptr_factory_.GetWeakPtr(),
                                   merge_result_ptr_factory_.GetWeakPtr(),
                                   test_user_share_.user_share(),
                                   sync_factory_.get()));
  }

  virtual void TearDown() OVERRIDE {
    mock_attachment_service_ = NULL;
    test_user_share_.TearDown();
  }

  void BuildChildNodes(int n) {
    syncer::WriteTransaction trans(FROM_HERE, user_share());
    syncer::ReadNode root(&trans);
    ASSERT_EQ(syncer::BaseNode::INIT_OK, root.InitTypeRoot(kType));
    for (int i = 0; i < n; ++i) {
      syncer::WriteNode node(&trans);
      node.InitUniqueByCreation(kType, root, base::StringPrintf("node%05d", i));
    }
  }

  GenericChangeProcessor* change_processor() {
    return change_processor_.get();
  }

  syncer::UserShare* user_share() {
    return test_user_share_.user_share();
  }

  MockAttachmentService* mock_attachment_service() {
    return mock_attachment_service_;
  }

 private:
  base::MessageLoopForUI loop_;

  syncer::SyncMergeResult sync_merge_result_;
  base::WeakPtrFactory<syncer::SyncMergeResult> merge_result_ptr_factory_;

  syncer::FakeSyncableService fake_syncable_service_;
  base::WeakPtrFactory<syncer::FakeSyncableService>
      syncable_service_ptr_factory_;

  DataTypeErrorHandlerMock data_type_error_handler_;
  syncer::TestUserShare test_user_share_;
  MockAttachmentService* mock_attachment_service_;
  scoped_ptr<SyncApiComponentFactory> sync_factory_;

  scoped_ptr<GenericChangeProcessor> change_processor_;
};

// Similar to above, but focused on the method that implements sync/api
// interfaces and is hence exposed to datatypes directly.
TEST_F(SyncGenericChangeProcessorTest, StressGetAllSyncData) {
  const int kNumChildNodes = 1000;
  const int kRepeatCount = 1;

  ASSERT_NO_FATAL_FAILURE(BuildChildNodes(kNumChildNodes));

  for (int i = 0; i < kRepeatCount; ++i) {
    syncer::SyncDataList sync_data =
        change_processor()->GetAllSyncData(kType);

    // Start with a simple test.  We can add more in-depth testing later.
    EXPECT_EQ(static_cast<size_t>(kNumChildNodes), sync_data.size());
  }
}

TEST_F(SyncGenericChangeProcessorTest, SetGetPasswords) {
  const int kNumPasswords = 10;
  sync_pb::PasswordSpecificsData password_data;
  password_data.set_username_value("user");

  sync_pb::EntitySpecifics password_holder;

  syncer::SyncChangeList change_list;
  for (int i = 0; i < kNumPasswords; ++i) {
    password_data.set_password_value(
        base::StringPrintf("password%i", i));
    password_holder.mutable_password()->mutable_client_only_encrypted_data()->
        CopyFrom(password_data);
    change_list.push_back(
        syncer::SyncChange(FROM_HERE,
                           syncer::SyncChange::ACTION_ADD,
                           syncer::SyncData::CreateLocalData(
                               base::StringPrintf("tag%i", i),
                               base::StringPrintf("title%i", i),
                               password_holder)));
  }

  ASSERT_FALSE(
      change_processor()->ProcessSyncChanges(FROM_HERE, change_list).IsSet());

  syncer::SyncDataList password_list(
      change_processor()->GetAllSyncData(syncer::PASSWORDS));

  ASSERT_EQ(password_list.size(), change_list.size());
  for (int i = 0; i < kNumPasswords; ++i) {
    // Verify the password is returned properly.
    ASSERT_TRUE(password_list[i].GetSpecifics().has_password());
    ASSERT_TRUE(password_list[i].GetSpecifics().password().
                    has_client_only_encrypted_data());
    ASSERT_FALSE(password_list[i].GetSpecifics().password().has_encrypted());
    const sync_pb::PasswordSpecificsData& sync_password =
        password_list[i].GetSpecifics().password().client_only_encrypted_data();
    const sync_pb::PasswordSpecificsData& change_password =
        change_list[i].sync_data().GetSpecifics().password().
            client_only_encrypted_data();
    ASSERT_EQ(sync_password.password_value(), change_password.password_value());
    ASSERT_EQ(sync_password.username_value(), change_password.username_value());

    // Verify the raw sync data was stored securely.
    syncer::ReadTransaction read_transaction(FROM_HERE, user_share());
    syncer::ReadNode node(&read_transaction);
    ASSERT_EQ(node.InitByClientTagLookup(syncer::PASSWORDS,
                                         base::StringPrintf("tag%i", i)),
              syncer::BaseNode::INIT_OK);
    ASSERT_EQ(node.GetTitle(), "encrypted");
    const sync_pb::EntitySpecifics& raw_specifics = node.GetEntitySpecifics();
    ASSERT_TRUE(raw_specifics.has_password());
    ASSERT_TRUE(raw_specifics.password().has_encrypted());
    ASSERT_FALSE(raw_specifics.password().has_client_only_encrypted_data());
  }
}

TEST_F(SyncGenericChangeProcessorTest, UpdatePasswords) {
  const int kNumPasswords = 10;
  sync_pb::PasswordSpecificsData password_data;
  password_data.set_username_value("user");

  sync_pb::EntitySpecifics password_holder;

  syncer::SyncChangeList change_list;
  syncer::SyncChangeList change_list2;
  for (int i = 0; i < kNumPasswords; ++i) {
    password_data.set_password_value(
        base::StringPrintf("password%i", i));
    password_holder.mutable_password()->mutable_client_only_encrypted_data()->
        CopyFrom(password_data);
    change_list.push_back(
        syncer::SyncChange(FROM_HERE,
                           syncer::SyncChange::ACTION_ADD,
                           syncer::SyncData::CreateLocalData(
                               base::StringPrintf("tag%i", i),
                               base::StringPrintf("title%i", i),
                               password_holder)));
    password_data.set_password_value(
        base::StringPrintf("password_m%i", i));
    password_holder.mutable_password()->mutable_client_only_encrypted_data()->
        CopyFrom(password_data);
    change_list2.push_back(
        syncer::SyncChange(FROM_HERE,
                           syncer::SyncChange::ACTION_UPDATE,
                           syncer::SyncData::CreateLocalData(
                               base::StringPrintf("tag%i", i),
                               base::StringPrintf("title_m%i", i),
                               password_holder)));
  }

  ASSERT_FALSE(
      change_processor()->ProcessSyncChanges(FROM_HERE, change_list).IsSet());
  ASSERT_FALSE(
      change_processor()->ProcessSyncChanges(FROM_HERE, change_list2).IsSet());

  syncer::SyncDataList password_list(
      change_processor()->GetAllSyncData(syncer::PASSWORDS));

  ASSERT_EQ(password_list.size(), change_list2.size());
  for (int i = 0; i < kNumPasswords; ++i) {
    // Verify the password is returned properly.
    ASSERT_TRUE(password_list[i].GetSpecifics().has_password());
    ASSERT_TRUE(password_list[i].GetSpecifics().password().
                    has_client_only_encrypted_data());
    ASSERT_FALSE(password_list[i].GetSpecifics().password().has_encrypted());
    const sync_pb::PasswordSpecificsData& sync_password =
        password_list[i].GetSpecifics().password().client_only_encrypted_data();
    const sync_pb::PasswordSpecificsData& change_password =
        change_list2[i].sync_data().GetSpecifics().password().
            client_only_encrypted_data();
    ASSERT_EQ(sync_password.password_value(), change_password.password_value());
    ASSERT_EQ(sync_password.username_value(), change_password.username_value());

    // Verify the raw sync data was stored securely.
    syncer::ReadTransaction read_transaction(FROM_HERE, user_share());
    syncer::ReadNode node(&read_transaction);
    ASSERT_EQ(node.InitByClientTagLookup(syncer::PASSWORDS,
                                         base::StringPrintf("tag%i", i)),
              syncer::BaseNode::INIT_OK);
    ASSERT_EQ(node.GetTitle(), "encrypted");
    const sync_pb::EntitySpecifics& raw_specifics = node.GetEntitySpecifics();
    ASSERT_TRUE(raw_specifics.has_password());
    ASSERT_TRUE(raw_specifics.password().has_encrypted());
    ASSERT_FALSE(raw_specifics.password().has_client_only_encrypted_data());
  }
}

// Verify that attachments on newly added or updated SyncData are passed to the
// AttachmentService.
TEST_F(SyncGenericChangeProcessorTest,
       ProcessSyncChanges_AddUpdateWithAttachment) {
  std::string tag = "client_tag";
  std::string title = "client_title";
  sync_pb::EntitySpecifics specifics;
  sync_pb::PreferenceSpecifics* pref_specifics = specifics.mutable_preference();
  pref_specifics->set_name("test");
  syncer::AttachmentList attachments;
  scoped_refptr<base::RefCountedString> attachment_data =
      new base::RefCountedString;
  attachment_data->data() = kTestData;
  attachments.push_back(syncer::Attachment::Create(attachment_data));
  attachments.push_back(syncer::Attachment::Create(attachment_data));

  // Add a SyncData with two attachments.
  syncer::SyncChangeList change_list;
  change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_ADD,
                         syncer::SyncData::CreateLocalDataWithAttachments(
                             tag, title, specifics, attachments)));
  ASSERT_FALSE(
      change_processor()->ProcessSyncChanges(FROM_HERE, change_list).IsSet());

  // Check that the AttachmentService received the new attachments.
  ASSERT_EQ(mock_attachment_service()->attachment_lists()->size(), 1U);
  const syncer::AttachmentList& attachments_added =
      mock_attachment_service()->attachment_lists()->front();
  ASSERT_EQ(attachments_added.size(), 2U);
  ASSERT_EQ(attachments_added[0].GetId(), attachments[0].GetId());
  ASSERT_EQ(attachments_added[1].GetId(), attachments[1].GetId());

  // Update the SyncData, replacing its two attachments with one new attachment.
  syncer::AttachmentList new_attachments;
  new_attachments.push_back(syncer::Attachment::Create(attachment_data));
  mock_attachment_service()->attachment_lists()->clear();
  change_list.clear();
  change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_UPDATE,
                         syncer::SyncData::CreateLocalDataWithAttachments(
                             tag, title, specifics, new_attachments)));
  ASSERT_FALSE(
      change_processor()->ProcessSyncChanges(FROM_HERE, change_list).IsSet());

  // Check that the AttachmentService received it.
  ASSERT_EQ(mock_attachment_service()->attachment_lists()->size(), 1U);
  const syncer::AttachmentList& new_attachments_added =
      mock_attachment_service()->attachment_lists()->front();
  ASSERT_EQ(new_attachments_added.size(), 1U);
  ASSERT_EQ(new_attachments_added[0].GetId(), new_attachments[0].GetId());
}

// Verify that after attachment is uploaded GenericChangeProcessor updates
// corresponding entries
TEST_F(SyncGenericChangeProcessorTest, AttachmentUploaded) {
  std::string tag = "client_tag";
  std::string title = "client_title";
  sync_pb::EntitySpecifics specifics;
  sync_pb::PreferenceSpecifics* pref_specifics = specifics.mutable_preference();
  pref_specifics->set_name("test");
  syncer::AttachmentList attachments;
  scoped_refptr<base::RefCountedString> attachment_data =
      new base::RefCountedString;
  attachment_data->data() = kTestData;
  attachments.push_back(syncer::Attachment::Create(attachment_data));

  // Add a SyncData with two attachments.
  syncer::SyncChangeList change_list;
  change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_ADD,
                         syncer::SyncData::CreateLocalDataWithAttachments(
                             tag, title, specifics, attachments)));
  ASSERT_FALSE(
      change_processor()->ProcessSyncChanges(FROM_HERE, change_list).IsSet());

  sync_pb::AttachmentIdProto attachment_id_proto =
      attachments[0].GetId().GetProto();
  syncer::AttachmentId attachment_id =
      syncer::AttachmentId::CreateFromProto(attachment_id_proto);

  change_processor()->OnAttachmentUploaded(attachment_id);
  syncer::ReadTransaction read_transaction(FROM_HERE, user_share());
  syncer::ReadNode node(&read_transaction);
  ASSERT_EQ(node.InitByClientTagLookup(syncer::PREFERENCES, tag),
            syncer::BaseNode::INIT_OK);
  syncer::AttachmentIdList attachment_ids = node.GetAttachmentIds();
  EXPECT_EQ(1U, attachment_ids.size());
}

}  // namespace

}  // namespace browser_sync
