// 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 "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h"
#include "sync/api/sync_error_factory.h"
#include "sync/api/sync_error_factory_mock.h"
#include "sync/protocol/sync.pb.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace autofill {

using ::testing::_;
using ::testing::DoAll;
using ::testing::Eq;
using ::testing::Return;
using ::testing::Property;
using base::ASCIIToUTF16;

namespace {

// Some guids for testing.
const char kGuid1[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44B";
const char kGuid2[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44C";
const char kGuid3[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44D";
const char kGuid4[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44E";
const char kHttpOrigin[] = "http://www.example.com/";
const char kHttpsOrigin[] = "https://www.example.com/";
const char kSettingsOrigin[] = "Chrome settings";

class MockAutofillProfileSyncableService
    : public AutofillProfileSyncableService {
 public:
  MockAutofillProfileSyncableService() {}
  virtual ~MockAutofillProfileSyncableService() {}

  using AutofillProfileSyncableService::DataBundle;
  using AutofillProfileSyncableService::set_sync_processor;
  using AutofillProfileSyncableService::CreateData;

  MOCK_METHOD1(LoadAutofillData, bool(std::vector<AutofillProfile*>*));
  MOCK_METHOD1(SaveChangesToWebData,
               bool(const AutofillProfileSyncableService::DataBundle&));
};

ACTION_P(CopyData, data) {
  arg0->resize(data->size());
  std::copy(data->begin(), data->end(), arg0->begin());
}

MATCHER_P(CheckSyncChanges, n_sync_changes_list, "") {
  if (arg.size() != n_sync_changes_list.size())
    return false;
  syncer::SyncChangeList::const_iterator passed, expected;
  for (passed = arg.begin(), expected = n_sync_changes_list.begin();
       passed != arg.end() && expected != n_sync_changes_list.end();
       ++passed, ++expected) {
    DCHECK(passed->IsValid());
    if (passed->change_type() != expected->change_type())
      return false;
    if (passed->sync_data().GetSpecifics().SerializeAsString() !=
            expected->sync_data().GetSpecifics().SerializeAsString()) {
      return false;
    }
  }
  return true;
}

MATCHER_P(DataBundleCheck, n_bundle, "") {
  if ((arg.profiles_to_delete.size() != n_bundle.profiles_to_delete.size()) ||
      (arg.profiles_to_update.size() != n_bundle.profiles_to_update.size()) ||
      (arg.profiles_to_add.size() != n_bundle.profiles_to_add.size()))
    return false;
  for (size_t i = 0; i < arg.profiles_to_delete.size(); ++i) {
    if (arg.profiles_to_delete[i] != n_bundle.profiles_to_delete[i])
      return false;
  }
  for (size_t i = 0; i < arg.profiles_to_update.size(); ++i) {
    if (*arg.profiles_to_update[i] != *n_bundle.profiles_to_update[i])
      return false;
  }
  for (size_t i = 0; i < arg.profiles_to_add.size(); ++i) {
    if (*arg.profiles_to_add[i] != *n_bundle.profiles_to_add[i])
      return false;
  }
  return true;
}

class MockSyncChangeProcessor : public syncer::SyncChangeProcessor {
 public:
  MockSyncChangeProcessor() {}
  ~MockSyncChangeProcessor() override {}

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

class TestSyncChangeProcessor : public syncer::SyncChangeProcessor {
 public:
  TestSyncChangeProcessor() {}
  ~TestSyncChangeProcessor() override {}

  syncer::SyncError ProcessSyncChanges(
      const tracked_objects::Location& location,
      const syncer::SyncChangeList& changes) override {
    changes_ = changes;
    return syncer::SyncError();
  }

  syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override {
    return syncer::SyncDataList();
  }

  const syncer::SyncChangeList& changes() { return changes_; }

 private:
  syncer::SyncChangeList changes_;
};

// Returns a profile with all fields set.  Contains identical data to the data
// returned from ConstructCompleteSyncData().
scoped_ptr<AutofillProfile> ConstructCompleteProfile() {
  scoped_ptr<AutofillProfile> profile(
      new AutofillProfile(kGuid1, kHttpsOrigin));

  profile->set_use_count(7);
  profile->set_use_date(base::Time::FromTimeT(1423182152));

  std::vector<base::string16> names;
  names.push_back(ASCIIToUTF16("John K. Doe, Jr."));
  names.push_back(ASCIIToUTF16("Jane Luise Smith MD"));
  profile->SetRawMultiInfo(NAME_FULL, names);
  names.clear();
  names.push_back(ASCIIToUTF16("John"));
  names.push_back(ASCIIToUTF16("Jane"));
  profile->SetRawMultiInfo(NAME_FIRST, names);
  names.clear();
  names.push_back(ASCIIToUTF16("K."));
  names.push_back(ASCIIToUTF16("Luise"));
  profile->SetRawMultiInfo(NAME_MIDDLE, names);
  names.clear();
  names.push_back(ASCIIToUTF16("Doe"));
  names.push_back(ASCIIToUTF16("Smith"));
  profile->SetRawMultiInfo(NAME_LAST, names);

  std::vector<base::string16> emails;
  emails.push_back(ASCIIToUTF16("user@example.com"));
  emails.push_back(ASCIIToUTF16("superuser@example.org"));
  profile->SetRawMultiInfo(EMAIL_ADDRESS, emails);

  std::vector<base::string16> phones;
  phones.push_back(ASCIIToUTF16("1.800.555.1234"));
  phones.push_back(ASCIIToUTF16("1.866.650.0000"));
  profile->SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, phones);

  profile->SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
                      ASCIIToUTF16("123 Fake St.\n"
                                   "Apt. 42"));
  EXPECT_EQ(ASCIIToUTF16("123 Fake St."),
            profile->GetRawInfo(ADDRESS_HOME_LINE1));
  EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile->GetRawInfo(ADDRESS_HOME_LINE2));

  profile->SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Google, Inc."));
  profile->SetRawInfo(ADDRESS_HOME_CITY, ASCIIToUTF16("Mountain View"));
  profile->SetRawInfo(ADDRESS_HOME_STATE, ASCIIToUTF16("California"));
  profile->SetRawInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("94043"));
  profile->SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("US"));
  profile->SetRawInfo(ADDRESS_HOME_SORTING_CODE, ASCIIToUTF16("CEDEX"));
  profile->SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY,
                      ASCIIToUTF16("Santa Clara"));
  profile->set_language_code("en");
  return profile.Pass();
}

// Returns SyncData with all Autofill profile fields set.  Contains identical
// data to the data returned from ConstructCompleteProfile().
syncer::SyncData ConstructCompleteSyncData() {
  sync_pb::EntitySpecifics entity_specifics;
  sync_pb::AutofillProfileSpecifics* specifics =
      entity_specifics.mutable_autofill_profile();

  specifics->set_guid(kGuid1);
  specifics->set_origin(kHttpsOrigin);
  specifics->set_use_count(7);
  specifics->set_use_date(1423182152);

  specifics->add_name_first("John");
  specifics->add_name_middle("K.");
  specifics->add_name_last("Doe");
  specifics->add_name_full("John K. Doe, Jr.");

  specifics->add_name_first("Jane");
  specifics->add_name_middle("Luise");
  specifics->add_name_last("Smith");
  specifics->add_name_full("Jane Luise Smith MD");

  specifics->add_email_address("user@example.com");
  specifics->add_email_address("superuser@example.org");

  specifics->add_phone_home_whole_number("1.800.555.1234");
  specifics->add_phone_home_whole_number("1.866.650.0000");

  specifics->set_address_home_line1("123 Fake St.");
  specifics->set_address_home_line2("Apt. 42");
  specifics->set_address_home_street_address("123 Fake St.\n"
                                             "Apt. 42");

  specifics->set_company_name("Google, Inc.");
  specifics->set_address_home_city("Mountain View");
  specifics->set_address_home_state("California");
  specifics->set_address_home_zip("94043");
  specifics->set_address_home_country("US");
  specifics->set_address_home_sorting_code("CEDEX");
  specifics->set_address_home_dependent_locality("Santa Clara");
  specifics->set_address_home_language_code("en");

  return syncer::SyncData::CreateLocalData(kGuid1, kGuid1, entity_specifics);
}

}  // namespace

class AutofillProfileSyncableServiceTest : public testing::Test {
 public:
  AutofillProfileSyncableServiceTest() {}

  void SetUp() override { sync_processor_.reset(new MockSyncChangeProcessor); }

  // Wrapper around AutofillProfileSyncableService::MergeDataAndStartSyncing()
  // that also verifies expectations.
  void MergeDataAndStartSyncing(
      const std::vector<AutofillProfile*>& profiles_from_web_db,
      const syncer::SyncDataList& data_list,
      const MockAutofillProfileSyncableService::DataBundle& expected_bundle,
      const syncer::SyncChangeList& expected_change_list) {
    EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
        .Times(1)
        .WillOnce(DoAll(CopyData(&profiles_from_web_db), Return(true)));
    EXPECT_CALL(autofill_syncable_service_,
                SaveChangesToWebData(DataBundleCheck(expected_bundle)))
        .Times(1)
        .WillOnce(Return(true));
    if (expected_change_list.empty()) {
      EXPECT_CALL(*sync_processor_, ProcessSyncChanges(_, _)).Times(0);
    } else {
      ON_CALL(*sync_processor_, ProcessSyncChanges(_, _))
          .WillByDefault(Return(syncer::SyncError()));
      EXPECT_CALL(*sync_processor_,
                  ProcessSyncChanges(_, CheckSyncChanges(expected_change_list)))
          .Times(1)
          .WillOnce(Return(syncer::SyncError()));
    }

    // Takes ownership of sync_processor_.
    autofill_syncable_service_.MergeDataAndStartSyncing(
        syncer::AUTOFILL_PROFILE,
        data_list,
        sync_processor_.Pass(),
        scoped_ptr<syncer::SyncErrorFactory>(
            new syncer::SyncErrorFactoryMock()));
  }

 protected:
  base::MessageLoop message_loop_;
  MockAutofillProfileSyncableService autofill_syncable_service_;
  scoped_ptr<MockSyncChangeProcessor> sync_processor_;
};

TEST_F(AutofillProfileSyncableServiceTest, MergeDataAndStartSyncing) {
  std::vector<AutofillProfile*> profiles_from_web_db;
  std::string guid_present1 = kGuid1;
  std::string guid_present2 = kGuid2;
  std::string guid_synced1 = kGuid3;
  std::string guid_synced2 = kGuid4;
  std::string origin_present1 = kHttpOrigin;
  std::string origin_present2 = std::string();
  std::string origin_synced1 = kHttpsOrigin;
  std::string origin_synced2 = kSettingsOrigin;

  profiles_from_web_db.push_back(
      new AutofillProfile(guid_present1, origin_present1));
  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
                                          ASCIIToUTF16("1 1st st"));
  profiles_from_web_db.push_back(
      new AutofillProfile(guid_present2, origin_present2));
  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
                                          ASCIIToUTF16("2 2nd st"));

  syncer::SyncDataList data_list;
  AutofillProfile profile1(guid_synced1, origin_synced1);
  profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
  data_list.push_back(autofill_syncable_service_.CreateData(profile1));
  AutofillProfile profile2(guid_synced2, origin_synced2);
  profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Harry"));
  data_list.push_back(autofill_syncable_service_.CreateData(profile2));
  // This one will have the name and origin updated.
  AutofillProfile profile3(guid_present2, origin_synced2);
  profile3.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom Doe"));
  data_list.push_back(autofill_syncable_service_.CreateData(profile3));

  syncer::SyncChangeList expected_change_list;
  expected_change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_ADD,
                         MockAutofillProfileSyncableService::CreateData(
                             *profiles_from_web_db.front())));

  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  expected_bundle.profiles_to_add.push_back(&profile1);
  expected_bundle.profiles_to_add.push_back(&profile2);
  expected_bundle.profiles_to_update.push_back(&profile3);

  MergeDataAndStartSyncing(
      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

TEST_F(AutofillProfileSyncableServiceTest, MergeIdenticalProfiles) {
  std::vector<AutofillProfile*> profiles_from_web_db;
  std::string guid_present1 = kGuid1;
  std::string guid_present2 = kGuid2;
  std::string guid_synced1 = kGuid3;
  std::string guid_synced2 = kGuid4;
  std::string origin_present1 = kHttpOrigin;
  std::string origin_present2 = kSettingsOrigin;
  std::string origin_synced1 = kHttpsOrigin;
  std::string origin_synced2 = kHttpsOrigin;

  profiles_from_web_db.push_back(
      new AutofillProfile(guid_present1, origin_present1));
  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
                                          ASCIIToUTF16("1 1st st"));
  profiles_from_web_db.push_back(
      new AutofillProfile(guid_present2, origin_present2));
  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
                                          ASCIIToUTF16("2 2nd st"));

  // The synced profiles are identical to the local ones, except that the guids
  // are different.
  syncer::SyncDataList data_list;
  AutofillProfile profile1(guid_synced1, origin_synced1);
  profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
  data_list.push_back(autofill_syncable_service_.CreateData(profile1));
  AutofillProfile profile2(guid_synced2, origin_synced2);
  profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
  profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st"));
  data_list.push_back(autofill_syncable_service_.CreateData(profile2));

  AutofillProfile expected_profile(profile2);
  expected_profile.set_origin(kSettingsOrigin);
  syncer::SyncChangeList expected_change_list;
  expected_change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_UPDATE,
                         MockAutofillProfileSyncableService::CreateData(
                             expected_profile)));

  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  expected_bundle.profiles_to_delete.push_back(guid_present1);
  expected_bundle.profiles_to_delete.push_back(guid_present2);
  expected_bundle.profiles_to_add.push_back(&profile1);
  expected_bundle.profiles_to_add.push_back(&expected_profile);

  MergeDataAndStartSyncing(
      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

TEST_F(AutofillProfileSyncableServiceTest, MergeSimilarProfiles) {
  std::vector<AutofillProfile*> profiles_from_web_db;
  std::string guid_present1 = kGuid1;
  std::string guid_present2 = kGuid2;
  std::string guid_synced1 = kGuid3;
  std::string guid_synced2 = kGuid4;
  std::string origin_present1 = kHttpOrigin;
  std::string origin_present2 = kSettingsOrigin;
  std::string origin_synced1 = kHttpsOrigin;
  std::string origin_synced2 = kHttpsOrigin;

  profiles_from_web_db.push_back(
      new AutofillProfile(guid_present1, origin_present1));
  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
                                          ASCIIToUTF16("1 1st st"));
  profiles_from_web_db.push_back(
      new AutofillProfile(guid_present2, origin_present2));
  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
  profiles_from_web_db.back()->SetRawInfo(ADDRESS_HOME_LINE1,
                                          ASCIIToUTF16("2 2nd st"));

  // The synced profiles are identical to the local ones, except that the guids
  // are different.
  syncer::SyncDataList data_list;
  AutofillProfile profile1(guid_synced1, origin_synced1);
  profile1.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));
  profile1.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Frobbers, Inc."));
  data_list.push_back(autofill_syncable_service_.CreateData(profile1));
  AutofillProfile profile2(guid_synced2, origin_synced2);
  profile2.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Tom"));
  profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("2 2nd st"));
  profile2.SetRawInfo(COMPANY_NAME, ASCIIToUTF16("Fizzbang, LLC."));
  data_list.push_back(autofill_syncable_service_.CreateData(profile2));

  // The first profile should have its origin updated.
  // The second profile should remain as-is, because an unverified profile
  // should never overwrite a verified one.
  AutofillProfile expected_profile(profile1);
  expected_profile.set_origin(origin_present1);
  syncer::SyncChangeList expected_change_list;
  expected_change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_ADD,
                         MockAutofillProfileSyncableService::CreateData(
                             *profiles_from_web_db.back())));
  expected_change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_UPDATE,
                         MockAutofillProfileSyncableService::CreateData(
                             expected_profile)));

  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  expected_bundle.profiles_to_delete.push_back(guid_present1);
  expected_bundle.profiles_to_add.push_back(&expected_profile);
  expected_bundle.profiles_to_add.push_back(&profile2);

  MergeDataAndStartSyncing(
      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Ensure that no Sync events are generated to fill in missing origins from Sync
// with explicitly present empty ones.  This ensures that the migration to add
// origins to profiles does not generate lots of needless Sync updates.
TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyOrigins) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Create a profile with an empty origin.
  AutofillProfile profile(kGuid1, std::string());
  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  profile.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("1 1st st"));

  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Create a Sync profile identical to |profile|, except with no origin set.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->add_name_first("John");
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  autofill_specifics->set_address_home_line1("1 1st st");
  EXPECT_FALSE(autofill_specifics->has_origin());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  syncer::SyncChangeList expected_change_list;
  MergeDataAndStartSyncing(
      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

TEST_F(AutofillProfileSyncableServiceTest, GetAllSyncData) {
  std::vector<AutofillProfile*> profiles_from_web_db;
  std::string guid_present1 = kGuid1;
  std::string guid_present2 = kGuid2;

  profiles_from_web_db.push_back(
      new AutofillProfile(guid_present1, kHttpOrigin));
  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  profiles_from_web_db.push_back(
      new AutofillProfile(guid_present2, kHttpsOrigin));
  profiles_from_web_db.back()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));

  syncer::SyncChangeList expected_change_list;
  expected_change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_ADD,
                         MockAutofillProfileSyncableService::CreateData(
                             *profiles_from_web_db.front())));
  expected_change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_ADD,
                         MockAutofillProfileSyncableService::CreateData(
                             *profiles_from_web_db.back())));

  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  syncer::SyncDataList data_list;
  MergeDataAndStartSyncing(
      profiles_from_web_db, data_list, expected_bundle, expected_change_list);

  syncer::SyncDataList data =
      autofill_syncable_service_.GetAllSyncData(syncer::AUTOFILL_PROFILE);

  ASSERT_EQ(2U, data.size());
  EXPECT_EQ(guid_present1, data[0].GetSpecifics().autofill_profile().guid());
  EXPECT_EQ(guid_present2, data[1].GetSpecifics().autofill_profile().guid());
  EXPECT_EQ(kHttpOrigin, data[0].GetSpecifics().autofill_profile().origin());
  EXPECT_EQ(kHttpsOrigin, data[1].GetSpecifics().autofill_profile().origin());

  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

TEST_F(AutofillProfileSyncableServiceTest, ProcessSyncChanges) {
  std::vector<AutofillProfile *> profiles_from_web_db;
  std::string guid_present = kGuid1;
  std::string guid_synced = kGuid2;

  syncer::SyncChangeList change_list;
  AutofillProfile profile(guid_synced, kHttpOrigin);
  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
  change_list.push_back(
      syncer::SyncChange(
          FROM_HERE,
          syncer::SyncChange::ACTION_ADD,
          MockAutofillProfileSyncableService::CreateData(profile)));
  AutofillProfile empty_profile(guid_present, kHttpsOrigin);
  change_list.push_back(
      syncer::SyncChange(
          FROM_HERE,
          syncer::SyncChange::ACTION_DELETE,
          MockAutofillProfileSyncableService::CreateData(empty_profile)));

  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  expected_bundle.profiles_to_delete.push_back(guid_present);
  expected_bundle.profiles_to_add.push_back(&profile);

  EXPECT_CALL(autofill_syncable_service_, SaveChangesToWebData(
              DataBundleCheck(expected_bundle)))
      .Times(1)
      .WillOnce(Return(true));

  autofill_syncable_service_.set_sync_processor(sync_processor_.release());
  syncer::SyncError error = autofill_syncable_service_.ProcessSyncChanges(
      FROM_HERE, change_list);

  EXPECT_FALSE(error.IsSet());
}

TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileAdded) {
  // Will be owned by the syncable service.  Keep a reference available here for
  // verifying test expectations.
  TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
  autofill_syncable_service_.set_sync_processor(sync_change_processor);

  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("Jane"));
  AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
  autofill_syncable_service_.AutofillProfileChanged(change);

  ASSERT_EQ(1U, sync_change_processor->changes().size());
  syncer::SyncChange result = sync_change_processor->changes()[0];
  EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());

  sync_pb::AutofillProfileSpecifics specifics =
      result.sync_data().GetSpecifics().autofill_profile();
  EXPECT_EQ(kGuid1, specifics.guid());
  EXPECT_EQ(kHttpsOrigin, specifics.origin());
  EXPECT_THAT(specifics.name_first(), testing::ElementsAre("Jane"));
}

TEST_F(AutofillProfileSyncableServiceTest, AutofillProfileDeleted) {
  // Will be owned by the syncable service.  Keep a reference available here for
  // verifying test expectations.
  TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
  autofill_syncable_service_.set_sync_processor(sync_change_processor);

  AutofillProfileChange change(AutofillProfileChange::REMOVE, kGuid2, NULL);
  autofill_syncable_service_.AutofillProfileChanged(change);

  ASSERT_EQ(1U, sync_change_processor->changes().size());
  syncer::SyncChange result = sync_change_processor->changes()[0];
  EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, result.change_type());
  sync_pb::AutofillProfileSpecifics specifics =
      result.sync_data().GetSpecifics().autofill_profile();
  EXPECT_EQ(kGuid2, specifics.guid());
}

TEST_F(AutofillProfileSyncableServiceTest, UpdateField) {
  AutofillProfile profile(kGuid1, kSettingsOrigin);
  std::string company1 = "A Company";
  std::string company2 = "Another Company";
  profile.SetRawInfo(COMPANY_NAME, ASCIIToUTF16(company1));
  EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
      COMPANY_NAME, company1, &profile));
  EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company1));
  EXPECT_TRUE(AutofillProfileSyncableService::UpdateField(
      COMPANY_NAME, company2, &profile));
  EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2));
  EXPECT_FALSE(AutofillProfileSyncableService::UpdateField(
      COMPANY_NAME, company2, &profile));
  EXPECT_EQ(profile.GetRawInfo(COMPANY_NAME), ASCIIToUTF16(company2));
}

TEST_F(AutofillProfileSyncableServiceTest, UpdateMultivaluedField) {
  AutofillProfile profile(kGuid1, kHttpsOrigin);

  std::vector<base::string16> values;
  values.push_back(ASCIIToUTF16("1@1.com"));
  values.push_back(ASCIIToUTF16("2@1.com"));
  profile.SetRawMultiInfo(EMAIL_ADDRESS, values);

  ::google::protobuf::RepeatedPtrField<std::string> specifics_fields;
  specifics_fields.AddAllocated(new std::string("2@1.com"));
  specifics_fields.AddAllocated(new std::string("3@1.com"));

  EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
      EMAIL_ADDRESS, specifics_fields, &profile));
  profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
  ASSERT_TRUE(values.size() == 2);
  EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com"));
  EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com"));

  EXPECT_FALSE(AutofillProfileSyncableService::UpdateMultivaluedField(
      EMAIL_ADDRESS, specifics_fields, &profile));
  profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
  ASSERT_EQ(values.size(), 2U);
  EXPECT_EQ(values[0], ASCIIToUTF16("2@1.com"));
  EXPECT_EQ(values[1], ASCIIToUTF16("3@1.com"));
  EXPECT_TRUE(AutofillProfileSyncableService::UpdateMultivaluedField(
      EMAIL_ADDRESS, ::google::protobuf::RepeatedPtrField<std::string>(),
      &profile));
  profile.GetRawMultiInfo(EMAIL_ADDRESS, &values);
  ASSERT_EQ(values.size(), 1U);  // Always have at least an empty string.
  EXPECT_EQ(values[0], ASCIIToUTF16(""));
}

TEST_F(AutofillProfileSyncableServiceTest, MergeProfile) {
  AutofillProfile profile1(kGuid1, kHttpOrigin);
  profile1.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));

  std::vector<base::string16> values;
  values.push_back(ASCIIToUTF16("1@1.com"));
  values.push_back(ASCIIToUTF16("2@1.com"));
  profile1.SetRawMultiInfo(EMAIL_ADDRESS, values);

  AutofillProfile profile2(kGuid2, kHttpsOrigin);
  profile2.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));

  // |values| now is [ "1@1.com", "2@1.com", "3@1.com" ].
  values.push_back(ASCIIToUTF16("3@1.com"));
  profile2.SetRawMultiInfo(EMAIL_ADDRESS, values);

  values.clear();
  values.push_back(ASCIIToUTF16("John"));
  profile1.SetRawMultiInfo(NAME_FIRST, values);
  values.push_back(ASCIIToUTF16("Jane"));
  profile2.SetRawMultiInfo(NAME_FIRST, values);

  values.clear();
  values.push_back(ASCIIToUTF16("Doe"));
  profile1.SetRawMultiInfo(NAME_LAST, values);
  values.push_back(ASCIIToUTF16("Other"));
  profile2.SetRawMultiInfo(NAME_LAST, values);

  values.clear();
  values.push_back(ASCIIToUTF16("650234567"));
  profile2.SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, values);

  profile1.set_language_code("en");

  EXPECT_FALSE(AutofillProfileSyncableService::MergeProfile(profile2,
                                                            &profile1,
                                                            "en-US"));

  // The more recent use_date is maintained and synced back.
  profile2.set_use_date(base::Time::FromTimeT(30));
  profile1.set_use_date(base::Time::FromTimeT(25));
  EXPECT_FALSE(AutofillProfileSyncableService::MergeProfile(profile2,
                                                            &profile1,
                                                            "en-US"));
  EXPECT_EQ(base::Time::FromTimeT(30), profile1.use_date());
  profile1.set_use_date(base::Time::FromTimeT(35));
  EXPECT_TRUE(AutofillProfileSyncableService::MergeProfile(profile2,
                                                           &profile1,
                                                           "en-US"));
  EXPECT_EQ(base::Time::FromTimeT(35), profile1.use_date());

  profile1.GetRawMultiInfo(NAME_FIRST, &values);
  ASSERT_EQ(values.size(), 2U);
  EXPECT_EQ(values[0], ASCIIToUTF16("John"));
  EXPECT_EQ(values[1], ASCIIToUTF16("Jane"));

  profile1.GetRawMultiInfo(NAME_LAST, &values);
  ASSERT_EQ(values.size(), 2U);
  EXPECT_EQ(values[0], ASCIIToUTF16("Doe"));
  EXPECT_EQ(values[1], ASCIIToUTF16("Other"));

  profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values);
  ASSERT_EQ(values.size(), 3U);
  EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com"));
  EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com"));
  EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com"));

  profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
  ASSERT_EQ(values.size(), 1U);
  EXPECT_EQ(values[0], ASCIIToUTF16("650234567"));

  EXPECT_EQ(profile2.origin(), profile1.origin());

  AutofillProfile profile3(kGuid3, kHttpOrigin);
  profile3.SetRawInfo(ADDRESS_HOME_LINE1, ASCIIToUTF16("111 First St."));

  values.clear();
  values.push_back(ASCIIToUTF16("Jane"));
  profile3.SetRawMultiInfo(NAME_FIRST, values);

  values.clear();
  values.push_back(ASCIIToUTF16("Doe"));
  profile3.SetRawMultiInfo(NAME_LAST, values);

  EXPECT_TRUE(AutofillProfileSyncableService::MergeProfile(profile3,
                                                           &profile1,
                                                           "en-US"));

  profile1.GetRawMultiInfo(NAME_FIRST, &values);
  ASSERT_EQ(values.size(), 3U);
  EXPECT_EQ(values[0], ASCIIToUTF16("John"));
  EXPECT_EQ(values[1], ASCIIToUTF16("Jane"));
  EXPECT_EQ(values[2], ASCIIToUTF16("Jane"));

  profile1.GetRawMultiInfo(NAME_LAST, &values);
  ASSERT_EQ(values.size(), 3U);
  EXPECT_EQ(values[0], ASCIIToUTF16("Doe"));
  EXPECT_EQ(values[1], ASCIIToUTF16("Other"));
  EXPECT_EQ(values[2], ASCIIToUTF16("Doe"));

  // Middle name should have three entries as well.
  profile1.GetRawMultiInfo(NAME_MIDDLE, &values);
  ASSERT_EQ(values.size(), 3U);
  EXPECT_TRUE(values[0].empty());
  EXPECT_TRUE(values[1].empty());
  EXPECT_TRUE(values[2].empty());

  profile1.GetRawMultiInfo(EMAIL_ADDRESS, &values);
  ASSERT_EQ(values.size(), 3U);
  EXPECT_EQ(values[0], ASCIIToUTF16("1@1.com"));
  EXPECT_EQ(values[1], ASCIIToUTF16("2@1.com"));
  EXPECT_EQ(values[2], ASCIIToUTF16("3@1.com"));

  profile1.GetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, &values);
  ASSERT_EQ(values.size(), 1U);
  EXPECT_EQ(values[0], ASCIIToUTF16("650234567"));
}

// Ensure that all profile fields are able to be synced up from the client to
// the server.
TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToServer) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Create a profile with all fields set.
  profiles_from_web_db.push_back(ConstructCompleteProfile().release());

  // Set up expectations: No changes to the WebDB, and all fields correctly
  // copied to Sync.
  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  syncer::SyncChangeList expected_change_list;
  expected_change_list.push_back(
      syncer::SyncChange(FROM_HERE,
                         syncer::SyncChange::ACTION_ADD,
                         ConstructCompleteSyncData()));

  // Verify the expectations.
  syncer::SyncDataList data_list;
  MergeDataAndStartSyncing(
      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Ensure that all profile fields are able to be synced down from the server to
// the client.
TEST_F(AutofillProfileSyncableServiceTest, SyncAllFieldsToClient) {
  // Create a profile with all fields set.
  syncer::SyncDataList data_list;
  data_list.push_back(ConstructCompleteSyncData());

  // Set up expectations: All fields correctly copied to the WebDB, and no
  // changes propagated to Sync.
  syncer::SyncChangeList expected_change_list;
  scoped_ptr<AutofillProfile> expected_profile = ConstructCompleteProfile();
  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  expected_bundle.profiles_to_add.push_back(expected_profile.get());

  // Verify the expectations.
  std::vector<AutofillProfile*> profiles_from_web_db;
  MergeDataAndStartSyncing(
      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Ensure that the street address field takes precedence over the address line 1
// and line 2 fields, even though these are expected to always be in sync in
// practice.
TEST_F(AutofillProfileSyncableServiceTest,
       StreetAddressTakesPrecedenceOverAddressLines) {
  // Create a Sync profile with conflicting address data in the street address
  // field vs. the address line 1 and address line 2 fields.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(kGuid1);
  autofill_specifics->set_origin(kHttpsOrigin);
  autofill_specifics->add_name_first(std::string());
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  autofill_specifics->set_address_home_line1("123 Example St.");
  autofill_specifics->set_address_home_line2("Apt. 42");
  autofill_specifics->set_address_home_street_address("456 El Camino Real\n"
                                                      "Suite #1337");

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(kGuid1, kGuid1, specifics));

  // Set up expectations: Full street address takes precedence over address
  // lines.
  syncer::SyncChangeList expected_change_list;
  AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
  expected_profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
                              ASCIIToUTF16("456 El Camino Real\n"
                                           "Suite #1337"));
  EXPECT_EQ(ASCIIToUTF16("456 El Camino Real"),
            expected_profile.GetRawInfo(ADDRESS_HOME_LINE1));
  EXPECT_EQ(ASCIIToUTF16("Suite #1337"),
            expected_profile.GetRawInfo(ADDRESS_HOME_LINE2));
  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  expected_bundle.profiles_to_add.push_back(&expected_profile);

  // Verify the expectations.
  std::vector<AutofillProfile*> profiles_from_web_db;
  MergeDataAndStartSyncing(
      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Ensure that no Sync events are generated to fill in missing street address
// fields from Sync with explicitly present ones identical to the data stored in
// the line1 and line2 fields.  This ensures that the migration to add the
// street address field to profiles does not generate lots of needless Sync
// updates.
TEST_F(AutofillProfileSyncableServiceTest, MergeDataEmptyStreetAddress) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Create a profile with the street address set.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS,
                     ASCIIToUTF16("123 Example St.\n"
                                  "Apt. 42"));
  EXPECT_EQ(ASCIIToUTF16("123 Example St."),
            profile.GetRawInfo(ADDRESS_HOME_LINE1));
  EXPECT_EQ(ASCIIToUTF16("Apt. 42"), profile.GetRawInfo(ADDRESS_HOME_LINE2));

  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Create a Sync profile identical to |profile|, except without street address
  // explicitly set.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->set_origin(profile.origin());
  autofill_specifics->add_name_first(std::string());
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  autofill_specifics->set_address_home_line1("123 Example St.");
  autofill_specifics->set_address_home_line2("Apt. 42");
  EXPECT_FALSE(autofill_specifics->has_address_home_street_address());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  syncer::SyncChangeList expected_change_list;
  MergeDataAndStartSyncing(
      profiles_from_web_db, data_list, expected_bundle, expected_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Sync data without origin should not overwrite existing origin in local
// autofill profile.
TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesOrigin) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Local autofill profile has an origin.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Remote data does not have an origin value.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->add_name_first("John");
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  EXPECT_FALSE(autofill_specifics->has_origin());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  // Expect the local autofill profile to still have an origin after sync.
  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  AutofillProfile expected_profile(profile.guid(), profile.origin());
  expected_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  expected_bundle.profiles_to_update.push_back(&expected_profile);

  // Expect no sync events to add origin to the remote data.
  syncer::SyncChangeList expected_empty_change_list;

  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
                           expected_bundle, expected_empty_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Missing language code field should not generate sync events.
TEST_F(AutofillProfileSyncableServiceTest, NoLanguageCodeNoSync) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Local autofill profile has an empty language code.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  EXPECT_TRUE(profile.language_code().empty());
  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Remote data does not have a language code value.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->set_origin(profile.origin());
  autofill_specifics->add_name_first(std::string());
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  EXPECT_FALSE(autofill_specifics->has_address_home_language_code());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  // Expect no changes to local and remote data.
  MockAutofillProfileSyncableService::DataBundle expected_empty_bundle;
  syncer::SyncChangeList expected_empty_change_list;

  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
                           expected_empty_bundle, expected_empty_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Empty language code should be overwritten by sync.
TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesEmptyLanguageCode) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Local autofill profile has an empty language code.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  EXPECT_TRUE(profile.language_code().empty());
  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Remote data has "en" language code.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->set_origin(profile.origin());
  autofill_specifics->add_name_first(std::string());
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  autofill_specifics->set_address_home_language_code("en");
  EXPECT_TRUE(autofill_specifics->has_address_home_language_code());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  // Expect the local autofill profile to have "en" language code after sync.
  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
  expected_profile.set_language_code("en");
  expected_bundle.profiles_to_update.push_back(&expected_profile);

  // Expect no changes to remote data.
  syncer::SyncChangeList expected_empty_change_list;

  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
                           expected_bundle, expected_empty_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Incorrect language code should be overwritten by sync.
TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesIncorrectLanguageCode) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Local autofill profile has "de" language code.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.set_language_code("de");
  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Remote data has "en" language code.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->set_origin(profile.origin());
  autofill_specifics->add_name_first(std::string());
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  autofill_specifics->set_address_home_language_code("en");
  EXPECT_TRUE(autofill_specifics->has_address_home_language_code());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  // Expect the local autofill profile to have "en" language code after sync.
  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  AutofillProfile expected_profile(kGuid1, kHttpsOrigin);
  expected_profile.set_language_code("en");
  expected_bundle.profiles_to_update.push_back(&expected_profile);

  // Expect no changes to remote data.
  syncer::SyncChangeList expected_empty_change_list;

  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
                           expected_bundle, expected_empty_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Sync data without language code should not overwrite existing language code
// in local autofill profile.
TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesLanguageCode) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Local autofill profile has "en" language code.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.set_language_code("en");
  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Remote data does not have a language code value.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->set_origin(profile.origin());
  autofill_specifics->add_name_first("John");
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  EXPECT_FALSE(autofill_specifics->has_address_home_language_code());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  // Expect local autofill profile to still have "en" language code after sync.
  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  AutofillProfile expected_profile(profile.guid(), profile.origin());
  expected_profile.set_language_code("en");
  expected_profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  expected_bundle.profiles_to_update.push_back(&expected_profile);

  // Expect no changes to remote data.
  syncer::SyncChangeList expected_empty_change_list;

  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
                           expected_bundle, expected_empty_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Language code in autofill profiles should be synced to the server.
TEST_F(AutofillProfileSyncableServiceTest, LanguageCodePropagates) {
  TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;
  autofill_syncable_service_.set_sync_processor(sync_change_processor);

  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.set_language_code("en");
  AutofillProfileChange change(AutofillProfileChange::ADD, kGuid1, &profile);
  autofill_syncable_service_.AutofillProfileChanged(change);

  ASSERT_EQ(1U, sync_change_processor->changes().size());
  syncer::SyncChange result = sync_change_processor->changes()[0];
  EXPECT_EQ(syncer::SyncChange::ACTION_ADD, result.change_type());

  sync_pb::AutofillProfileSpecifics specifics =
      result.sync_data().GetSpecifics().autofill_profile();
  EXPECT_EQ(kGuid1, specifics.guid());
  EXPECT_EQ(kHttpsOrigin, specifics.origin());
  EXPECT_EQ("en", specifics.address_home_language_code());
}

// Missing full name field should not generate sync events.
TEST_F(AutofillProfileSyncableServiceTest, NoFullNameNoSync) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Local autofill profile has an empty full name.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.SetRawInfo(NAME_FIRST, ASCIIToUTF16("John"));
  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Remote data does not have a full name.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->set_origin(profile.origin());
  autofill_specifics->add_name_first(std::string("John"));
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  // Expect no changes to local and remote data.
  MockAutofillProfileSyncableService::DataBundle expected_empty_bundle;
  syncer::SyncChangeList expected_empty_change_list;

  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
                           expected_empty_bundle, expected_empty_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

TEST_F(AutofillProfileSyncableServiceTest, EmptySyncPreservesFullName) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Local autofill profile has a full name.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.SetInfo(AutofillType(NAME_FULL),
                  ASCIIToUTF16("John Jacob Smith, Jr"), "en-US");
  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Remote data does not have a full name value.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->set_origin(profile.origin());
  autofill_specifics->add_name_first(std::string("John"));
  autofill_specifics->add_name_middle(std::string("Jacob"));
  autofill_specifics->add_name_last(std::string("Smith"));

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  // Expect local autofill profile to still have the same full name after sync.
  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  AutofillProfile expected_profile(profile.guid(), profile.origin());
  expected_profile.SetInfo(AutofillType(NAME_FULL),
                           ASCIIToUTF16("John Jacob Smith, Jr"),
                           "en-US");
  expected_bundle.profiles_to_update.push_back(&expected_profile);

  // Expect no changes to remote data.
  syncer::SyncChangeList expected_empty_change_list;

  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
                           expected_bundle, expected_empty_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Missing use_count/use_date fields should not generate sync events.
TEST_F(AutofillProfileSyncableServiceTest, NoUsageStatsNoSync) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Local autofill profile has 0 for use_count/use_date.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.set_language_code("en");
  EXPECT_EQ(0U, profile.use_count());
  EXPECT_EQ(base::Time(), profile.use_date());
  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Remote data does not have use_count/use_date.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->set_origin(profile.origin());
  autofill_specifics->add_name_first(std::string());
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  autofill_specifics->set_address_home_language_code("en");
  EXPECT_FALSE(autofill_specifics->has_use_count());
  EXPECT_FALSE(autofill_specifics->has_use_date());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  // Expect no changes to local and remote data.
  MockAutofillProfileSyncableService::DataBundle expected_empty_bundle;
  syncer::SyncChangeList expected_empty_change_list;

  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
                           expected_empty_bundle, expected_empty_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Usage stats should be updated by sync.
TEST_F(AutofillProfileSyncableServiceTest, SyncUpdatesEmptyUsageStats) {
  std::vector<AutofillProfile*> profiles_from_web_db;

  // Local autofill profile has 0 for use_count/use_date.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.set_language_code("en");
  EXPECT_EQ(0U, profile.use_count());
  EXPECT_EQ(base::Time(), profile.use_date());
  profiles_from_web_db.push_back(new AutofillProfile(profile));

  // Remote data has usage stats.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(profile.guid());
  autofill_specifics->set_origin(profile.origin());
  autofill_specifics->add_name_first(std::string());
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  autofill_specifics->set_address_home_language_code("en");
  autofill_specifics->set_use_count(9);
  autofill_specifics->set_use_date(1423182153);
  EXPECT_TRUE(autofill_specifics->has_use_count());
  EXPECT_TRUE(autofill_specifics->has_use_date());

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          profile.guid(), profile.guid(), specifics));

  // Expect the local autofill profile to have usage stats after sync.
  MockAutofillProfileSyncableService::DataBundle expected_bundle;
  AutofillProfile expected_profile = profile;
  expected_profile.set_use_count(9U);
  expected_profile.set_use_date(base::Time::FromTimeT(1423182153));
  expected_bundle.profiles_to_update.push_back(&expected_profile);

  // Expect no changes to remote data.
  syncer::SyncChangeList expected_empty_change_list;

  MergeDataAndStartSyncing(profiles_from_web_db, data_list,
                           expected_bundle, expected_empty_change_list);
  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

// Usage stats should be updated by the client.
TEST_F(AutofillProfileSyncableServiceTest, ClientOverwritesUsageStats) {
  TestSyncChangeProcessor* sync_change_processor = new TestSyncChangeProcessor;

  // Remote data has a profile with usage stats.
  sync_pb::EntitySpecifics specifics;
  sync_pb::AutofillProfileSpecifics* autofill_specifics =
      specifics.mutable_autofill_profile();
  autofill_specifics->set_guid(kGuid1);
  autofill_specifics->set_origin(kHttpsOrigin);
  autofill_specifics->add_name_first(std::string());
  autofill_specifics->add_name_middle(std::string());
  autofill_specifics->add_name_last(std::string());
  autofill_specifics->add_name_full(std::string());
  autofill_specifics->add_email_address(std::string());
  autofill_specifics->add_phone_home_whole_number(std::string());
  autofill_specifics->set_address_home_language_code("en");
  autofill_specifics->set_use_count(9);
  autofill_specifics->set_use_date(25);

  syncer::SyncDataList data_list;
  data_list.push_back(
      syncer::SyncData::CreateLocalData(
          kGuid1, kHttpsOrigin, specifics));

  EXPECT_CALL(autofill_syncable_service_, LoadAutofillData(_))
      .Times(1)
      .WillOnce(Return(true));
  EXPECT_CALL(autofill_syncable_service_,
              SaveChangesToWebData(_))
      .Times(1)
      .WillOnce(Return(true));
  autofill_syncable_service_.MergeDataAndStartSyncing(
      syncer::AUTOFILL_PROFILE,
      data_list,
      make_scoped_ptr(sync_change_processor),
      scoped_ptr<syncer::SyncErrorFactory>(
          new syncer::SyncErrorFactoryMock()));

  // Update to the usage stats for that profile.
  AutofillProfile profile(kGuid1, kHttpsOrigin);
  profile.set_language_code("en");
  profile.set_use_count(10U);
  profile.set_use_date(base::Time::FromTimeT(30));
  AutofillProfileChange change(AutofillProfileChange::UPDATE, kGuid1, &profile);
  autofill_syncable_service_.AutofillProfileChanged(change);
  std::vector<AutofillProfile*> profiles;
  profiles.push_back(&profile);

  ASSERT_EQ(1U, sync_change_processor->changes().size());
  syncer::SyncChange result = sync_change_processor->changes()[0];
  EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, result.change_type());

  sync_pb::AutofillProfileSpecifics result_specifics =
      result.sync_data().GetSpecifics().autofill_profile();
  EXPECT_EQ(10U, result_specifics.use_count());
  EXPECT_EQ(30, result_specifics.use_date());

  autofill_syncable_service_.StopSyncing(syncer::AUTOFILL_PROFILE);
}

}  // namespace autofill
