// 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/password_manager/core/browser/password_syncable_service.h"

#include <algorithm>
#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "components/password_manager/core/browser/mock_password_store.h"
#include "sync/api/sync_change_processor.h"
#include "sync/api/sync_error.h"
#include "sync/api/sync_error_factory_mock.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using syncer::SyncChange;
using syncer::SyncData;
using syncer::SyncDataList;
using syncer::SyncError;
using testing::AnyNumber;
using testing::DoAll;
using testing::ElementsAre;
using testing::IgnoreResult;
using testing::Invoke;
using testing::IsEmpty;
using testing::Matches;
using testing::Return;
using testing::SetArgPointee;
using testing::UnorderedElementsAre;
using testing::_;

namespace password_manager {

// Defined in the implementation file corresponding to this test.
syncer::SyncData SyncDataFromPassword(const autofill::PasswordForm& password);
autofill::PasswordForm PasswordFromSpecifics(
    const sync_pb::PasswordSpecificsData& password);
std::string MakePasswordSyncTag(const sync_pb::PasswordSpecificsData& password);
std::string MakePasswordSyncTag(const autofill::PasswordForm& password);

namespace {

// PasswordForm values for tests.
const autofill::PasswordForm::Type kArbitraryType =
    autofill::PasswordForm::TYPE_GENERATED;
const char kAvatarUrl[] = "https://fb.com/Avatar";
const char kDisplayName[] = "Agent Smith";
const char kFederationUrl[] = "https://fb.com/federation_url";
const char kPassword[] = "abcdef";
const char kSignonRealm[] = "abc";
const char kSignonRealm2[] = "def";
const char kSignonRealm3[] = "xyz";
const int kTimesUsed = 5;
const char kUsername[] = "godzilla";

typedef std::vector<SyncChange> SyncChangeList;

const sync_pb::PasswordSpecificsData& GetPasswordSpecifics(
    const syncer::SyncData& sync_data) {
  return sync_data.GetSpecifics().password().client_only_encrypted_data();
}

MATCHER(HasDateSynced, "") {
  return !arg.date_synced.is_null() && !arg.date_synced.is_max();
}

MATCHER_P(PasswordIs, form, "") {
  sync_pb::PasswordSpecificsData actual_password =
      GetPasswordSpecifics(SyncDataFromPassword(arg));
  sync_pb::PasswordSpecificsData expected_password =
      GetPasswordSpecifics(SyncDataFromPassword(form));
  if (expected_password.scheme() == actual_password.scheme() &&
      expected_password.signon_realm() == actual_password.signon_realm() &&
      expected_password.origin() == actual_password.origin() &&
      expected_password.action() == actual_password.action() &&
      expected_password.username_element() ==
          actual_password.username_element() &&
      expected_password.password_element() ==
          actual_password.password_element() &&
      expected_password.username_value() == actual_password.username_value() &&
      expected_password.password_value() == actual_password.password_value() &&
      expected_password.ssl_valid() == actual_password.ssl_valid() &&
      expected_password.preferred() == actual_password.preferred() &&
      expected_password.date_created() == actual_password.date_created() &&
      expected_password.blacklisted() == actual_password.blacklisted() &&
      expected_password.type() == actual_password.type() &&
      expected_password.times_used() == actual_password.times_used() &&
      expected_password.display_name() == actual_password.display_name() &&
      expected_password.avatar_url() == actual_password.avatar_url() &&
      expected_password.federation_url() == actual_password.federation_url())
    return true;

  *result_listener << "Password protobuf does not match; expected:\n"
                   << form << '\n'
                   << "actual:" << '\n'
                   << arg;
  return false;
}

MATCHER_P2(SyncChangeIs, change_type, password, "") {
  const SyncData& data = arg.sync_data();
  autofill::PasswordForm form =
      PasswordFromSpecifics(GetPasswordSpecifics(data));
  return (arg.change_type() == change_type &&
          syncer::SyncDataLocal(data).GetTag() ==
              MakePasswordSyncTag(password) &&
          (change_type == SyncChange::ACTION_DELETE ||
           Matches(PasswordIs(password))(form)));
}

// The argument is std::vector<autofill::PasswordForm*>*. The caller is
// responsible for the lifetime of all the password forms.
ACTION_P(AppendForm, form) {
  arg0->push_back(new autofill::PasswordForm(form));
  return true;
}

// Creates a sync data consisting of password specifics. The sign on realm is
// set to |signon_realm|.
SyncData CreateSyncData(const std::string& signon_realm) {
  sync_pb::EntitySpecifics password_data;
  sync_pb::PasswordSpecificsData* password_specifics =
      password_data.mutable_password()->mutable_client_only_encrypted_data();
  password_specifics->set_signon_realm(signon_realm);
  password_specifics->set_type(autofill::PasswordForm::TYPE_GENERATED);
  password_specifics->set_times_used(3);
  password_specifics->set_display_name("Mr. X");
  password_specifics->set_avatar_url("https://accounts.google.com/Avatar");
  password_specifics->set_federation_url("https://google.com/federation");
  password_specifics->set_username_value("kingkong");
  password_specifics->set_password_value("sicrit");

  std::string tag = MakePasswordSyncTag(*password_specifics);
  return syncer::SyncData::CreateLocalData(tag, tag, password_data);
}

SyncChange CreateSyncChange(const autofill::PasswordForm& password,
                            SyncChange::SyncChangeType type) {
  SyncData data = SyncDataFromPassword(password);
  return SyncChange(FROM_HERE, type, data);
}

// A testable implementation of the |PasswordSyncableService| that mocks
// out all interaction with the password database.
class MockPasswordSyncableService : public PasswordSyncableService {
 public:
  explicit MockPasswordSyncableService(PasswordStoreSync* password_store)
      : PasswordSyncableService(password_store) {}

  MOCK_METHOD1(StartSyncFlare, void(syncer::ModelType));

 private:
  DISALLOW_COPY_AND_ASSIGN(MockPasswordSyncableService);
};

// Mock implementation of SyncChangeProcessor.
class MockSyncChangeProcessor : public syncer::SyncChangeProcessor {
 public:
  MockSyncChangeProcessor() {}

  MOCK_METHOD2(ProcessSyncChanges,
               SyncError(const tracked_objects::Location&,
                         const SyncChangeList& list));
  SyncDataList GetAllSyncData(syncer::ModelType type) const override {
    NOTREACHED();
    return SyncDataList();
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(MockSyncChangeProcessor);
};

// Convenience wrapper around a PasswordSyncableService and PasswordStore
// pair.
class PasswordSyncableServiceWrapper {
 public:
  PasswordSyncableServiceWrapper() {
    password_store_ = new testing::StrictMock<MockPasswordStore>;
    service_.reset(
        new MockPasswordSyncableService(password_store_->GetSyncInterface()));
    ON_CALL(*password_store_, AddLoginImpl(HasDateSynced()))
        .WillByDefault(Return(PasswordStoreChangeList()));
    ON_CALL(*password_store_, RemoveLoginImpl(_))
        .WillByDefault(Return(PasswordStoreChangeList()));
    ON_CALL(*password_store_, UpdateLoginImpl(HasDateSynced()))
        .WillByDefault(Return(PasswordStoreChangeList()));
    EXPECT_CALL(*password_store(), NotifyLoginsChanged(_)).Times(AnyNumber());
  }

  ~PasswordSyncableServiceWrapper() { password_store_->Shutdown(); }

  MockPasswordStore* password_store() { return password_store_.get(); }

  MockPasswordSyncableService* service() { return service_.get(); }

  // Returnes the scoped_ptr to |service_| thus NULLing out it.
  scoped_ptr<syncer::SyncChangeProcessor> ReleaseSyncableService() {
    return service_.Pass();
  }

 private:
  scoped_refptr<MockPasswordStore> password_store_;
  scoped_ptr<MockPasswordSyncableService> service_;

  DISALLOW_COPY_AND_ASSIGN(PasswordSyncableServiceWrapper);
};

class PasswordSyncableServiceTest : public testing::Test {
 public:
  PasswordSyncableServiceTest()
      : processor_(new testing::StrictMock<MockSyncChangeProcessor>) {
    ON_CALL(*processor_, ProcessSyncChanges(_, _))
        .WillByDefault(Return(SyncError()));
  }
  MockPasswordStore* password_store() { return wrapper_.password_store(); }
  MockPasswordSyncableService* service() { return wrapper_.service(); }

 protected:
  scoped_ptr<MockSyncChangeProcessor> processor_;

 private:
  PasswordSyncableServiceWrapper wrapper_;
};

// Both sync and password db have data that are not present in the other.
TEST_F(PasswordSyncableServiceTest, AdditionsInBoth) {
  autofill::PasswordForm form;
  form.signon_realm = kSignonRealm;
  form.username_value = base::ASCIIToUTF16(kUsername);
  form.password_value = base::ASCIIToUTF16(kPassword);

  SyncDataList list;
  list.push_back(CreateSyncData(kSignonRealm2));
  autofill::PasswordForm new_from_sync =
      PasswordFromSpecifics(GetPasswordSpecifics(list.back()));

  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(AppendForm(form));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true));
  EXPECT_CALL(*password_store(), AddLoginImpl(PasswordIs(new_from_sync)));
  EXPECT_CALL(*processor_, ProcessSyncChanges(_, ElementsAre(
      SyncChangeIs(SyncChange::ACTION_ADD, form))));

  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
                                      list,
                                      processor_.Pass(),
                                      scoped_ptr<syncer::SyncErrorFactory>());
}

// Sync has data that is not present in the password db.
TEST_F(PasswordSyncableServiceTest, AdditionOnlyInSync) {
  SyncDataList list;
  list.push_back(CreateSyncData(kSignonRealm));
  autofill::PasswordForm new_from_sync =
      PasswordFromSpecifics(GetPasswordSpecifics(list.back()));

  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(Return(true));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true));
  EXPECT_CALL(*password_store(), AddLoginImpl(PasswordIs(new_from_sync)));
  EXPECT_CALL(*processor_, ProcessSyncChanges(_, IsEmpty()));

  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
                                      list,
                                      processor_.Pass(),
                                      scoped_ptr<syncer::SyncErrorFactory>());
}

// Passwords db has data that is not present in sync.
TEST_F(PasswordSyncableServiceTest, AdditionOnlyInPasswordStore) {
  autofill::PasswordForm form;
  form.signon_realm = kSignonRealm;
  form.times_used = kTimesUsed;
  form.type = kArbitraryType;
  form.display_name = base::ASCIIToUTF16(kDisplayName);
  form.avatar_url = GURL(kAvatarUrl);
  form.federation_url = GURL(kFederationUrl);
  form.username_value = base::ASCIIToUTF16(kUsername);
  form.password_value = base::ASCIIToUTF16(kPassword);
  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(AppendForm(form));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true));

  EXPECT_CALL(*processor_, ProcessSyncChanges(_, ElementsAre(
      SyncChangeIs(SyncChange::ACTION_ADD, form))));

  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
                                      SyncDataList(),
                                      processor_.Pass(),
                                      scoped_ptr<syncer::SyncErrorFactory>());
}

// Both passwords db and sync contain the same data.
TEST_F(PasswordSyncableServiceTest, BothInSync) {
  autofill::PasswordForm form;
  form.signon_realm = kSignonRealm;
  form.times_used = kTimesUsed;
  form.type = kArbitraryType;
  form.username_value = base::ASCIIToUTF16(kUsername);
  form.password_value = base::ASCIIToUTF16(kPassword);
  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(AppendForm(form));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true));

  EXPECT_CALL(*processor_, ProcessSyncChanges(_, IsEmpty()));

  service()->MergeDataAndStartSyncing(
      syncer::PASSWORDS,
      SyncDataList(1, SyncDataFromPassword(form)),
      processor_.Pass(),
      scoped_ptr<syncer::SyncErrorFactory>());
}

// Both passwords db and sync have the same data but they need to be merged
// as some fields of the data differ.
TEST_F(PasswordSyncableServiceTest, Merge) {
  autofill::PasswordForm form1;
  form1.signon_realm = kSignonRealm;
  form1.action = GURL("http://pie.com");
  form1.date_created = base::Time::Now();
  form1.preferred = true;
  form1.username_value = base::ASCIIToUTF16(kUsername);
  form1.password_value = base::ASCIIToUTF16(kPassword);

  autofill::PasswordForm form2(form1);
  form2.preferred = false;
  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(AppendForm(form1));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true));
  EXPECT_CALL(*password_store(), UpdateLoginImpl(PasswordIs(form2)));
  EXPECT_CALL(*processor_, ProcessSyncChanges(_, IsEmpty()));

  service()->MergeDataAndStartSyncing(
      syncer::PASSWORDS,
      SyncDataList(1, SyncDataFromPassword(form2)),
      processor_.Pass(),
      scoped_ptr<syncer::SyncErrorFactory>());
}

// Initiate sync due to local DB changes.
TEST_F(PasswordSyncableServiceTest, PasswordStoreChanges) {
  // Save the reference to the processor because |processor_| is NULL after
  // MergeDataAndStartSyncing().
  MockSyncChangeProcessor& weak_processor = *processor_;
  EXPECT_CALL(weak_processor, ProcessSyncChanges(_, IsEmpty()));
  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(Return(true));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_))
      .WillOnce(Return(true));
  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
                                      SyncDataList(),
                                      processor_.Pass(),
                                      scoped_ptr<syncer::SyncErrorFactory>());

  autofill::PasswordForm form1;
  form1.signon_realm = kSignonRealm;
  autofill::PasswordForm form2;
  form2.signon_realm = kSignonRealm2;
  autofill::PasswordForm form3;
  form3.signon_realm = kSignonRealm3;

  SyncChangeList sync_list;
  sync_list.push_back(CreateSyncChange(form1, SyncChange::ACTION_ADD));
  sync_list.push_back(CreateSyncChange(form2, SyncChange::ACTION_UPDATE));
  sync_list.push_back(CreateSyncChange(form3, SyncChange::ACTION_DELETE));

  PasswordStoreChangeList list;
  list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form1));
  list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form2));
  list.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form3));
  EXPECT_CALL(weak_processor, ProcessSyncChanges(_, ElementsAre(
      SyncChangeIs(SyncChange::ACTION_ADD, form1),
      SyncChangeIs(SyncChange::ACTION_UPDATE, form2),
      SyncChangeIs(SyncChange::ACTION_DELETE, form3))));
  service()->ActOnPasswordStoreChanges(list);
}

// Process all types of changes from sync.
TEST_F(PasswordSyncableServiceTest, ProcessSyncChanges) {
  autofill::PasswordForm updated_form;
  updated_form.signon_realm = kSignonRealm;
  updated_form.action = GURL("http://foo.com");
  updated_form.date_created = base::Time::Now();
  updated_form.username_value = base::ASCIIToUTF16(kUsername);
  updated_form.password_value = base::ASCIIToUTF16(kPassword);
  autofill::PasswordForm deleted_form;
  deleted_form.signon_realm = kSignonRealm2;
  deleted_form.action = GURL("http://bar.com");
  deleted_form.blacklisted_by_user = true;

  SyncData add_data = CreateSyncData(kSignonRealm3);
  autofill::PasswordForm new_from_sync =
      PasswordFromSpecifics(GetPasswordSpecifics(add_data));

  SyncChangeList list;
  list.push_back(
      SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD, add_data));
  list.push_back(
      CreateSyncChange(updated_form, syncer::SyncChange::ACTION_UPDATE));
  list.push_back(
      CreateSyncChange(deleted_form, syncer::SyncChange::ACTION_DELETE));
  EXPECT_CALL(*password_store(), AddLoginImpl(PasswordIs(new_from_sync)));
  EXPECT_CALL(*password_store(), UpdateLoginImpl(PasswordIs(updated_form)));
  EXPECT_CALL(*password_store(), RemoveLoginImpl(PasswordIs(deleted_form)));
  service()->ProcessSyncChanges(FROM_HERE, list);
}

// Retrives sync data from the model.
TEST_F(PasswordSyncableServiceTest, GetAllSyncData) {
  autofill::PasswordForm form1;
  form1.signon_realm = kSignonRealm;
  form1.action = GURL("http://foo.com");
  form1.times_used = kTimesUsed;
  form1.type = kArbitraryType;
  form1.display_name = base::ASCIIToUTF16(kDisplayName);
  form1.avatar_url = GURL(kAvatarUrl);
  form1.federation_url = GURL(kFederationUrl);
  form1.username_value = base::ASCIIToUTF16(kUsername);
  form1.password_value = base::ASCIIToUTF16(kPassword);
  autofill::PasswordForm form2;
  form2.signon_realm = kSignonRealm2;
  form2.action = GURL("http://bar.com");
  form2.blacklisted_by_user = true;
  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(AppendForm(form1));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_))
      .WillOnce(AppendForm(form2));

  SyncDataList actual_list = service()->GetAllSyncData(syncer::PASSWORDS);
  std::vector<autofill::PasswordForm> actual_form_list;
  for (SyncDataList::iterator it = actual_list.begin(); it != actual_list.end();
       ++it) {
    actual_form_list.push_back(
        PasswordFromSpecifics(GetPasswordSpecifics(*it)));
  }
  EXPECT_THAT(actual_form_list,
              UnorderedElementsAre(PasswordIs(form1), PasswordIs(form2)));
}

// Creates 2 PasswordSyncableService instances, merges the content of the first
// one to the second one and back.
TEST_F(PasswordSyncableServiceTest, MergeDataAndPushBack) {
  autofill::PasswordForm form1;
  form1.signon_realm = kSignonRealm;
  form1.action = GURL("http://foo.com");
  form1.username_value = base::ASCIIToUTF16(kUsername);
  form1.password_value = base::ASCIIToUTF16(kPassword);

  PasswordSyncableServiceWrapper other_service_wrapper;
  autofill::PasswordForm form2;
  form2.signon_realm = kSignonRealm2;
  form2.action = GURL("http://bar.com");
  form2.username_value = base::ASCIIToUTF16(kUsername);
  form2.password_value = base::ASCIIToUTF16(kPassword);
  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(AppendForm(form1));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true));
  EXPECT_CALL(*other_service_wrapper.password_store(),
              FillAutofillableLogins(_)).WillOnce(AppendForm(form2));
  EXPECT_CALL(*other_service_wrapper.password_store(), FillBlacklistLogins(_))
      .WillOnce(Return(true));

  EXPECT_CALL(*password_store(), AddLoginImpl(PasswordIs(form2)));
  EXPECT_CALL(*other_service_wrapper.password_store(),
              AddLoginImpl(PasswordIs(form1)));

  syncer::SyncDataList other_service_data =
      other_service_wrapper.service()->GetAllSyncData(syncer::PASSWORDS);
  service()->MergeDataAndStartSyncing(
      syncer::PASSWORDS,
      other_service_data,
      other_service_wrapper.ReleaseSyncableService(),
      scoped_ptr<syncer::SyncErrorFactory>());
}

// Calls ActOnPasswordStoreChanges without SyncChangeProcessor. StartSyncFlare
// should be called.
TEST_F(PasswordSyncableServiceTest, StartSyncFlare) {
  autofill::PasswordForm form;
  form.signon_realm = kSignonRealm;
  form.username_value = base::ASCIIToUTF16(kUsername);
  form.password_value = base::ASCIIToUTF16(kPassword);
  PasswordStoreChangeList list;
  list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));

  // No flare and no SyncChangeProcessor, the call shouldn't crash.
  service()->ActOnPasswordStoreChanges(list);

  // Set the flare. It should be called as there is no SyncChangeProcessor.
  service()->InjectStartSyncFlare(
      base::Bind(&MockPasswordSyncableService::StartSyncFlare,
                 base::Unretained(service())));
  EXPECT_CALL(*service(), StartSyncFlare(syncer::PASSWORDS));
  service()->ActOnPasswordStoreChanges(list);
}

// Start syncing with an error. Subsequent password store updates shouldn't be
// propagated to Sync.
TEST_F(PasswordSyncableServiceTest, FailedReadFromPasswordStore) {
  scoped_ptr<syncer::SyncErrorFactoryMock> error_factory(
      new syncer::SyncErrorFactoryMock);
  syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
                          "Failed to get passwords from store.",
                          syncer::PASSWORDS);
  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(Return(false));
  EXPECT_CALL(*error_factory, CreateAndUploadError(_, _))
      .WillOnce(Return(error));
  // ActOnPasswordStoreChanges() below shouldn't generate any changes for Sync.
  // |processor_| will be destroyed in MergeDataAndStartSyncing().
  EXPECT_CALL(*processor_, ProcessSyncChanges(_, _)).Times(0);
  syncer::SyncMergeResult result =
      service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
                                          syncer::SyncDataList(),
                                          processor_.Pass(),
                                          error_factory.Pass());
  EXPECT_TRUE(result.error().IsSet());

  autofill::PasswordForm form;
  form.signon_realm = kSignonRealm;
  PasswordStoreChangeList list;
  list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
  service()->ActOnPasswordStoreChanges(list);
}

// Start syncing with an error in ProcessSyncChanges. Subsequent password store
// updates shouldn't be propagated to Sync.
TEST_F(PasswordSyncableServiceTest, FailedProcessSyncChanges) {
  autofill::PasswordForm form;
  form.signon_realm = kSignonRealm;
  form.username_value = base::ASCIIToUTF16(kUsername);
  form.password_value = base::ASCIIToUTF16(kPassword);
  scoped_ptr<syncer::SyncErrorFactoryMock> error_factory(
      new syncer::SyncErrorFactoryMock);
  syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR,
                          "There is a problem", syncer::PASSWORDS);
  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(AppendForm(form));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true));

  // ActOnPasswordStoreChanges() below shouldn't generate any changes for Sync.
  // |processor_| will be destroyed in MergeDataAndStartSyncing().
  EXPECT_CALL(*processor_, ProcessSyncChanges(_, _))
      .Times(1)
      .WillOnce(Return(error));
  syncer::SyncMergeResult result =
      service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
                                          syncer::SyncDataList(),
                                          processor_.Pass(),
                                          error_factory.Pass());
  EXPECT_TRUE(result.error().IsSet());

  form.signon_realm = kSignonRealm2;
  PasswordStoreChangeList list;
  list.push_back(PasswordStoreChange(PasswordStoreChange::ADD, form));
  service()->ActOnPasswordStoreChanges(list);
}

// Tests that empty forms known to the client and/or the server are deleted.
TEST_F(PasswordSyncableServiceTest, MergeEmptyPasswords) {
  autofill::PasswordForm old_empty_form;
  old_empty_form.signon_realm = kSignonRealm;
  old_empty_form.times_used = kTimesUsed;
  old_empty_form.type = kArbitraryType;

  autofill::PasswordForm db_empty_form = old_empty_form;
  db_empty_form.signon_realm = kSignonRealm2;

  autofill::PasswordForm sync_empty_form = old_empty_form;
  sync_empty_form.signon_realm = kSignonRealm3;
  SyncDataList sync_data;
  sync_data.push_back(SyncDataFromPassword(old_empty_form));
  sync_data.push_back(SyncDataFromPassword(sync_empty_form));

  EXPECT_CALL(*password_store(), FillAutofillableLogins(_))
      .WillOnce(DoAll(IgnoreResult(AppendForm(old_empty_form)),
                      AppendForm(db_empty_form)));
  EXPECT_CALL(*password_store(), FillBlacklistLogins(_)).WillOnce(Return(true));

  EXPECT_CALL(*password_store(), RemoveLoginImpl(PasswordIs(old_empty_form)));
  EXPECT_CALL(*password_store(), RemoveLoginImpl(PasswordIs(db_empty_form)));
  EXPECT_CALL(*processor_, ProcessSyncChanges(_, ElementsAre(
      SyncChangeIs(SyncChange::ACTION_DELETE, old_empty_form),
      SyncChangeIs(SyncChange::ACTION_DELETE, sync_empty_form))));

  service()->MergeDataAndStartSyncing(syncer::PASSWORDS,
                                      sync_data,
                                      processor_.Pass(),
                                      scoped_ptr<syncer::SyncErrorFactory>());
}

}  // namespace

}  // namespace password_manager
