// Copyright 2013 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_sessions/favicon_cache.h"

#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
#include "components/sync/model/attachments/attachment_id.h"
#include "components/sync/model/attachments/attachment_service_proxy_for_test.h"
#include "components/sync/model/sync_change_processor_wrapper_for_test.h"
#include "components/sync/model/sync_error_factory_mock.h"
#include "components/sync/model/time.h"
#include "components/sync/protocol/favicon_image_specifics.pb.h"
#include "components/sync/protocol/favicon_tracking_specifics.pb.h"
#include "components/sync/protocol/sync.pb.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace sync_sessions {

namespace {

// Total number of favicons to use in sync test batches.
const int kFaviconBatchSize = 10;

// Maximum number of favicons to sync.
const int kMaxSyncFavicons = kFaviconBatchSize*2;

// TestChangeProcessor --------------------------------------------------------

// Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
// back up to Sync.
class TestChangeProcessor : public syncer::SyncChangeProcessor {
 public:
  TestChangeProcessor();
  ~TestChangeProcessor() override;

  // Store a copy of all the changes passed in so we can examine them later.
  syncer::SyncError ProcessSyncChanges(
      const tracked_objects::Location& from_here,
      const syncer::SyncChangeList& change_list) override;

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

  bool contains_guid(const std::string& guid) const {
    return change_map_.count(guid) != 0;
  }

  syncer::SyncChange change_for_guid(const std::string& guid) const {
    DCHECK(contains_guid(guid));
    return change_map_.find(guid)->second;
  }

  // Returns the last change list received, and resets the internal list.
  syncer::SyncChangeList GetAndResetChangeList() {
    syncer::SyncChangeList list;
    list.swap(change_list_);
    return list;
  }

  void set_erroneous(bool erroneous) { erroneous_ = erroneous; }

 private:
  // Track the changes received in ProcessSyncChanges.
  std::map<std::string, syncer::SyncChange> change_map_;
  syncer::SyncChangeList change_list_;
  bool erroneous_;

  DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
};

TestChangeProcessor::TestChangeProcessor() : erroneous_(false) {
}

TestChangeProcessor::~TestChangeProcessor() {
}

syncer::SyncError TestChangeProcessor::ProcessSyncChanges(
    const tracked_objects::Location& from_here,
    const syncer::SyncChangeList& change_list) {
  if (erroneous_) {
    return syncer::SyncError(
        FROM_HERE,
        syncer::SyncError::DATATYPE_ERROR,
        "Some error.",
        change_list[0].sync_data().GetDataType());
  }

  change_list_.insert(change_list_.end(),
                      change_list.begin(),
                      change_list.end());
  change_map_.erase(change_map_.begin(), change_map_.end());
  for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
      iter != change_list.end(); ++iter) {
    change_map_[iter->sync_data().GetTitle()] = *iter;
  }
  return syncer::SyncError();
}

// TestFaviconData ------------------------------------------------------------
struct TestFaviconData {
  TestFaviconData() : last_visit_time(0), is_bookmarked(false) {}
  GURL page_url;
  GURL icon_url;
  std::string image_16;
  std::string image_32;
  std::string image_64;
  int64_t last_visit_time;
  bool is_bookmarked;
};

TestFaviconData BuildFaviconData(int index) {
  TestFaviconData data;
  data.page_url = GURL(base::StringPrintf("http://bla.com/%.2i.html", index));
  data.icon_url = GURL(base::StringPrintf("http://bla.com/%.2i.ico", index));
  data.image_16 = base::StringPrintf("16 %i", index);
  // TODO(zea): enable this once the cache supports writing them.
  // data.image_32 = base::StringPrintf("32 %i", index);
  // data.image_64 = base::StringPrintf("64 %i", index);
  data.last_visit_time = index;
  return data;
}

void FillImageSpecifics(
    const TestFaviconData& test_data,
    sync_pb::FaviconImageSpecifics* image_specifics) {
  image_specifics->set_favicon_url(test_data.icon_url.spec());
  if (!test_data.image_16.empty()) {
    image_specifics->mutable_favicon_web()->set_height(16);
    image_specifics->mutable_favicon_web()->set_width(16);
    image_specifics->mutable_favicon_web()->set_favicon(test_data.image_16);
  }
  if (!test_data.image_32.empty()) {
    image_specifics->mutable_favicon_web_32()->set_height(32);
    image_specifics->mutable_favicon_web_32()->set_width(32);
    image_specifics->mutable_favicon_web_32()->set_favicon(test_data.image_32);
  }
  if (!test_data.image_64.empty()) {
    image_specifics->mutable_favicon_touch_64()->set_height(64);
    image_specifics->mutable_favicon_touch_64()->set_width(64);
    image_specifics->mutable_favicon_touch_64()->
        set_favicon(test_data.image_64);
  }
}

void FillTrackingSpecifics(
    const TestFaviconData& test_data,
    sync_pb::FaviconTrackingSpecifics* tracking_specifics) {
  tracking_specifics->set_favicon_url(test_data.icon_url.spec());
  tracking_specifics->set_last_visit_time_ms(test_data.last_visit_time);
  tracking_specifics->set_is_bookmarked(test_data.is_bookmarked);
}

testing::AssertionResult CompareFaviconDataToSpecifics(
    const TestFaviconData& test_data,
    const sync_pb::EntitySpecifics& specifics) {
  if (specifics.has_favicon_image()) {
    sync_pb::FaviconImageSpecifics image_specifics = specifics.favicon_image();
    if (image_specifics.favicon_url() != test_data.icon_url.spec())
      return testing::AssertionFailure() << "Image icon url doesn't match.";
    if (!test_data.image_16.empty()) {
      if (image_specifics.favicon_web().favicon() != test_data.image_16 ||
          image_specifics.favicon_web().height() != 16 ||
          image_specifics.favicon_web().width() != 16) {
        return testing::AssertionFailure() << "16p image data doesn't match.";
      }
    } else if (image_specifics.has_favicon_web()) {
      return testing::AssertionFailure() << "Missing 16p favicon.";
    }
    if (!test_data.image_32.empty()) {
      if (image_specifics.favicon_web_32().favicon() != test_data.image_32 ||
          image_specifics.favicon_web().height() != 32 ||
          image_specifics.favicon_web().width() != 32) {
        return testing::AssertionFailure() << "32p image data doesn't match.";
      }
    } else if (image_specifics.has_favicon_web_32()) {
      return testing::AssertionFailure() << "Missing 32p favicon.";
    }
    if (!test_data.image_64.empty()) {
      if (image_specifics.favicon_touch_64().favicon() != test_data.image_64 ||
          image_specifics.favicon_web().height() != 64 ||
          image_specifics.favicon_web().width() != 64) {
        return testing::AssertionFailure() << "64p image data doesn't match.";
      }
    } else if (image_specifics.has_favicon_touch_64()) {
      return testing::AssertionFailure() << "Missing 64p favicon.";
    }
  } else {
    sync_pb::FaviconTrackingSpecifics tracking_specifics =
        specifics.favicon_tracking();
    if (tracking_specifics.favicon_url() != test_data.icon_url.spec())
      return testing::AssertionFailure() << "Tracking icon url doesn't match.";
    if (tracking_specifics.last_visit_time_ms() != test_data.last_visit_time)
      return testing::AssertionFailure() << "Visit time doesn't match.";
    if (tracking_specifics.is_bookmarked() != test_data.is_bookmarked)
      return testing::AssertionFailure() << "Bookmark status doens't match.";
  }
  return testing::AssertionSuccess();
}

testing::AssertionResult VerifyChanges(
    syncer::ModelType expected_model_type,
    const std::vector<syncer::SyncChange::SyncChangeType>&
        expected_change_types,
    const std::vector<int>& expected_icons,
    const syncer::SyncChangeList& change_list) {
  DCHECK_EQ(expected_change_types.size(), expected_icons.size());
  if (change_list.size() != expected_icons.size())
    return testing::AssertionFailure() << "Change list size doesn't match.";
  for (size_t i = 0; i < expected_icons.size(); ++i) {
    TestFaviconData data = BuildFaviconData(expected_icons[i]);
    if (change_list[i].sync_data().GetDataType() != expected_model_type)
      return testing::AssertionFailure() << "Change datatype doesn't match.";
    if (change_list[i].change_type() != expected_change_types[i])
      return testing::AssertionFailure() << "Change type doesn't match.";
    if (change_list[i].change_type() == syncer::SyncChange::ACTION_DELETE) {
      if (syncer::SyncDataLocal(change_list[i].sync_data()).GetTag() !=
          data.icon_url.spec())
        return testing::AssertionFailure() << "Deletion url does not match.";
    } else {
      testing::AssertionResult compare_result =
          CompareFaviconDataToSpecifics(
              data,
              change_list[i].sync_data().GetSpecifics());
      if (!compare_result)
        return compare_result;
    }
  }
  return testing::AssertionSuccess();
}

// Helper to extract the favicon id embedded in the tag of a sync
// change.
int GetFaviconId(const syncer::SyncChange change) {
  std::string tag = syncer::SyncDataLocal(change.sync_data()).GetTag();
  const std::string kPrefix = "http://bla.com/";
  const std::string kSuffix = ".ico";
  if (!base::StartsWith(tag, kPrefix, base::CompareCase::SENSITIVE))
    return -1;
  std::string temp = tag.substr(kPrefix.length());
  if (temp.rfind(kSuffix) <= 0)
    return -1;
  temp = temp.substr(0, temp.rfind(kSuffix));
  int result = -1;
  if (!base::StringToInt(temp, &result))
    return -1;
  return result;
}

}  // namespace

class SyncFaviconCacheTest : public testing::Test {
 public:
  SyncFaviconCacheTest();
  ~SyncFaviconCacheTest() override {}

  void SetUpInitialSync(const syncer::SyncDataList& initial_image_data,
                        const syncer::SyncDataList& initial_tracking_data);

  size_t GetFaviconCount() const;
  size_t GetTaskCount() const;

  testing::AssertionResult ExpectFaviconEquals(
        const std::string& page_url,
        const std::string& bytes) const;
  testing::AssertionResult VerifyLocalIcons(
      const std::vector<int>& expected_icons);
  testing::AssertionResult VerifyLocalCustomIcons(
      const std::vector<TestFaviconData>& expected_icons);

  std::unique_ptr<syncer::SyncChangeProcessor> CreateAndPassProcessor();
  std::unique_ptr<syncer::SyncErrorFactory> CreateAndPassSyncErrorFactory();

  FaviconCache* cache() { return &cache_; }
  TestChangeProcessor* processor() { return sync_processor_.get(); }

  // Finish an outstanding favicon load for the icon described in |test_data|.
  void OnCustomFaviconDataAvailable(const TestFaviconData& test_data);

  // Helper method to run the message loop after invoking
  // OnReceivedSyncFavicon, which posts an internal task.
  void TriggerSyncFaviconReceived(const GURL& page_url,
                                  const GURL& icon_url,
                                  const std::string& icon_bytes,
                                  int64_t last_visit_time_ms);

 private:
  base::test::ScopedTaskEnvironment scoped_task_environment_;
  FaviconCache cache_;

  // Our dummy ChangeProcessor used to inspect changes pushed to Sync.
  std::unique_ptr<TestChangeProcessor> sync_processor_;
  std::unique_ptr<syncer::SyncChangeProcessorWrapperForTest>
      sync_processor_wrapper_;
};

SyncFaviconCacheTest::SyncFaviconCacheTest()
    : scoped_task_environment_(
          base::test::ScopedTaskEnvironment::MainThreadType::UI),
      cache_(nullptr, nullptr, kMaxSyncFavicons),
      sync_processor_(new TestChangeProcessor),
      sync_processor_wrapper_(new syncer::SyncChangeProcessorWrapperForTest(
          sync_processor_.get())) {}

void SyncFaviconCacheTest::SetUpInitialSync(
    const syncer::SyncDataList& initial_image_data,
    const syncer::SyncDataList& initial_tracking_data) {
  cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                    initial_image_data,
                                    CreateAndPassProcessor(),
                                    CreateAndPassSyncErrorFactory());
  ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
  cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
                                    initial_tracking_data,
                                    CreateAndPassProcessor(),
                                    CreateAndPassSyncErrorFactory());
  ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
}

size_t SyncFaviconCacheTest::GetFaviconCount() const {
  return cache_.NumFaviconsForTest();
}

size_t SyncFaviconCacheTest::GetTaskCount() const {
  return cache_.NumTasksForTest();
}

testing::AssertionResult SyncFaviconCacheTest::ExpectFaviconEquals(
    const std::string& page_url,
    const std::string& bytes) const {
  GURL gurl(page_url);
  scoped_refptr<base::RefCountedMemory> favicon;
  if (!cache_.GetSyncedFaviconForPageURL(gurl, &favicon))
    return testing::AssertionFailure() << "Favicon is missing.";
  if (favicon->size() != bytes.size())
    return testing::AssertionFailure() << "Favicon sizes don't match.";
  for (size_t i = 0; i < favicon->size(); ++i) {
    if (bytes[i] != *(favicon->front() + i))
      return testing::AssertionFailure() << "Favicon data doesn't match.";
  }
  return testing::AssertionSuccess();
}

testing::AssertionResult SyncFaviconCacheTest::VerifyLocalIcons(
    const std::vector<int>& expected_icons) {
  std::vector<TestFaviconData> expected_custom_icons;
  for (size_t i = 0; i < expected_icons.size(); ++i) {
    expected_custom_icons.push_back(BuildFaviconData(expected_icons[i]));
  }
  return VerifyLocalCustomIcons(expected_custom_icons);
}


testing::AssertionResult SyncFaviconCacheTest::VerifyLocalCustomIcons(
    const std::vector<TestFaviconData>& expected_custom_icons) {
  syncer::SyncDataList image_data_list =
      cache()->GetAllSyncData(syncer::FAVICON_IMAGES);
  syncer::SyncDataList tracking_data_list =
      cache()->GetAllSyncData(syncer::FAVICON_TRACKING);
  if (expected_custom_icons.size() > image_data_list.size() ||
      expected_custom_icons.size() > tracking_data_list.size())
    return testing::AssertionFailure() << "Number of icons doesn't match.";
  for (size_t i = 0; i < expected_custom_icons.size(); ++i) {
    const TestFaviconData& test_data = expected_custom_icons[i];
    // Find the test data in the data lists. Assume that both lists have the
    // same ordering, which may not match the |expected_custom_icons| ordering.
    bool found_match = false;
    for (size_t j = 0; j < image_data_list.size(); ++j) {
      if (image_data_list[j].GetTitle() != test_data.icon_url.spec())
        continue;
      found_match = true;
      const sync_pb::FaviconImageSpecifics& image_specifics =
          image_data_list[j].GetSpecifics().favicon_image();
      sync_pb::FaviconImageSpecifics expected_image_specifics;
      FillImageSpecifics(test_data, &expected_image_specifics);
      if (image_specifics.SerializeAsString() !=
          expected_image_specifics.SerializeAsString()) {
        return testing::AssertionFailure() << "Image data doesn't match.";
      }
      const sync_pb::FaviconTrackingSpecifics& tracking_specifics =
          tracking_data_list[j].GetSpecifics().favicon_tracking();
      sync_pb::FaviconTrackingSpecifics expected_tracking_specifics;
      FillTrackingSpecifics(test_data, &expected_tracking_specifics);
      if (tracking_specifics.SerializeAsString() !=
          expected_tracking_specifics.SerializeAsString()) {
        return testing::AssertionFailure() << "Tracking data doesn't match.";
      }
    }
    if (!found_match)
      return testing::AssertionFailure() << "Could not find favicon.";
  }
  return testing::AssertionSuccess();
}

std::unique_ptr<syncer::SyncChangeProcessor>
SyncFaviconCacheTest::CreateAndPassProcessor() {
  return base::MakeUnique<syncer::SyncChangeProcessorWrapperForTest>(
      sync_processor_.get());
}

std::unique_ptr<syncer::SyncErrorFactory>
SyncFaviconCacheTest::CreateAndPassSyncErrorFactory() {
  return base::WrapUnique(new syncer::SyncErrorFactoryMock);
}

void SyncFaviconCacheTest::OnCustomFaviconDataAvailable(
    const TestFaviconData& test_data) {
  std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results;
  if (!test_data.image_16.empty()) {
    favicon_base::FaviconRawBitmapResult bitmap_result;
    bitmap_result.icon_url = test_data.icon_url;
    bitmap_result.pixel_size.set_width(16);
    bitmap_result.pixel_size.set_height(16);
    base::RefCountedString* temp_string = new base::RefCountedString();
    temp_string->data() = test_data.image_16;
    bitmap_result.bitmap_data = temp_string;
    bitmap_results.push_back(bitmap_result);
  }
  if (!test_data.image_32.empty()) {
    favicon_base::FaviconRawBitmapResult bitmap_result;
    bitmap_result.icon_url = test_data.icon_url;
    bitmap_result.pixel_size.set_width(32);
    bitmap_result.pixel_size.set_height(32);
    base::RefCountedString* temp_string = new base::RefCountedString();
    temp_string->data() = test_data.image_32;
    bitmap_result.bitmap_data = temp_string;
    bitmap_results.push_back(bitmap_result);
  }
  if (!test_data.image_64.empty()) {
    favicon_base::FaviconRawBitmapResult bitmap_result;
    bitmap_result.icon_url = test_data.icon_url;
    bitmap_result.pixel_size.set_width(64);
    bitmap_result.pixel_size.set_height(64);
    base::RefCountedString* temp_string = new base::RefCountedString();
    temp_string->data() = test_data.image_64;
    bitmap_result.bitmap_data = temp_string;
    bitmap_results.push_back(bitmap_result);
  }
  cache()->OnFaviconDataAvailable(test_data.page_url, bitmap_results);
}

void SyncFaviconCacheTest::TriggerSyncFaviconReceived(
    const GURL& page_url,
    const GURL& icon_url,
    const std::string& icon_bytes,
    int64_t last_visit_time_ms) {
  cache()->OnReceivedSyncFavicon(page_url,
                                 icon_url,
                                 icon_bytes,
                                 last_visit_time_ms);
  base::RunLoop().RunUntilIdle();
}

// A freshly constructed cache should be empty.
TEST_F(SyncFaviconCacheTest, Empty) {
  EXPECT_EQ(0U, GetFaviconCount());
}

TEST_F(SyncFaviconCacheTest, ReceiveSyncFavicon) {
  std::string page_url = "http://www.google.com";
  std::string fav_url = "http://www.google.com/favicon.ico";
  std::string bytes = "bytes";
  EXPECT_EQ(0U, GetFaviconCount());
  TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
  EXPECT_EQ(1U, GetFaviconCount());
  EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
}

TEST_F(SyncFaviconCacheTest, ReceiveEmptySyncFavicon) {
  std::string page_url = "http://www.google.com";
  std::string fav_url = "http://www.google.com/favicon.ico";
  std::string bytes = "bytes";
  EXPECT_EQ(0U, GetFaviconCount());
  TriggerSyncFaviconReceived(GURL(page_url),
                             GURL(fav_url),
                             std::string(),
                             0);
  EXPECT_EQ(0U, GetFaviconCount());
  EXPECT_FALSE(ExpectFaviconEquals(page_url, std::string()));

  // Then receive the actual favicon.
  TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
  EXPECT_EQ(1U, GetFaviconCount());
  EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
}

TEST_F(SyncFaviconCacheTest, ReceiveUpdatedSyncFavicon) {
  std::string page_url = "http://www.google.com";
  std::string fav_url = "http://www.google.com/favicon.ico";
  std::string bytes = "bytes";
  std::string bytes2 = "bytes2";
  EXPECT_EQ(0U, GetFaviconCount());
  TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
  EXPECT_EQ(1U, GetFaviconCount());
  EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));

  // The cache should not update existing favicons from tab sync favicons
  // (which can be reassociated several times).
  TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes2, 0);
  EXPECT_EQ(1U, GetFaviconCount());
  EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
  EXPECT_FALSE(ExpectFaviconEquals(page_url, bytes2));
}

TEST_F(SyncFaviconCacheTest, MultipleMappings) {
  std::string page_url = "http://www.google.com";
  std::string page2_url = "http://bla.google.com";
  std::string fav_url = "http://www.google.com/favicon.ico";
  std::string bytes = "bytes";
  EXPECT_EQ(0U, GetFaviconCount());
  TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
  EXPECT_EQ(1U, GetFaviconCount());
  EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));

  // Map another page to the same favicon. They should share the same data.
  TriggerSyncFaviconReceived(GURL(page2_url), GURL(fav_url), bytes, 0);
  EXPECT_EQ(1U, GetFaviconCount());
  EXPECT_TRUE(ExpectFaviconEquals(page2_url, bytes));
}

TEST_F(SyncFaviconCacheTest, SyncEmpty) {
  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        syncer::SyncDataList(),
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());

  EXPECT_EQ(0U, cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(0, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(0, merge_result.num_items_before_association());
  EXPECT_EQ(0, merge_result.num_items_after_association());

  merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
                                        syncer::SyncDataList(),
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());

  EXPECT_EQ(0U, cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(0, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(0, merge_result.num_items_before_association());
  EXPECT_EQ(0, merge_result.num_items_after_association());
}

// Setting up sync with existing local favicons should push those favicons into
// sync.
TEST_F(SyncFaviconCacheTest, SyncExistingLocal) {
  std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
  std::vector<int> expected_icons;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData favicon = BuildFaviconData(i);
    TriggerSyncFaviconReceived(favicon.page_url,
                               favicon.icon_url,
                               favicon.image_16,
                               i);
    expected_change_types.push_back(syncer::SyncChange::ACTION_ADD);
    expected_icons.push_back(i);
  }

  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        syncer::SyncDataList(),
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize),
            cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
  syncer::SyncChangeList change_list = processor()->GetAndResetChangeList();
  EXPECT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
                            expected_change_types,
                            expected_icons,
                            change_list));
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(0, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());

  merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
                                        syncer::SyncDataList(),
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize),
            cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
  change_list = processor()->GetAndResetChangeList();
  EXPECT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
                            expected_change_types,
                            expected_icons,
                            change_list));
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(0, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
}

// Setting up sync with existing sync data should load that data into the local
// cache.
TEST_F(SyncFaviconCacheTest, SyncExistingRemote) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  std::vector<int> expected_icons;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        initial_image_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize),
            cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_added());
  EXPECT_EQ(0, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(0, merge_result.num_items_before_association());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());

  merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
                                        initial_tracking_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize),
            cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());

  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
}

// Setting up sync with local data and sync data should merge the two image
// sets, with remote data having priority in case both exist.
TEST_F(SyncFaviconCacheTest, SyncMergesImages) {
  // First go through and add local 16p favicons.
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData favicon = BuildFaviconData(i);
    TriggerSyncFaviconReceived(favicon.page_url,
                               favicon.icon_url,
                               favicon.image_16,
                               i);
  }

  // Then go through and create the initial sync data, which does not have 16p
  // favicons for the first half, and has custom 16p favicons for the second.
  std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
  std::vector<int> expected_icons;
  std::vector<TestFaviconData> expected_data;
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    TestFaviconData test_data = BuildFaviconData(i);
    if (i < kFaviconBatchSize/2) {
      test_data.image_16 = std::string();
      expected_icons.push_back(i);
      expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    } else {
      test_data.image_16 += "custom";
      expected_data.push_back(test_data);
    }
    FillImageSpecifics(test_data,
                       image_specifics.mutable_favicon_image());

    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(test_data,
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        initial_image_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize),
            cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize)/2, changes.size());
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());

  merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
                                        initial_tracking_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize),
            cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());

  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
  ASSERT_TRUE(VerifyLocalCustomIcons(expected_data));
  ASSERT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
                            expected_change_types,
                            expected_icons,
                            changes));
}

// Setting up sync with local data and sync data should merge the two tracking
// sets, such that the visit time is the most recent.
TEST_F(SyncFaviconCacheTest, SyncMergesTracking) {
  // First go through and add local 16p favicons.
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData favicon = BuildFaviconData(i);
    TriggerSyncFaviconReceived(favicon.page_url,
                               favicon.icon_url,
                               favicon.image_16,
                               i);
  }

  // Then go through and create the initial sync data, which for the first half
  // the local has a newer visit, and for the second the remote does.
  std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
  std::vector<int> expected_icons;
  std::vector<TestFaviconData> expected_data;
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    TestFaviconData test_data = BuildFaviconData(i);
    if (i < kFaviconBatchSize/2) {
      test_data.last_visit_time = i-1;
      expected_icons.push_back(i);
      expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    } else {
      test_data.last_visit_time = i+1;
      expected_data.push_back(test_data);
    }
    FillImageSpecifics(test_data,
                       image_specifics.mutable_favicon_image());

    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(test_data,
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        initial_image_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize),
            cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());

  merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
                                        initial_tracking_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize),
            cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize)/2, changes.size());
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
  EXPECT_EQ(0, merge_result.num_items_deleted());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
  EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());

  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
  ASSERT_TRUE(VerifyLocalCustomIcons(expected_data));
  ASSERT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
                            expected_change_types,
                            expected_icons,
                            changes));
}

// Receiving old icons (missing image data) should result in pushing the new
// merged icons back to the remote syncer.
TEST_F(SyncFaviconCacheTest, ReceiveStaleImages) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  syncer::SyncChangeList stale_changes;
  std::vector<int> expected_icons;
  std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    image_specifics.mutable_favicon_image()->clear_favicon_web();
    stale_changes.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_UPDATE,
        syncer::SyncData::CreateRemoteData(
            1,
            image_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // Now receive the same icons as an update, but with missing image data.
  cache()->ProcessSyncChanges(FROM_HERE, stale_changes);
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
  ASSERT_EQ(static_cast<size_t>(kFaviconBatchSize), changes.size());
  ASSERT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
                            expected_change_types,
                            expected_icons,
                            changes));
}

// New icons should be added locally without pushing anything back to the
// remote syncer.
TEST_F(SyncFaviconCacheTest, ReceiveNewImages) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  syncer::SyncChangeList new_changes;
  std::vector<int> expected_icons;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    TestFaviconData test_data = BuildFaviconData(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(test_data,
                       image_specifics.mutable_favicon_image());
    new_changes.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_UPDATE,
        syncer::SyncData::CreateRemoteData(
            1,
            image_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
    image_specifics.mutable_favicon_image()
        ->mutable_favicon_web()
        ->mutable_favicon()
        ->append("old");
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // Now receive the new icons as an update.
  cache()->ProcessSyncChanges(FROM_HERE, new_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
}

// Recieving the same icons as the local data should have no effect.
TEST_F(SyncFaviconCacheTest, ReceiveSameImages) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  syncer::SyncChangeList same_changes;
  std::vector<int> expected_icons;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    TestFaviconData test_data = BuildFaviconData(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(test_data,
                       image_specifics.mutable_favicon_image());
    same_changes.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_UPDATE,
        syncer::SyncData::CreateRemoteData(
            1,
            image_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // Now receive the new icons as an update.
  cache()->ProcessSyncChanges(FROM_HERE, same_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
}

// Receiving stale tracking (old visit times) should result in pushing back
// the newer visit times to the remote syncer.
TEST_F(SyncFaviconCacheTest, ReceiveStaleTracking) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  syncer::SyncChangeList stale_changes;
  std::vector<int> expected_icons;
  std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(-1);
    stale_changes.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_UPDATE,
        syncer::SyncData::CreateRemoteData(
            1,
            tracking_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // Now receive the same icons as an update, but with missing image data.
  cache()->ProcessSyncChanges(FROM_HERE, stale_changes);
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
  ASSERT_EQ(static_cast<size_t>(kFaviconBatchSize), changes.size());
  ASSERT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
                            expected_change_types,
                            expected_icons,
                            changes));
}

// New tracking information should be added locally without pushing anything
// back to the remote syncer.
TEST_F(SyncFaviconCacheTest, ReceiveNewTracking) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  syncer::SyncChangeList new_changes;
  std::vector<int> expected_icons;
  // We start from one here so that we don't have to deal with a -1 visit time.
  for (int i = 1; i <= kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    new_changes.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_UPDATE,
        syncer::SyncData::CreateRemoteData(
            1,
            tracking_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
    tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(i-1);
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // Now receive the new icons as an update.
  cache()->ProcessSyncChanges(FROM_HERE, new_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
}

// Receiving the same tracking information as the local data should have no
// effect.
TEST_F(SyncFaviconCacheTest, ReceiveSameTracking) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  syncer::SyncChangeList same_changes;
  std::vector<int> expected_icons;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    same_changes.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_UPDATE,
        syncer::SyncData::CreateRemoteData(
            1,
            tracking_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // Now receive the new icons as an update.
  cache()->ProcessSyncChanges(FROM_HERE, same_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
}

// Verify we can delete favicons after setting up sync.
TEST_F(SyncFaviconCacheTest, DeleteFavicons) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  syncer::SyncChangeList tracking_deletions, image_deletions;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    tracking_deletions.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_DELETE,
        syncer::SyncData::CreateRemoteData(
            1,
            tracking_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
    image_deletions.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_DELETE,
        syncer::SyncData::CreateRemoteData(
            1,
            image_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // Now receive the tracking deletions. Since we'll still have orphan data,
  // the favicon count should remain the same.
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());
  cache()->ProcessSyncChanges(FROM_HERE, tracking_deletions);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());

  // Once the image deletions arrive, the favicon count should be 0 again.
  cache()->ProcessSyncChanges(FROM_HERE, image_deletions);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(0U, GetFaviconCount());
}

// Ensure that MergeDataAndStartSyncing enforces the sync favicon limit by
// dropping local icons.
TEST_F(SyncFaviconCacheTest, ExpireOnMergeData) {
  std::vector<int> expected_icons;
  syncer::SyncDataList initial_image_data, initial_tracking_data;

  // Set up sync so it has the maximum number of favicons, while the local has
  // the same amount of different favicons.
  for (int i = 0; i < kMaxSyncFavicons; ++i) {
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    expected_icons.push_back(i);

    TestFaviconData favicon = BuildFaviconData(i+kMaxSyncFavicons);
    TriggerSyncFaviconReceived(favicon.page_url,
                               favicon.icon_url,
                               favicon.image_16,
                               i+kMaxSyncFavicons);
  }

  EXPECT_FALSE(VerifyLocalIcons(expected_icons));

  // Drops image part of the unsynced icons.
  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        initial_image_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kMaxSyncFavicons)*2,
            GetFaviconCount());  // Still have tracking.
  EXPECT_EQ(static_cast<size_t>(kMaxSyncFavicons),
            cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_added());
  EXPECT_EQ(0, merge_result.num_items_modified());
  EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_deleted());
  EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_before_association());
  EXPECT_EQ(kMaxSyncFavicons * 2, merge_result.num_items_after_association());

  // Drops tracking part of the unsynced icons.
  merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
                                        initial_tracking_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ(static_cast<size_t>(kMaxSyncFavicons),
            cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(0, merge_result.num_items_added());
  EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_modified());
  EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_deleted());
  EXPECT_EQ(kMaxSyncFavicons * 2, merge_result.num_items_before_association());
  EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_after_association());

  EXPECT_TRUE(VerifyLocalIcons(expected_icons));
}

// Receiving sync additions (via ProcessSyncChanges) should not trigger
// expirations.
TEST_F(SyncFaviconCacheTest, NoExpireOnProcessSyncChanges) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  syncer::SyncChangeList image_changes, tracking_changes;
  std::vector<int> expected_icons;
  for (int i = 0; i < kMaxSyncFavicons; ++i) {
    expected_icons.push_back(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    // Set up new tracking specifics for the icons received at change time.
    expected_icons.push_back(i + kMaxSyncFavicons);
    FillImageSpecifics(BuildFaviconData(i + kMaxSyncFavicons),
                       image_specifics.mutable_favicon_image());
    image_changes.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_ADD,
        syncer::SyncData::CreateRemoteData(
            1,
            image_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
    FillTrackingSpecifics(BuildFaviconData(i + kMaxSyncFavicons),
                          tracking_specifics.mutable_favicon_tracking());
    tracking_changes.push_back(syncer::SyncChange(
        FROM_HERE,
        syncer::SyncChange::ACTION_ADD,
        syncer::SyncData::CreateRemoteData(
            1,
            tracking_specifics,
            base::Time(),
            syncer::AttachmentIdList(),
            syncer::AttachmentServiceProxyForTest::Create())));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // Now receive the new icons as an update.
  EXPECT_EQ(static_cast<size_t>(kMaxSyncFavicons), GetFaviconCount());
  cache()->ProcessSyncChanges(FROM_HERE, image_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  cache()->ProcessSyncChanges(FROM_HERE, tracking_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_TRUE(VerifyLocalIcons(expected_icons));
  EXPECT_LT(static_cast<size_t>(kMaxSyncFavicons), GetFaviconCount());
}

// Test that visiting a new page triggers a favicon load and a sync addition.
TEST_F(SyncFaviconCacheTest, AddOnFaviconVisited) {
  EXPECT_EQ(0U, GetFaviconCount());
  SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
  std::vector<int> expected_icons;

  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    TestFaviconData test_data = BuildFaviconData(i);
    cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
  }

  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetTaskCount());

  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    OnCustomFaviconDataAvailable(test_data);

    syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    ASSERT_EQ(2U, changes.size());
    EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
    EXPECT_EQ(syncer::FAVICON_IMAGES, changes[0].sync_data().GetDataType());
    EXPECT_TRUE(
        CompareFaviconDataToSpecifics(test_data,
                                      changes[0].sync_data().GetSpecifics()));
    EXPECT_EQ(syncer::FAVICON_TRACKING, changes[1].sync_data().GetDataType());
    // Just verify the favicon url for the tracking specifics and that the
    // timestamp is non-null.
    EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[1].change_type());
    EXPECT_EQ(test_data.icon_url.spec(),
              changes[1].sync_data().GetSpecifics().favicon_tracking().
                  favicon_url());
    EXPECT_NE(changes[1].sync_data().GetSpecifics().favicon_tracking().
                  last_visit_time_ms(), 0);
  }

  EXPECT_EQ(0U, GetTaskCount());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());
}

// Test that visiting a known page does not trigger a favicon load and just
// updates the sync tracking info.
TEST_F(SyncFaviconCacheTest, UpdateOnFaviconVisited) {
  EXPECT_EQ(0U, GetFaviconCount());
  SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
  std::vector<int> expected_icons;

  // Add the favicons.
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    TestFaviconData test_data = BuildFaviconData(i);
    cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
    OnCustomFaviconDataAvailable(test_data);
  }
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();

  // Visit the favicons again.
  EXPECT_EQ(0U, GetTaskCount());
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);

    syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    ASSERT_EQ(1U, changes.size());
    // Just verify the favicon url for the tracking specifics and that the
    // timestamp is non-null.
    EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
    EXPECT_EQ(test_data.icon_url.spec(),
              changes[0].sync_data().GetSpecifics().favicon_tracking().
                  favicon_url());
    EXPECT_NE(changes[0].sync_data().GetSpecifics().favicon_tracking().
                  last_visit_time_ms(), 0);
  }
  EXPECT_EQ(0U, GetTaskCount());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());
}

// Ensure we properly expire old synced favicons as new ones are updated.
TEST_F(SyncFaviconCacheTest, ExpireOnFaviconVisited) {
  EXPECT_EQ(0U, GetFaviconCount());
  SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
  std::vector<int> expected_icons;

  // Add the initial favicons.
  for (int i = 0; i < kMaxSyncFavicons; ++i) {
    expected_icons.push_back(i);
    TestFaviconData test_data = BuildFaviconData(i);
    cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
    OnCustomFaviconDataAvailable(test_data);
  }
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();

  // Visit some new favicons, triggering expirations of the old favicons.
  EXPECT_EQ(0U, GetTaskCount());
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData old_favicon = BuildFaviconData(i);
    TestFaviconData test_data = BuildFaviconData(i + kMaxSyncFavicons);
    cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
    OnCustomFaviconDataAvailable(test_data);

    syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    ASSERT_EQ(4U, changes.size());
    EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
    EXPECT_TRUE(
        CompareFaviconDataToSpecifics(test_data,
                                      changes[0].sync_data().GetSpecifics()));
    EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, changes[1].change_type());
    EXPECT_EQ(old_favicon.icon_url.spec(),
              syncer::SyncDataLocal(changes[1].sync_data()).GetTag());

    EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[2].change_type());
    EXPECT_EQ(test_data.icon_url.spec(),
              changes[2].sync_data().GetSpecifics().favicon_tracking().
                  favicon_url());
    EXPECT_NE(changes[2].sync_data().GetSpecifics().favicon_tracking().
                  last_visit_time_ms(), 0);
    EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, changes[3].change_type());
    EXPECT_EQ(old_favicon.icon_url.spec(),
              syncer::SyncDataLocal(changes[3].sync_data()).GetTag());
  }

  EXPECT_EQ(0U, GetTaskCount());
  EXPECT_EQ(static_cast<size_t>(kMaxSyncFavicons), GetFaviconCount());
}

// A full history clear notification should result in all synced favicons being
// deleted.
TEST_F(SyncFaviconCacheTest, HistoryFullClear) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  std::vector<int> expected_icons;
  std::vector<syncer::SyncChange::SyncChangeType> expected_deletions;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    expected_deletions.push_back(syncer::SyncChange::ACTION_DELETE);
    TestFaviconData test_data = BuildFaviconData(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(test_data,
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  EXPECT_TRUE(changes.empty());

  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());
  cache()->OnURLsDeleted(nullptr, true, false, history::URLRows(),
                         std::set<GURL>());
  EXPECT_EQ(0U, GetFaviconCount());
  changes = processor()->GetAndResetChangeList();
  ASSERT_EQ(changes.size(), static_cast<size_t>(kFaviconBatchSize)*2);
  syncer::SyncChangeList changes_1, changes_2;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    changes_1.push_back(changes[i]);
    changes_2.push_back(changes[i + kFaviconBatchSize]);
  }
  VerifyChanges(syncer::FAVICON_IMAGES,
                expected_deletions,
                expected_icons,
                changes_1);
  VerifyChanges(syncer::FAVICON_TRACKING,
                expected_deletions,
                expected_icons,
                changes_2);
}

// A partial history clear notification should result in the expired favicons
// also being deleted from sync.
TEST_F(SyncFaviconCacheTest, HistorySubsetClear) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  std::vector<int> expected_icons;
  std::vector<syncer::SyncChange::SyncChangeType> expected_deletions;
  std::set<GURL> favicon_urls_to_delete;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    if (i < kFaviconBatchSize/2) {
      expected_icons.push_back(i);
      expected_deletions.push_back(syncer::SyncChange::ACTION_DELETE);
      favicon_urls_to_delete.insert(test_data.icon_url);
    }
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(test_data,
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  EXPECT_TRUE(changes.empty());

  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());
  cache()->OnURLsDeleted(nullptr, false, false, history::URLRows(),
                         favicon_urls_to_delete);
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize)/2, GetFaviconCount());
  changes = processor()->GetAndResetChangeList();
  ASSERT_EQ(changes.size(), static_cast<size_t>(kFaviconBatchSize));
  syncer::SyncChangeList changes_1, changes_2;
  for (size_t i = 0; i < kFaviconBatchSize/2; ++i) {
    changes_1.push_back(changes[i]);
    changes_2.push_back(changes[i + kFaviconBatchSize/2]);
  }
  VerifyChanges(syncer::FAVICON_IMAGES,
                expected_deletions,
                expected_icons,
                changes_1);
  VerifyChanges(syncer::FAVICON_TRACKING,
                expected_deletions,
                expected_icons,
                changes_2);
}

// Any favicon urls with the "data" scheme should be ignored.
TEST_F(SyncFaviconCacheTest, IgnoreDataScheme) {
  EXPECT_EQ(0U, GetFaviconCount());
  SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
  std::vector<int> expected_icons;

  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    cache()->OnFaviconVisited(test_data.page_url, GURL());
  }

  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetTaskCount());

  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    test_data.icon_url = GURL("data:image/png;base64;blabla");
    EXPECT_TRUE(test_data.icon_url.is_valid());
    OnCustomFaviconDataAvailable(test_data);
  }

  EXPECT_EQ(0U, GetTaskCount());
  EXPECT_EQ(0U, GetFaviconCount());
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  EXPECT_TRUE(changes.empty());
}

// When visiting a page we've already loaded the favicon for, don't attempt to
// reload the favicon, just update the visit time using the cached icon url.
TEST_F(SyncFaviconCacheTest, ReuseCachedIconUrl) {
  EXPECT_EQ(0U, GetFaviconCount());
  SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
  std::vector<int> expected_icons;

  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    TestFaviconData test_data = BuildFaviconData(i);
    cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
  }

  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetTaskCount());

  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    OnCustomFaviconDataAvailable(test_data);
  }
  processor()->GetAndResetChangeList();
  EXPECT_EQ(0U, GetTaskCount());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());

  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
    syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    ASSERT_EQ(1U, changes.size());
    // Just verify the favicon url for the tracking specifics and that the
    // timestamp is non-null.
    EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
    EXPECT_EQ(test_data.icon_url.spec(),
              changes[0].sync_data().GetSpecifics().favicon_tracking().
                  favicon_url());
    EXPECT_NE(changes[0].sync_data().GetSpecifics().favicon_tracking().
                  last_visit_time_ms(), 0);
  }
  EXPECT_EQ(0U, GetTaskCount());
}

// If we wind up with orphan image/tracking nodes, then receive an update
// for those favicons, we should lazily create the missing nodes.
TEST_F(SyncFaviconCacheTest, UpdatedOrphans) {
  EXPECT_EQ(0U, GetFaviconCount());
  SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());

  syncer::SyncChangeList initial_image_changes;
  syncer::SyncChangeList initial_tracking_changes;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    // Even favicons have image data but no tracking data. Odd favicons have
    // tracking data but no image data.
    if (i % 2 == 0) {
      sync_pb::EntitySpecifics image_specifics;
      FillImageSpecifics(BuildFaviconData(i),
                         image_specifics.mutable_favicon_image());
      initial_image_changes.push_back(syncer::SyncChange(
          FROM_HERE,
          syncer::SyncChange::ACTION_ADD,
          syncer::SyncData::CreateRemoteData(
              1,
              image_specifics,
              base::Time(),
              syncer::AttachmentIdList(),
              syncer::AttachmentServiceProxyForTest::Create())));
    } else {
      sync_pb::EntitySpecifics tracking_specifics;
      FillTrackingSpecifics(BuildFaviconData(i),
                            tracking_specifics.mutable_favicon_tracking());
      initial_tracking_changes.push_back(syncer::SyncChange(
          FROM_HERE,
          syncer::SyncChange::ACTION_ADD,
          syncer::SyncData::CreateRemoteData(
              1,
              tracking_specifics,
              base::Time(),
              syncer::AttachmentIdList(),
              syncer::AttachmentServiceProxyForTest::Create())));
    }
  }

  cache()->ProcessSyncChanges(FROM_HERE, initial_image_changes);
  cache()->ProcessSyncChanges(FROM_HERE, initial_tracking_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());

  for (int i = 0; i < kFaviconBatchSize/2; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    cache()->OnFaviconVisited(test_data.page_url, GURL());
    EXPECT_EQ(1U, GetTaskCount());
    OnCustomFaviconDataAvailable(test_data);
    syncer::SyncChangeList changes = processor()->GetAndResetChangeList();

    // Even favicons had image data, so should now receive new tracking data
    // and updated image data (we allow one update after the initial add).
    // Odd favicons had tracking so should now receive new image data and
    // updated tracking data.
    if (i % 2 == 0) {
      ASSERT_EQ(2U, changes.size());
      EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
      EXPECT_TRUE(
          CompareFaviconDataToSpecifics(test_data,
                                        changes[0].sync_data().GetSpecifics()));
      EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[1].change_type());
      EXPECT_EQ(test_data.icon_url.spec(),
                changes[1].sync_data().GetSpecifics().favicon_tracking().
                    favicon_url());
      EXPECT_NE(changes[1].sync_data().GetSpecifics().favicon_tracking().
                    last_visit_time_ms(), 0);
    } else {
      ASSERT_EQ(2U, changes.size());
      EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
      EXPECT_TRUE(
          CompareFaviconDataToSpecifics(test_data,
                                        changes[0].sync_data().GetSpecifics()));
      EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[1].change_type());
      EXPECT_EQ(test_data.icon_url.spec(),
                changes[1].sync_data().GetSpecifics().favicon_tracking().
                    favicon_url());
      EXPECT_NE(changes[1].sync_data().GetSpecifics().favicon_tracking().
                    last_visit_time_ms(), 0);
    }
  }

  EXPECT_EQ(0U, GetTaskCount());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());
}

// Verify that orphaned favicon images don't result in creating invalid
// favicon tracking data.
TEST_F(SyncFaviconCacheTest, PartialAssociationInfo) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    sync_pb::EntitySpecifics image_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    image_specifics.mutable_favicon_image()->clear_favicon_web();
  }

  SetUpInitialSync(initial_image_data, initial_tracking_data);
  syncer::SyncChangeList change_list = processor()->GetAndResetChangeList();
  EXPECT_TRUE(change_list.empty());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());
}

// Tests that we don't choke if a favicon visit node with a null visit time is
// present (see crbug.com/258196) and an update is made.
TEST_F(SyncFaviconCacheTest, NullFaviconVisitTime) {
  EXPECT_EQ(0U, GetFaviconCount());

  syncer::SyncDataList initial_image_data, initial_tracking_data;
  std::vector<int> expected_icons;
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    expected_icons.push_back(i);
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    FillImageSpecifics(BuildFaviconData(i),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(
        syncer::TimeToProtoTime(base::Time()));
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }

  cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                    initial_image_data,
                                    CreateAndPassProcessor(),
                                    CreateAndPassSyncErrorFactory());
  ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
  cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
                                    initial_tracking_data,
                                    CreateAndPassProcessor(),
                                    CreateAndPassSyncErrorFactory());
  ASSERT_EQ(static_cast<size_t>(kFaviconBatchSize),
            processor()->GetAndResetChangeList().size());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());

  // Visit the favicons again.
  EXPECT_EQ(0U, GetTaskCount());
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData test_data = BuildFaviconData(i);
    cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);

    syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    ASSERT_EQ(1U, changes.size());
    // Just verify the favicon url for the tracking specifics and that the
    // timestamp is non-null.
    EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
    EXPECT_EQ(test_data.icon_url.spec(),
              changes[0].sync_data().GetSpecifics().favicon_tracking().
                  favicon_url());
    EXPECT_NE(changes[0].sync_data().GetSpecifics().favicon_tracking().
                  last_visit_time_ms(), 0);
  }
  EXPECT_EQ(0U, GetTaskCount());
  EXPECT_EQ(static_cast<size_t>(kFaviconBatchSize), GetFaviconCount());
}

// If another synced client has a clock skewed towards the future, it's possible
// that favicons added locally will be expired as they are added. Ensure this
// doesn't crash (see crbug.com/306150).
TEST_F(SyncFaviconCacheTest, VisitFaviconClockSkew) {
  EXPECT_EQ(0U, GetFaviconCount());
  const int kClockSkew = 20;  // 20 minutes in the future.

  // Set up sync with kMaxSyncFavicons starting kClockSkew minutes in the
  // future.
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  for (int i = 0; i < kMaxSyncFavicons; ++i) {
    sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    TestFaviconData test_data = BuildFaviconData(i);
    test_data.last_visit_time =
        syncer::TimeToProtoTime(
            base::Time::Now() + base::TimeDelta::FromMinutes(kClockSkew));
    FillImageSpecifics(test_data,
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
    FillTrackingSpecifics(test_data,
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // Visit some new favicons with local time, which will be expired as they
  // are added.
  EXPECT_EQ(0U, GetTaskCount());
  for (int i = 0; i < kClockSkew; ++i) {
    TestFaviconData test_data = BuildFaviconData(i + kMaxSyncFavicons);
    cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
    OnCustomFaviconDataAvailable(test_data);

    // The changes will be an add followed by a delete for both the image and
    // tracking info.
    syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    ASSERT_EQ(changes.size(), 4U);
    ASSERT_EQ(changes[0].change_type(), syncer::SyncChange::ACTION_ADD);
    ASSERT_EQ(changes[0].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
    ASSERT_EQ(changes[1].change_type(), syncer::SyncChange::ACTION_DELETE);
    ASSERT_EQ(changes[1].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
    ASSERT_EQ(changes[2].change_type(), syncer::SyncChange::ACTION_ADD);
    ASSERT_EQ(changes[2].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
    ASSERT_EQ(changes[3].change_type(), syncer::SyncChange::ACTION_DELETE);
    ASSERT_EQ(changes[3].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
  }
  EXPECT_EQ(0U, GetTaskCount());
  EXPECT_EQ(static_cast<size_t>(kMaxSyncFavicons), GetFaviconCount());
}

// Simulate a case where the set of tracking info and image info doesn't match,
// and there is more tracking info than the max. A local update should correctly
// determine whether to update/add an image/tracking entity.
TEST_F(SyncFaviconCacheTest, MixedThreshold) {
  // First go through and add local favicons.
  for (int i = kMaxSyncFavicons; i < kMaxSyncFavicons + 5; ++i) {
    TestFaviconData favicon = BuildFaviconData(i);
    TriggerSyncFaviconReceived(favicon.page_url,
                               favicon.icon_url,
                               favicon.image_16,
                               favicon.last_visit_time);
  }

  syncer::SyncDataList initial_image_data, initial_tracking_data;
  // Then sync with enough favicons such that the tracking info is over the max
  // after merge completes.
  for (int i = 0; i < kMaxSyncFavicons; ++i) {
    sync_pb::EntitySpecifics image_specifics;
    // Push the images forward by 5, to match the unsynced favicons.
    FillImageSpecifics(BuildFaviconData(i + 5),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        image_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));

    sync_pb::EntitySpecifics tracking_specifics;
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
        1,
        tracking_specifics,
        base::Time(),
        syncer::AttachmentIdList(),
        syncer::AttachmentServiceProxyForTest::Create()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);

  // The local unsynced tracking info should be dropped, but not deleted.
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());

  // Because the image and tracking data don't overlap, the total number of
  // favicons is still over the limit.
  EXPECT_EQ(static_cast<size_t>(kMaxSyncFavicons)+5, GetFaviconCount());

  // Trigger a tracking change for one of the favicons whose tracking info
  // was dropped, resulting in a tracking add and expiration of the orphaned
  // images.
  TestFaviconData test_data = BuildFaviconData(kMaxSyncFavicons);
  cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);

  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  // 1 image update, 5 image deletions, 1 tracking deletion.
  ASSERT_EQ(6U, changes.size());
  // Expire image for favicon[kMaxSyncFavicons + 1].
  EXPECT_EQ(changes[0].change_type(), syncer::SyncChange::ACTION_DELETE);
  EXPECT_EQ(changes[0].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
  EXPECT_EQ(kMaxSyncFavicons + 1, GetFaviconId(changes[0]));
  // Expire image for favicon[kMaxSyncFavicons + 2].
  EXPECT_EQ(changes[1].change_type(), syncer::SyncChange::ACTION_DELETE);
  EXPECT_EQ(changes[1].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
  EXPECT_EQ(kMaxSyncFavicons + 2, GetFaviconId(changes[1]));
  // Expire image for favicon[kMaxSyncFavicons + 3].
  EXPECT_EQ(changes[2].change_type(), syncer::SyncChange::ACTION_DELETE);
  EXPECT_EQ(changes[2].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
  EXPECT_EQ(kMaxSyncFavicons + 3, GetFaviconId(changes[2]));
  // Expire image for favicon[kMaxSyncFavicons + 4].
  EXPECT_EQ(changes[3].change_type(), syncer::SyncChange::ACTION_DELETE);
  EXPECT_EQ(changes[3].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
  EXPECT_EQ(kMaxSyncFavicons + 4, GetFaviconId(changes[3]));
  // Update tracking for favicon[kMaxSyncFavicons].
  EXPECT_EQ(changes[4].change_type(), syncer::SyncChange::ACTION_ADD);
  EXPECT_EQ(changes[4].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
  EXPECT_EQ(kMaxSyncFavicons, GetFaviconId(changes[4]));
  // Expire tracking for favicon[0].
  EXPECT_EQ(changes[5].change_type(), syncer::SyncChange::ACTION_DELETE);
  EXPECT_EQ(changes[5].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
  EXPECT_EQ(0, GetFaviconId(changes[5]));
}

}  // namespace sync_sessions
