This source file includes following definitions.
- GetAllSyncData
- contains_guid
- change_for_guid
- GetAndResetChangeList
- set_erroneous
- ProcessSyncChanges
- BuildFaviconData
- FillImageSpecifics
- FillTrackingSpecifics
- CompareFaviconDataToSpecifics
- VerifyChanges
- GetFaviconId
- cache
- processor
- sync_processor_wrapper_
- SetUpInitialSync
- GetFaviconCount
- GetTaskCount
- ExpectFaviconEquals
- VerifyLocalIcons
- VerifyLocalCustomIcons
- CreateAndPassProcessor
- CreateAndPassSyncErrorFactory
- OnCustomFaviconDataAvailable
- TriggerSyncFaviconReceived
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "chrome/browser/sync/glue/favicon_cache.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/history_notifications.h"
#include "content/public/browser/notification_service.h"
#include "sync/api/sync_change_processor_wrapper_for_test.h"
#include "sync/api/sync_error_factory_mock.h"
#include "sync/api/time.h"
#include "sync/protocol/favicon_image_specifics.pb.h"
#include "sync/protocol/favicon_tracking_specifics.pb.h"
#include "sync/protocol/sync.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace browser_sync {
namespace {
const int kFaviconBatchSize = 10;
const int kMaxSyncFavicons = kFaviconBatchSize*2;
class TestChangeProcessor : public syncer::SyncChangeProcessor {
 public:
  TestChangeProcessor();
  virtual ~TestChangeProcessor();
  
  virtual syncer::SyncError ProcessSyncChanges(
      const tracked_objects::Location& from_here,
      const syncer::SyncChangeList& change_list) OVERRIDE;
  virtual 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;
  }
  
  syncer::SyncChangeList GetAndResetChangeList() {
    syncer::SyncChangeList list;
    list.swap(change_list_);
    return list;
  }
  void set_erroneous(bool erroneous) { erroneous_ = erroneous; }
 private:
  
  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();
}
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 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);
  
  
  
  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();
}
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 (tag.find(kPrefix) != 0)
    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;
}
}  
class SyncFaviconCacheTest : public testing::Test {
 public:
  SyncFaviconCacheTest();
  virtual ~SyncFaviconCacheTest() {}
  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);
  scoped_ptr<syncer::SyncChangeProcessor> CreateAndPassProcessor();
  scoped_ptr<syncer::SyncErrorFactory> CreateAndPassSyncErrorFactory();
  FaviconCache* cache() { return &cache_; }
  TestChangeProcessor* processor() { return sync_processor_.get(); }
  
  void OnCustomFaviconDataAvailable(const TestFaviconData& test_data);
  
  
  void TriggerSyncFaviconReceived(const GURL& page_url,
                                  const GURL& icon_url,
                                  const std::string& icon_bytes,
                                  int64 last_visit_time_ms);
 private:
  base::MessageLoopForUI message_loop_;
  FaviconCache cache_;
  
  scoped_ptr<TestChangeProcessor> sync_processor_;
  scoped_ptr<syncer::SyncChangeProcessorWrapperForTest> sync_processor_wrapper_;
};
SyncFaviconCacheTest::SyncFaviconCacheTest()
    : cache_(NULL, 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];
    
    
    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();
}
scoped_ptr<syncer::SyncChangeProcessor>
SyncFaviconCacheTest::CreateAndPassProcessor() {
  return scoped_ptr<syncer::SyncChangeProcessor>(
      new syncer::SyncChangeProcessorWrapperForTest(sync_processor_.get()));
}
scoped_ptr<syncer::SyncErrorFactory> SyncFaviconCacheTest::
    CreateAndPassSyncErrorFactory() {
  return scoped_ptr<syncer::SyncErrorFactory>(
      new syncer::SyncErrorFactoryMock());
}
void SyncFaviconCacheTest::OnCustomFaviconDataAvailable(
    const TestFaviconData& test_data) {
  std::vector<chrome::FaviconBitmapResult> bitmap_results;
  if (!test_data.image_16.empty()) {
    chrome::FaviconBitmapResult 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()) {
    chrome::FaviconBitmapResult 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()) {
    chrome::FaviconBitmapResult 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 last_visit_time_ms) {
  cache()->OnReceivedSyncFavicon(page_url,
                                 icon_url,
                                 icon_bytes,
                                 last_visit_time_ms);
  message_loop_.RunUntilIdle();
}
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()));
  
  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));
  
  
  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));
  
  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());
}
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((unsigned long)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((unsigned long)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());
}
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()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
  }
  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        initial_image_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ((unsigned long)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((unsigned long)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));
}
TEST_F(SyncFaviconCacheTest, SyncMergesImages) {
  
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData favicon = BuildFaviconData(i);
    TriggerSyncFaviconReceived(favicon.page_url,
                               favicon.icon_url,
                               favicon.image_16,
                               i);
  }
  
  
  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()));
    FillTrackingSpecifics(test_data,
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
  }
  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        initial_image_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ((unsigned long)kFaviconBatchSize,
            cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  EXPECT_EQ((unsigned long)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((unsigned long)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));
}
TEST_F(SyncFaviconCacheTest, SyncMergesTracking) {
  
  for (int i = 0; i < kFaviconBatchSize; ++i) {
    TestFaviconData favicon = BuildFaviconData(i);
    TriggerSyncFaviconReceived(favicon.page_url,
                               favicon.icon_url,
                               favicon.image_16,
                               i);
  }
  
  
  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()));
    FillTrackingSpecifics(test_data,
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
  }
  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        initial_image_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ((unsigned long)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((unsigned long)kFaviconBatchSize,
            cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  EXPECT_EQ((unsigned long)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));
}
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()));
    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())));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  cache()->ProcessSyncChanges(FROM_HERE, stale_changes);
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
  ASSERT_EQ((unsigned long)kFaviconBatchSize, changes.size());
  ASSERT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
                            expected_change_types,
                            expected_icons,
                            changes));
}
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())));
    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()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  cache()->ProcessSyncChanges(FROM_HERE, new_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
}
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())));
    initial_image_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           image_specifics,
                                           base::Time()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  cache()->ProcessSyncChanges(FROM_HERE, same_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
}
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()));
    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()));
    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())));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  cache()->ProcessSyncChanges(FROM_HERE, stale_changes);
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
  ASSERT_EQ((unsigned long)kFaviconBatchSize, changes.size());
  ASSERT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
                            expected_change_types,
                            expected_icons,
                            changes));
}
TEST_F(SyncFaviconCacheTest, ReceiveNewTracking) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  syncer::SyncChangeList new_changes;
  std::vector<int> expected_icons;
  
  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()));
    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())));
    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()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  cache()->ProcessSyncChanges(FROM_HERE, new_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
}
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()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
    same_changes.push_back(
        syncer::SyncChange(
             FROM_HERE,
             syncer::SyncChange::ACTION_UPDATE,
             syncer::SyncData::CreateRemoteData(1,
                                                tracking_specifics,
                                                base::Time())));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  cache()->ProcessSyncChanges(FROM_HERE, same_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  ASSERT_TRUE(VerifyLocalIcons(expected_icons));
}
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()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
    tracking_deletions.push_back(
        syncer::SyncChange(
             FROM_HERE,
             syncer::SyncChange::ACTION_DELETE,
             syncer::SyncData::CreateRemoteData(1,
                                                tracking_specifics,
                                                base::Time())));
    image_deletions.push_back(
        syncer::SyncChange(
             FROM_HERE,
             syncer::SyncChange::ACTION_DELETE,
             syncer::SyncData::CreateRemoteData(1,
                                                image_specifics,
                                                base::Time())));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  
  EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
  cache()->ProcessSyncChanges(FROM_HERE, tracking_deletions);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
  
  cache()->ProcessSyncChanges(FROM_HERE, image_deletions);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ(0U, GetFaviconCount());
}
TEST_F(SyncFaviconCacheTest, ExpireOnMergeData) {
  std::vector<int> expected_icons;
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  
  
  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()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
    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));
  
  syncer::SyncMergeResult merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
                                        initial_image_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ((unsigned long)kMaxSyncFavicons * 2,
            GetFaviconCount());  
  EXPECT_EQ((unsigned long)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());
  
  merge_result =
      cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
                                        initial_tracking_data,
                                        CreateAndPassProcessor(),
                                        CreateAndPassSyncErrorFactory());
  EXPECT_EQ((unsigned long)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));
}
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()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::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())));
    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())));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  EXPECT_EQ((unsigned long)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_GT(GetFaviconCount(), (unsigned long)kMaxSyncFavicons);
}
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((unsigned long)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());
    
    
    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((unsigned long)kFaviconBatchSize, GetFaviconCount());
}
TEST_F(SyncFaviconCacheTest, UpdateOnFaviconVisited) {
  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);
    OnCustomFaviconDataAvailable(test_data);
  }
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  
  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());
    
    
    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((unsigned long)kFaviconBatchSize, GetFaviconCount());
}
TEST_F(SyncFaviconCacheTest, ExpireOnFaviconVisited) {
  EXPECT_EQ(0U, GetFaviconCount());
  SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
  std::vector<int> expected_icons;
  
  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();
  
  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((unsigned long)kMaxSyncFavicons, GetFaviconCount());
}
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()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  EXPECT_TRUE(changes.empty());
  history::URLsDeletedDetails deletions;
  deletions.all_history = true;
  EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
  content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_HISTORY_URLS_DELETED,
        content::Source<Profile>(NULL),
        content::Details<history::URLsDeletedDetails>(&deletions));
  EXPECT_EQ(0U, GetFaviconCount());
  changes = processor()->GetAndResetChangeList();
  ASSERT_EQ(changes.size(), (unsigned long)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);
}
TEST_F(SyncFaviconCacheTest, HistorySubsetClear) {
  syncer::SyncDataList initial_image_data, initial_tracking_data;
  std::vector<int> expected_icons;
  std::vector<syncer::SyncChange::SyncChangeType> expected_deletions;
  history::URLsDeletedDetails deletions;
  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);
      deletions.favicon_urls.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()));
    FillTrackingSpecifics(BuildFaviconData(i),
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  EXPECT_TRUE(changes.empty());
  EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
  content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_HISTORY_URLS_DELETED,
        content::Source<Profile>(NULL),
        content::Details<history::URLsDeletedDetails>(&deletions));
  EXPECT_EQ((unsigned long)kFaviconBatchSize/2, GetFaviconCount());
  changes = processor()->GetAndResetChangeList();
  ASSERT_EQ(changes.size(), (unsigned long)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);
}
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((unsigned long)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());
}
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((unsigned long)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((unsigned long)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());
    
    
    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());
}
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);
    
    
    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())));
    } 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())));
    }
  }
  cache()->ProcessSyncChanges(FROM_HERE, initial_image_changes);
  cache()->ProcessSyncChanges(FROM_HERE, initial_tracking_changes);
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  EXPECT_EQ((unsigned long)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();
    
    
    
    
    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((unsigned long)kFaviconBatchSize, GetFaviconCount());
}
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()));
    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((unsigned long)kFaviconBatchSize, GetFaviconCount());
}
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()));
    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()));
  }
  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((unsigned long)kFaviconBatchSize,
            processor()->GetAndResetChangeList().size());
  EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
  
  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());
    
    
    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((unsigned long)kFaviconBatchSize, GetFaviconCount());
}
TEST_F(SyncFaviconCacheTest, VisitFaviconClockSkew) {
  EXPECT_EQ(0U, GetFaviconCount());
  const int kClockSkew = 20;  
  
  
  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()));
    FillTrackingSpecifics(test_data,
                          tracking_specifics.mutable_favicon_tracking());
    initial_tracking_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           tracking_specifics,
                                           base::Time()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  
  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);
    
    
    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((unsigned long)kMaxSyncFavicons, GetFaviconCount());
}
TEST_F(SyncFaviconCacheTest, MixedThreshold) {
  
  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;
  
  
  for (int i = 0; i < kMaxSyncFavicons; ++i) {
    sync_pb::EntitySpecifics image_specifics;
    
    FillImageSpecifics(BuildFaviconData(i + 5),
                       image_specifics.mutable_favicon_image());
    initial_image_data.push_back(
        syncer::SyncData::CreateRemoteData(1,
                                           image_specifics,
                                           base::Time()));
    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()));
  }
  SetUpInitialSync(initial_image_data, initial_tracking_data);
  
  EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
  
  
  EXPECT_EQ((unsigned long)kMaxSyncFavicons + 5, GetFaviconCount());
  
  
  
  TestFaviconData test_data = BuildFaviconData(kMaxSyncFavicons);
  cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
  syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
  
  ASSERT_EQ(6U, changes.size());
  
  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]));
  
  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]));
  
  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]));
  
  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]));
  
  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]));
  
  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]));
}
}