Home | History | Annotate | Download | only in glue
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/sync/glue/favicon_cache.h"
      6 
      7 #include "base/message_loop/message_loop.h"
      8 #include "base/strings/string_number_conversions.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "base/time/time.h"
     11 #include "chrome/browser/chrome_notification_types.h"
     12 #include "chrome/browser/history/history_notifications.h"
     13 #include "content/public/browser/notification_service.h"
     14 #include "sync/api/attachments/attachment_id.h"
     15 #include "sync/api/sync_change_processor_wrapper_for_test.h"
     16 #include "sync/api/sync_error_factory_mock.h"
     17 #include "sync/api/time.h"
     18 #include "sync/internal_api/public/attachments/attachment_service_proxy_for_test.h"
     19 #include "sync/protocol/favicon_image_specifics.pb.h"
     20 #include "sync/protocol/favicon_tracking_specifics.pb.h"
     21 #include "sync/protocol/sync.pb.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 
     24 namespace browser_sync {
     25 
     26 namespace {
     27 
     28 // Total number of favicons to use in sync test batches.
     29 const int kFaviconBatchSize = 10;
     30 
     31 // Maximum number of favicons to sync.
     32 const int kMaxSyncFavicons = kFaviconBatchSize*2;
     33 
     34 // TestChangeProcessor --------------------------------------------------------
     35 
     36 // Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
     37 // back up to Sync.
     38 class TestChangeProcessor : public syncer::SyncChangeProcessor {
     39  public:
     40   TestChangeProcessor();
     41   virtual ~TestChangeProcessor();
     42 
     43   // Store a copy of all the changes passed in so we can examine them later.
     44   virtual syncer::SyncError ProcessSyncChanges(
     45       const tracked_objects::Location& from_here,
     46       const syncer::SyncChangeList& change_list) OVERRIDE;
     47 
     48   virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
     49       OVERRIDE {
     50     return syncer::SyncDataList();
     51   }
     52 
     53   bool contains_guid(const std::string& guid) const {
     54     return change_map_.count(guid) != 0;
     55   }
     56 
     57   syncer::SyncChange change_for_guid(const std::string& guid) const {
     58     DCHECK(contains_guid(guid));
     59     return change_map_.find(guid)->second;
     60   }
     61 
     62   // Returns the last change list received, and resets the internal list.
     63   syncer::SyncChangeList GetAndResetChangeList() {
     64     syncer::SyncChangeList list;
     65     list.swap(change_list_);
     66     return list;
     67   }
     68 
     69   void set_erroneous(bool erroneous) { erroneous_ = erroneous; }
     70 
     71  private:
     72   // Track the changes received in ProcessSyncChanges.
     73   std::map<std::string, syncer::SyncChange> change_map_;
     74   syncer::SyncChangeList change_list_;
     75   bool erroneous_;
     76 
     77   DISALLOW_COPY_AND_ASSIGN(TestChangeProcessor);
     78 };
     79 
     80 TestChangeProcessor::TestChangeProcessor() : erroneous_(false) {
     81 }
     82 
     83 TestChangeProcessor::~TestChangeProcessor() {
     84 }
     85 
     86 syncer::SyncError TestChangeProcessor::ProcessSyncChanges(
     87     const tracked_objects::Location& from_here,
     88     const syncer::SyncChangeList& change_list) {
     89   if (erroneous_) {
     90     return syncer::SyncError(
     91         FROM_HERE,
     92         syncer::SyncError::DATATYPE_ERROR,
     93         "Some error.",
     94         change_list[0].sync_data().GetDataType());
     95   }
     96 
     97   change_list_.insert(change_list_.end(),
     98                       change_list.begin(),
     99                       change_list.end());
    100   change_map_.erase(change_map_.begin(), change_map_.end());
    101   for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
    102       iter != change_list.end(); ++iter) {
    103     change_map_[iter->sync_data().GetTitle()] = *iter;
    104   }
    105   return syncer::SyncError();
    106 }
    107 
    108 // TestFaviconData ------------------------------------------------------------
    109 struct TestFaviconData {
    110   TestFaviconData() : last_visit_time(0), is_bookmarked(false) {}
    111   GURL page_url;
    112   GURL icon_url;
    113   std::string image_16;
    114   std::string image_32;
    115   std::string image_64;
    116   int64 last_visit_time;
    117   bool is_bookmarked;
    118 };
    119 
    120 TestFaviconData BuildFaviconData(int index) {
    121   TestFaviconData data;
    122   data.page_url = GURL(base::StringPrintf("http://bla.com/%.2i.html", index));
    123   data.icon_url = GURL(base::StringPrintf("http://bla.com/%.2i.ico", index));
    124   data.image_16 = base::StringPrintf("16 %i", index);
    125   // TODO(zea): enable this once the cache supports writing them.
    126   // data.image_32 = base::StringPrintf("32 %i", index);
    127   // data.image_64 = base::StringPrintf("64 %i", index);
    128   data.last_visit_time = index;
    129   return data;
    130 }
    131 
    132 void FillImageSpecifics(
    133     const TestFaviconData& test_data,
    134     sync_pb::FaviconImageSpecifics* image_specifics) {
    135   image_specifics->set_favicon_url(test_data.icon_url.spec());
    136   if (!test_data.image_16.empty()) {
    137     image_specifics->mutable_favicon_web()->set_height(16);
    138     image_specifics->mutable_favicon_web()->set_width(16);
    139     image_specifics->mutable_favicon_web()->set_favicon(test_data.image_16);
    140   }
    141   if (!test_data.image_32.empty()) {
    142     image_specifics->mutable_favicon_web_32()->set_height(32);
    143     image_specifics->mutable_favicon_web_32()->set_width(32);
    144     image_specifics->mutable_favicon_web_32()->set_favicon(test_data.image_32);
    145   }
    146   if (!test_data.image_64.empty()) {
    147     image_specifics->mutable_favicon_touch_64()->set_height(64);
    148     image_specifics->mutable_favicon_touch_64()->set_width(64);
    149     image_specifics->mutable_favicon_touch_64()->
    150         set_favicon(test_data.image_64);
    151   }
    152 }
    153 
    154 void FillTrackingSpecifics(
    155     const TestFaviconData& test_data,
    156     sync_pb::FaviconTrackingSpecifics* tracking_specifics) {
    157   tracking_specifics->set_favicon_url(test_data.icon_url.spec());
    158   tracking_specifics->set_last_visit_time_ms(test_data.last_visit_time);
    159   tracking_specifics->set_is_bookmarked(test_data.is_bookmarked);
    160 }
    161 
    162 testing::AssertionResult CompareFaviconDataToSpecifics(
    163     const TestFaviconData& test_data,
    164     const sync_pb::EntitySpecifics& specifics) {
    165   if (specifics.has_favicon_image()) {
    166     sync_pb::FaviconImageSpecifics image_specifics = specifics.favicon_image();
    167     if (image_specifics.favicon_url() != test_data.icon_url.spec())
    168       return testing::AssertionFailure() << "Image icon url doesn't match.";
    169     if (!test_data.image_16.empty()) {
    170       if (image_specifics.favicon_web().favicon() != test_data.image_16 ||
    171           image_specifics.favicon_web().height() != 16 ||
    172           image_specifics.favicon_web().width() != 16) {
    173         return testing::AssertionFailure() << "16p image data doesn't match.";
    174       }
    175     } else if (image_specifics.has_favicon_web()) {
    176       return testing::AssertionFailure() << "Missing 16p favicon.";
    177     }
    178     if (!test_data.image_32.empty()) {
    179       if (image_specifics.favicon_web_32().favicon() != test_data.image_32 ||
    180           image_specifics.favicon_web().height() != 32 ||
    181           image_specifics.favicon_web().width() != 32) {
    182         return testing::AssertionFailure() << "32p image data doesn't match.";
    183       }
    184     } else if (image_specifics.has_favicon_web_32()) {
    185       return testing::AssertionFailure() << "Missing 32p favicon.";
    186     }
    187     if (!test_data.image_64.empty()) {
    188       if (image_specifics.favicon_touch_64().favicon() != test_data.image_64 ||
    189           image_specifics.favicon_web().height() != 64 ||
    190           image_specifics.favicon_web().width() != 64) {
    191         return testing::AssertionFailure() << "64p image data doesn't match.";
    192       }
    193     } else if (image_specifics.has_favicon_touch_64()) {
    194       return testing::AssertionFailure() << "Missing 64p favicon.";
    195     }
    196   } else {
    197     sync_pb::FaviconTrackingSpecifics tracking_specifics =
    198         specifics.favicon_tracking();
    199     if (tracking_specifics.favicon_url() != test_data.icon_url.spec())
    200       return testing::AssertionFailure() << "Tracking icon url doesn't match.";
    201     if (tracking_specifics.last_visit_time_ms() != test_data.last_visit_time)
    202       return testing::AssertionFailure() << "Visit time doesn't match.";
    203     if (tracking_specifics.is_bookmarked() != test_data.is_bookmarked)
    204       return testing::AssertionFailure() << "Bookmark status doens't match.";
    205   }
    206   return testing::AssertionSuccess();
    207 }
    208 
    209 testing::AssertionResult VerifyChanges(
    210     syncer::ModelType expected_model_type,
    211     const std::vector<syncer::SyncChange::SyncChangeType>&
    212         expected_change_types,
    213     const std::vector<int>& expected_icons,
    214     const syncer::SyncChangeList& change_list) {
    215   DCHECK_EQ(expected_change_types.size(), expected_icons.size());
    216   if (change_list.size() != expected_icons.size())
    217     return testing::AssertionFailure() << "Change list size doesn't match.";
    218   for (size_t i = 0; i < expected_icons.size(); ++i) {
    219     TestFaviconData data = BuildFaviconData(expected_icons[i]);
    220     if (change_list[i].sync_data().GetDataType() != expected_model_type)
    221       return testing::AssertionFailure() << "Change datatype doesn't match.";
    222     if (change_list[i].change_type() != expected_change_types[i])
    223       return testing::AssertionFailure() << "Change type doesn't match.";
    224     if (change_list[i].change_type() == syncer::SyncChange::ACTION_DELETE) {
    225       if (syncer::SyncDataLocal(change_list[i].sync_data()).GetTag() !=
    226           data.icon_url.spec())
    227         return testing::AssertionFailure() << "Deletion url does not match.";
    228     } else {
    229       testing::AssertionResult compare_result =
    230           CompareFaviconDataToSpecifics(
    231               data,
    232               change_list[i].sync_data().GetSpecifics());
    233       if (!compare_result)
    234         return compare_result;
    235     }
    236   }
    237   return testing::AssertionSuccess();
    238 }
    239 
    240 // Helper to extract the favicon id embedded in the tag of a sync
    241 // change.
    242 int GetFaviconId(const syncer::SyncChange change) {
    243   std::string tag = syncer::SyncDataLocal(change.sync_data()).GetTag();
    244   const std::string kPrefix = "http://bla.com/";
    245   const std::string kSuffix = ".ico";
    246   if (tag.find(kPrefix) != 0)
    247     return -1;
    248   std::string temp = tag.substr(kPrefix.length());
    249   if (temp.rfind(kSuffix) <= 0)
    250     return -1;
    251   temp = temp.substr(0, temp.rfind(kSuffix));
    252   int result = -1;
    253   if (!base::StringToInt(temp, &result))
    254     return -1;
    255   return result;
    256 }
    257 
    258 }  // namespace
    259 
    260 class SyncFaviconCacheTest : public testing::Test {
    261  public:
    262   SyncFaviconCacheTest();
    263   virtual ~SyncFaviconCacheTest() {}
    264 
    265   void SetUpInitialSync(const syncer::SyncDataList& initial_image_data,
    266                         const syncer::SyncDataList& initial_tracking_data);
    267 
    268   size_t GetFaviconCount() const;
    269   size_t GetTaskCount() const;
    270 
    271   testing::AssertionResult ExpectFaviconEquals(
    272         const std::string& page_url,
    273         const std::string& bytes) const;
    274   testing::AssertionResult VerifyLocalIcons(
    275       const std::vector<int>& expected_icons);
    276   testing::AssertionResult VerifyLocalCustomIcons(
    277       const std::vector<TestFaviconData>& expected_icons);
    278 
    279   scoped_ptr<syncer::SyncChangeProcessor> CreateAndPassProcessor();
    280   scoped_ptr<syncer::SyncErrorFactory> CreateAndPassSyncErrorFactory();
    281 
    282   FaviconCache* cache() { return &cache_; }
    283   TestChangeProcessor* processor() { return sync_processor_.get(); }
    284 
    285   // Finish an outstanding favicon load for the icon described in |test_data|.
    286   void OnCustomFaviconDataAvailable(const TestFaviconData& test_data);
    287 
    288   // Helper method to run the message loop after invoking
    289   // OnReceivedSyncFavicon, which posts an internal task.
    290   void TriggerSyncFaviconReceived(const GURL& page_url,
    291                                   const GURL& icon_url,
    292                                   const std::string& icon_bytes,
    293                                   int64 last_visit_time_ms);
    294 
    295  private:
    296   base::MessageLoopForUI message_loop_;
    297   FaviconCache cache_;
    298 
    299   // Our dummy ChangeProcessor used to inspect changes pushed to Sync.
    300   scoped_ptr<TestChangeProcessor> sync_processor_;
    301   scoped_ptr<syncer::SyncChangeProcessorWrapperForTest> sync_processor_wrapper_;
    302 };
    303 
    304 SyncFaviconCacheTest::SyncFaviconCacheTest()
    305     : cache_(NULL, kMaxSyncFavicons),
    306       sync_processor_(new TestChangeProcessor),
    307       sync_processor_wrapper_(new syncer::SyncChangeProcessorWrapperForTest(
    308           sync_processor_.get())) {}
    309 
    310 void SyncFaviconCacheTest::SetUpInitialSync(
    311     const syncer::SyncDataList& initial_image_data,
    312     const syncer::SyncDataList& initial_tracking_data) {
    313   cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    314                                     initial_image_data,
    315                                     CreateAndPassProcessor(),
    316                                     CreateAndPassSyncErrorFactory());
    317   ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
    318   cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    319                                     initial_tracking_data,
    320                                     CreateAndPassProcessor(),
    321                                     CreateAndPassSyncErrorFactory());
    322   ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
    323 }
    324 
    325 size_t SyncFaviconCacheTest::GetFaviconCount() const {
    326   return cache_.NumFaviconsForTest();
    327 }
    328 
    329 size_t SyncFaviconCacheTest::GetTaskCount() const {
    330   return cache_.NumTasksForTest();
    331 }
    332 
    333 testing::AssertionResult SyncFaviconCacheTest::ExpectFaviconEquals(
    334     const std::string& page_url,
    335     const std::string& bytes) const {
    336   GURL gurl(page_url);
    337   scoped_refptr<base::RefCountedMemory> favicon;
    338   if (!cache_.GetSyncedFaviconForPageURL(gurl, &favicon))
    339     return testing::AssertionFailure() << "Favicon is missing.";
    340   if (favicon->size() != bytes.size())
    341     return testing::AssertionFailure() << "Favicon sizes don't match.";
    342   for (size_t i = 0; i < favicon->size(); ++i) {
    343     if (bytes[i] != *(favicon->front() + i))
    344       return testing::AssertionFailure() << "Favicon data doesn't match.";
    345   }
    346   return testing::AssertionSuccess();
    347 }
    348 
    349 testing::AssertionResult SyncFaviconCacheTest::VerifyLocalIcons(
    350     const std::vector<int>& expected_icons) {
    351   std::vector<TestFaviconData> expected_custom_icons;
    352   for (size_t i = 0; i < expected_icons.size(); ++i) {
    353     expected_custom_icons.push_back(BuildFaviconData(expected_icons[i]));
    354   }
    355   return VerifyLocalCustomIcons(expected_custom_icons);
    356 }
    357 
    358 
    359 testing::AssertionResult SyncFaviconCacheTest::VerifyLocalCustomIcons(
    360     const std::vector<TestFaviconData>& expected_custom_icons) {
    361   syncer::SyncDataList image_data_list =
    362       cache()->GetAllSyncData(syncer::FAVICON_IMAGES);
    363   syncer::SyncDataList tracking_data_list =
    364       cache()->GetAllSyncData(syncer::FAVICON_TRACKING);
    365   if (expected_custom_icons.size() > image_data_list.size() ||
    366       expected_custom_icons.size() > tracking_data_list.size())
    367     return testing::AssertionFailure() << "Number of icons doesn't match.";
    368   for (size_t i = 0; i < expected_custom_icons.size(); ++i) {
    369     const TestFaviconData& test_data = expected_custom_icons[i];
    370     // Find the test data in the data lists. Assume that both lists have the
    371     // same ordering, which may not match the |expected_custom_icons| ordering.
    372     bool found_match = false;
    373     for (size_t j = 0; j < image_data_list.size(); ++j) {
    374       if (image_data_list[j].GetTitle() != test_data.icon_url.spec())
    375         continue;
    376       found_match = true;
    377       const sync_pb::FaviconImageSpecifics& image_specifics =
    378           image_data_list[j].GetSpecifics().favicon_image();
    379       sync_pb::FaviconImageSpecifics expected_image_specifics;
    380       FillImageSpecifics(test_data, &expected_image_specifics);
    381       if (image_specifics.SerializeAsString() !=
    382           expected_image_specifics.SerializeAsString()) {
    383         return testing::AssertionFailure() << "Image data doesn't match.";
    384       }
    385       const sync_pb::FaviconTrackingSpecifics& tracking_specifics =
    386           tracking_data_list[j].GetSpecifics().favicon_tracking();
    387       sync_pb::FaviconTrackingSpecifics expected_tracking_specifics;
    388       FillTrackingSpecifics(test_data, &expected_tracking_specifics);
    389       if (tracking_specifics.SerializeAsString() !=
    390           expected_tracking_specifics.SerializeAsString()) {
    391         return testing::AssertionFailure() << "Tracking data doesn't match.";
    392       }
    393     }
    394     if (!found_match)
    395       return testing::AssertionFailure() << "Could not find favicon.";
    396   }
    397   return testing::AssertionSuccess();
    398 }
    399 
    400 scoped_ptr<syncer::SyncChangeProcessor>
    401 SyncFaviconCacheTest::CreateAndPassProcessor() {
    402   return scoped_ptr<syncer::SyncChangeProcessor>(
    403       new syncer::SyncChangeProcessorWrapperForTest(sync_processor_.get()));
    404 }
    405 
    406 scoped_ptr<syncer::SyncErrorFactory> SyncFaviconCacheTest::
    407     CreateAndPassSyncErrorFactory() {
    408   return scoped_ptr<syncer::SyncErrorFactory>(
    409       new syncer::SyncErrorFactoryMock());
    410 }
    411 
    412 void SyncFaviconCacheTest::OnCustomFaviconDataAvailable(
    413     const TestFaviconData& test_data) {
    414   std::vector<favicon_base::FaviconRawBitmapResult> bitmap_results;
    415   if (!test_data.image_16.empty()) {
    416     favicon_base::FaviconRawBitmapResult bitmap_result;
    417     bitmap_result.icon_url = test_data.icon_url;
    418     bitmap_result.pixel_size.set_width(16);
    419     bitmap_result.pixel_size.set_height(16);
    420     base::RefCountedString* temp_string = new base::RefCountedString();
    421     temp_string->data() = test_data.image_16;
    422     bitmap_result.bitmap_data = temp_string;
    423     bitmap_results.push_back(bitmap_result);
    424   }
    425   if (!test_data.image_32.empty()) {
    426     favicon_base::FaviconRawBitmapResult bitmap_result;
    427     bitmap_result.icon_url = test_data.icon_url;
    428     bitmap_result.pixel_size.set_width(32);
    429     bitmap_result.pixel_size.set_height(32);
    430     base::RefCountedString* temp_string = new base::RefCountedString();
    431     temp_string->data() = test_data.image_32;
    432     bitmap_result.bitmap_data = temp_string;
    433     bitmap_results.push_back(bitmap_result);
    434   }
    435   if (!test_data.image_64.empty()) {
    436     favicon_base::FaviconRawBitmapResult bitmap_result;
    437     bitmap_result.icon_url = test_data.icon_url;
    438     bitmap_result.pixel_size.set_width(64);
    439     bitmap_result.pixel_size.set_height(64);
    440     base::RefCountedString* temp_string = new base::RefCountedString();
    441     temp_string->data() = test_data.image_64;
    442     bitmap_result.bitmap_data = temp_string;
    443     bitmap_results.push_back(bitmap_result);
    444   }
    445   cache()->OnFaviconDataAvailable(test_data.page_url, bitmap_results);
    446 }
    447 
    448 void SyncFaviconCacheTest::TriggerSyncFaviconReceived(
    449     const GURL& page_url,
    450     const GURL& icon_url,
    451     const std::string& icon_bytes,
    452     int64 last_visit_time_ms) {
    453   cache()->OnReceivedSyncFavicon(page_url,
    454                                  icon_url,
    455                                  icon_bytes,
    456                                  last_visit_time_ms);
    457   message_loop_.RunUntilIdle();
    458 }
    459 
    460 // A freshly constructed cache should be empty.
    461 TEST_F(SyncFaviconCacheTest, Empty) {
    462   EXPECT_EQ(0U, GetFaviconCount());
    463 }
    464 
    465 TEST_F(SyncFaviconCacheTest, ReceiveSyncFavicon) {
    466   std::string page_url = "http://www.google.com";
    467   std::string fav_url = "http://www.google.com/favicon.ico";
    468   std::string bytes = "bytes";
    469   EXPECT_EQ(0U, GetFaviconCount());
    470   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
    471   EXPECT_EQ(1U, GetFaviconCount());
    472   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    473 }
    474 
    475 TEST_F(SyncFaviconCacheTest, ReceiveEmptySyncFavicon) {
    476   std::string page_url = "http://www.google.com";
    477   std::string fav_url = "http://www.google.com/favicon.ico";
    478   std::string bytes = "bytes";
    479   EXPECT_EQ(0U, GetFaviconCount());
    480   TriggerSyncFaviconReceived(GURL(page_url),
    481                              GURL(fav_url),
    482                              std::string(),
    483                              0);
    484   EXPECT_EQ(0U, GetFaviconCount());
    485   EXPECT_FALSE(ExpectFaviconEquals(page_url, std::string()));
    486 
    487   // Then receive the actual favicon.
    488   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
    489   EXPECT_EQ(1U, GetFaviconCount());
    490   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    491 }
    492 
    493 TEST_F(SyncFaviconCacheTest, ReceiveUpdatedSyncFavicon) {
    494   std::string page_url = "http://www.google.com";
    495   std::string fav_url = "http://www.google.com/favicon.ico";
    496   std::string bytes = "bytes";
    497   std::string bytes2 = "bytes2";
    498   EXPECT_EQ(0U, GetFaviconCount());
    499   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
    500   EXPECT_EQ(1U, GetFaviconCount());
    501   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    502 
    503   // The cache should not update existing favicons from tab sync favicons
    504   // (which can be reassociated several times).
    505   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes2, 0);
    506   EXPECT_EQ(1U, GetFaviconCount());
    507   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    508   EXPECT_FALSE(ExpectFaviconEquals(page_url, bytes2));
    509 }
    510 
    511 TEST_F(SyncFaviconCacheTest, MultipleMappings) {
    512   std::string page_url = "http://www.google.com";
    513   std::string page2_url = "http://bla.google.com";
    514   std::string fav_url = "http://www.google.com/favicon.ico";
    515   std::string bytes = "bytes";
    516   EXPECT_EQ(0U, GetFaviconCount());
    517   TriggerSyncFaviconReceived(GURL(page_url), GURL(fav_url), bytes, 0);
    518   EXPECT_EQ(1U, GetFaviconCount());
    519   EXPECT_TRUE(ExpectFaviconEquals(page_url, bytes));
    520 
    521   // Map another page to the same favicon. They should share the same data.
    522   TriggerSyncFaviconReceived(GURL(page2_url), GURL(fav_url), bytes, 0);
    523   EXPECT_EQ(1U, GetFaviconCount());
    524   EXPECT_TRUE(ExpectFaviconEquals(page2_url, bytes));
    525 }
    526 
    527 TEST_F(SyncFaviconCacheTest, SyncEmpty) {
    528   syncer::SyncMergeResult merge_result =
    529       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    530                                         syncer::SyncDataList(),
    531                                         CreateAndPassProcessor(),
    532                                         CreateAndPassSyncErrorFactory());
    533 
    534   EXPECT_EQ(0U, cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    535   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    536   EXPECT_EQ(0, merge_result.num_items_added());
    537   EXPECT_EQ(0, merge_result.num_items_modified());
    538   EXPECT_EQ(0, merge_result.num_items_deleted());
    539   EXPECT_EQ(0, merge_result.num_items_before_association());
    540   EXPECT_EQ(0, merge_result.num_items_after_association());
    541 
    542   merge_result =
    543       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    544                                         syncer::SyncDataList(),
    545                                         CreateAndPassProcessor(),
    546                                         CreateAndPassSyncErrorFactory());
    547 
    548   EXPECT_EQ(0U, cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    549   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    550   EXPECT_EQ(0, merge_result.num_items_added());
    551   EXPECT_EQ(0, merge_result.num_items_modified());
    552   EXPECT_EQ(0, merge_result.num_items_deleted());
    553   EXPECT_EQ(0, merge_result.num_items_before_association());
    554   EXPECT_EQ(0, merge_result.num_items_after_association());
    555 }
    556 
    557 // Setting up sync with existing local favicons should push those favicons into
    558 // sync.
    559 TEST_F(SyncFaviconCacheTest, SyncExistingLocal) {
    560   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    561   std::vector<int> expected_icons;
    562   for (int i = 0; i < kFaviconBatchSize; ++i) {
    563     TestFaviconData favicon = BuildFaviconData(i);
    564     TriggerSyncFaviconReceived(favicon.page_url,
    565                                favicon.icon_url,
    566                                favicon.image_16,
    567                                i);
    568     expected_change_types.push_back(syncer::SyncChange::ACTION_ADD);
    569     expected_icons.push_back(i);
    570   }
    571 
    572   syncer::SyncMergeResult merge_result =
    573       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    574                                         syncer::SyncDataList(),
    575                                         CreateAndPassProcessor(),
    576                                         CreateAndPassSyncErrorFactory());
    577   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    578             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    579   syncer::SyncChangeList change_list = processor()->GetAndResetChangeList();
    580   EXPECT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
    581                             expected_change_types,
    582                             expected_icons,
    583                             change_list));
    584   EXPECT_EQ(0, merge_result.num_items_added());
    585   EXPECT_EQ(0, merge_result.num_items_modified());
    586   EXPECT_EQ(0, merge_result.num_items_deleted());
    587   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    588   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    589 
    590   merge_result =
    591       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    592                                         syncer::SyncDataList(),
    593                                         CreateAndPassProcessor(),
    594                                         CreateAndPassSyncErrorFactory());
    595   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    596             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    597   change_list = processor()->GetAndResetChangeList();
    598   EXPECT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
    599                             expected_change_types,
    600                             expected_icons,
    601                             change_list));
    602   EXPECT_EQ(0, merge_result.num_items_added());
    603   EXPECT_EQ(0, merge_result.num_items_modified());
    604   EXPECT_EQ(0, merge_result.num_items_deleted());
    605   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    606   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    607 }
    608 
    609 // Setting up sync with existing sync data should load that data into the local
    610 // cache.
    611 TEST_F(SyncFaviconCacheTest, SyncExistingRemote) {
    612   syncer::SyncDataList initial_image_data, initial_tracking_data;
    613   std::vector<int> expected_icons;
    614   for (int i = 0; i < kFaviconBatchSize; ++i) {
    615     expected_icons.push_back(i);
    616     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    617     FillImageSpecifics(BuildFaviconData(i),
    618                        image_specifics.mutable_favicon_image());
    619     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
    620         1,
    621         image_specifics,
    622         base::Time(),
    623         syncer::AttachmentIdList(),
    624         syncer::AttachmentServiceProxyForTest::Create()));
    625     FillTrackingSpecifics(BuildFaviconData(i),
    626                           tracking_specifics.mutable_favicon_tracking());
    627     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
    628         1,
    629         tracking_specifics,
    630         base::Time(),
    631         syncer::AttachmentIdList(),
    632         syncer::AttachmentServiceProxyForTest::Create()));
    633   }
    634 
    635   syncer::SyncMergeResult merge_result =
    636       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    637                                         initial_image_data,
    638                                         CreateAndPassProcessor(),
    639                                         CreateAndPassSyncErrorFactory());
    640   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    641             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    642   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    643   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_added());
    644   EXPECT_EQ(0, merge_result.num_items_modified());
    645   EXPECT_EQ(0, merge_result.num_items_deleted());
    646   EXPECT_EQ(0, merge_result.num_items_before_association());
    647   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    648 
    649   merge_result =
    650       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    651                                         initial_tracking_data,
    652                                         CreateAndPassProcessor(),
    653                                         CreateAndPassSyncErrorFactory());
    654   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    655             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    656   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    657   EXPECT_EQ(0, merge_result.num_items_added());
    658   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    659   EXPECT_EQ(0, merge_result.num_items_deleted());
    660   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    661   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    662 
    663   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    664 }
    665 
    666 // Setting up sync with local data and sync data should merge the two image
    667 // sets, with remote data having priority in case both exist.
    668 TEST_F(SyncFaviconCacheTest, SyncMergesImages) {
    669   // First go through and add local 16p favicons.
    670   for (int i = 0; i < kFaviconBatchSize; ++i) {
    671     TestFaviconData favicon = BuildFaviconData(i);
    672     TriggerSyncFaviconReceived(favicon.page_url,
    673                                favicon.icon_url,
    674                                favicon.image_16,
    675                                i);
    676   }
    677 
    678   // Then go through and create the initial sync data, which does not have 16p
    679   // favicons for the first half, and has custom 16p favicons for the second.
    680   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    681   std::vector<int> expected_icons;
    682   std::vector<TestFaviconData> expected_data;
    683   syncer::SyncDataList initial_image_data, initial_tracking_data;
    684   for (int i = 0; i < kFaviconBatchSize; ++i) {
    685     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    686     TestFaviconData test_data = BuildFaviconData(i);
    687     if (i < kFaviconBatchSize/2) {
    688       test_data.image_16 = std::string();
    689       expected_icons.push_back(i);
    690       expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    691     } else {
    692       test_data.image_16 += "custom";
    693       expected_data.push_back(test_data);
    694     }
    695     FillImageSpecifics(test_data,
    696                        image_specifics.mutable_favicon_image());
    697 
    698     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
    699         1,
    700         image_specifics,
    701         base::Time(),
    702         syncer::AttachmentIdList(),
    703         syncer::AttachmentServiceProxyForTest::Create()));
    704     FillTrackingSpecifics(test_data,
    705                           tracking_specifics.mutable_favicon_tracking());
    706     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
    707         1,
    708         tracking_specifics,
    709         base::Time(),
    710         syncer::AttachmentIdList(),
    711         syncer::AttachmentServiceProxyForTest::Create()));
    712   }
    713 
    714   syncer::SyncMergeResult merge_result =
    715       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    716                                         initial_image_data,
    717                                         CreateAndPassProcessor(),
    718                                         CreateAndPassSyncErrorFactory());
    719   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    720             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    721   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    722   EXPECT_EQ((unsigned long)kFaviconBatchSize/2, changes.size());
    723   EXPECT_EQ(0, merge_result.num_items_added());
    724   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    725   EXPECT_EQ(0, merge_result.num_items_deleted());
    726   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    727   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    728 
    729   merge_result =
    730       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    731                                         initial_tracking_data,
    732                                         CreateAndPassProcessor(),
    733                                         CreateAndPassSyncErrorFactory());
    734   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    735             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    736   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    737   EXPECT_EQ(0, merge_result.num_items_added());
    738   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    739   EXPECT_EQ(0, merge_result.num_items_deleted());
    740   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    741   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    742 
    743   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    744   ASSERT_TRUE(VerifyLocalCustomIcons(expected_data));
    745   ASSERT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
    746                             expected_change_types,
    747                             expected_icons,
    748                             changes));
    749 }
    750 
    751 // Setting up sync with local data and sync data should merge the two tracking
    752 // sets, such that the visit time is the most recent.
    753 TEST_F(SyncFaviconCacheTest, SyncMergesTracking) {
    754   // First go through and add local 16p favicons.
    755   for (int i = 0; i < kFaviconBatchSize; ++i) {
    756     TestFaviconData favicon = BuildFaviconData(i);
    757     TriggerSyncFaviconReceived(favicon.page_url,
    758                                favicon.icon_url,
    759                                favicon.image_16,
    760                                i);
    761   }
    762 
    763   // Then go through and create the initial sync data, which for the first half
    764   // the local has a newer visit, and for the second the remote does.
    765   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    766   std::vector<int> expected_icons;
    767   std::vector<TestFaviconData> expected_data;
    768   syncer::SyncDataList initial_image_data, initial_tracking_data;
    769   for (int i = 0; i < kFaviconBatchSize; ++i) {
    770     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    771     TestFaviconData test_data = BuildFaviconData(i);
    772     if (i < kFaviconBatchSize/2) {
    773       test_data.last_visit_time = i-1;
    774       expected_icons.push_back(i);
    775       expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    776     } else {
    777       test_data.last_visit_time = i+1;
    778       expected_data.push_back(test_data);
    779     }
    780     FillImageSpecifics(test_data,
    781                        image_specifics.mutable_favicon_image());
    782 
    783     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
    784         1,
    785         image_specifics,
    786         base::Time(),
    787         syncer::AttachmentIdList(),
    788         syncer::AttachmentServiceProxyForTest::Create()));
    789     FillTrackingSpecifics(test_data,
    790                           tracking_specifics.mutable_favicon_tracking());
    791     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
    792         1,
    793         tracking_specifics,
    794         base::Time(),
    795         syncer::AttachmentIdList(),
    796         syncer::AttachmentServiceProxyForTest::Create()));
    797   }
    798 
    799   syncer::SyncMergeResult merge_result =
    800       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
    801                                         initial_image_data,
    802                                         CreateAndPassProcessor(),
    803                                         CreateAndPassSyncErrorFactory());
    804   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    805             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
    806   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    807   EXPECT_EQ(0, merge_result.num_items_added());
    808   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    809   EXPECT_EQ(0, merge_result.num_items_deleted());
    810   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    811   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    812 
    813   merge_result =
    814       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
    815                                         initial_tracking_data,
    816                                         CreateAndPassProcessor(),
    817                                         CreateAndPassSyncErrorFactory());
    818   EXPECT_EQ((unsigned long)kFaviconBatchSize,
    819             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
    820   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    821   EXPECT_EQ((unsigned long)kFaviconBatchSize/2, changes.size());
    822   EXPECT_EQ(0, merge_result.num_items_added());
    823   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_modified());
    824   EXPECT_EQ(0, merge_result.num_items_deleted());
    825   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_before_association());
    826   EXPECT_EQ(kFaviconBatchSize, merge_result.num_items_after_association());
    827 
    828   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    829   ASSERT_TRUE(VerifyLocalCustomIcons(expected_data));
    830   ASSERT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
    831                             expected_change_types,
    832                             expected_icons,
    833                             changes));
    834 }
    835 
    836 // Receiving old icons (missing image data) should result in pushing the new
    837 // merged icons back to the remote syncer.
    838 TEST_F(SyncFaviconCacheTest, ReceiveStaleImages) {
    839   syncer::SyncDataList initial_image_data, initial_tracking_data;
    840   syncer::SyncChangeList stale_changes;
    841   std::vector<int> expected_icons;
    842   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    843   for (int i = 0; i < kFaviconBatchSize; ++i) {
    844     expected_icons.push_back(i);
    845     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    846     FillImageSpecifics(BuildFaviconData(i),
    847                        image_specifics.mutable_favicon_image());
    848     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
    849         1,
    850         image_specifics,
    851         base::Time(),
    852         syncer::AttachmentIdList(),
    853         syncer::AttachmentServiceProxyForTest::Create()));
    854     expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
    855     image_specifics.mutable_favicon_image()->clear_favicon_web();
    856     stale_changes.push_back(syncer::SyncChange(
    857         FROM_HERE,
    858         syncer::SyncChange::ACTION_UPDATE,
    859         syncer::SyncData::CreateRemoteData(
    860             1,
    861             image_specifics,
    862             base::Time(),
    863             syncer::AttachmentIdList(),
    864             syncer::AttachmentServiceProxyForTest::Create())));
    865     FillTrackingSpecifics(BuildFaviconData(i),
    866                           tracking_specifics.mutable_favicon_tracking());
    867     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
    868         1,
    869         tracking_specifics,
    870         base::Time(),
    871         syncer::AttachmentIdList(),
    872         syncer::AttachmentServiceProxyForTest::Create()));
    873   }
    874 
    875   SetUpInitialSync(initial_image_data, initial_tracking_data);
    876 
    877   // Now receive the same icons as an update, but with missing image data.
    878   cache()->ProcessSyncChanges(FROM_HERE, stale_changes);
    879   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
    880   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    881   ASSERT_EQ((unsigned long)kFaviconBatchSize, changes.size());
    882   ASSERT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES,
    883                             expected_change_types,
    884                             expected_icons,
    885                             changes));
    886 }
    887 
    888 // New icons should be added locally without pushing anything back to the
    889 // remote syncer.
    890 TEST_F(SyncFaviconCacheTest, ReceiveNewImages) {
    891   syncer::SyncDataList initial_image_data, initial_tracking_data;
    892   syncer::SyncChangeList new_changes;
    893   std::vector<int> expected_icons;
    894   for (int i = 0; i < kFaviconBatchSize; ++i) {
    895     expected_icons.push_back(i);
    896     TestFaviconData test_data = BuildFaviconData(i);
    897     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    898     FillImageSpecifics(test_data,
    899                        image_specifics.mutable_favicon_image());
    900     new_changes.push_back(syncer::SyncChange(
    901         FROM_HERE,
    902         syncer::SyncChange::ACTION_UPDATE,
    903         syncer::SyncData::CreateRemoteData(
    904             1,
    905             image_specifics,
    906             base::Time(),
    907             syncer::AttachmentIdList(),
    908             syncer::AttachmentServiceProxyForTest::Create())));
    909     image_specifics.mutable_favicon_image()
    910         ->mutable_favicon_web()
    911         ->mutable_favicon()
    912         ->append("old");
    913     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
    914         1,
    915         image_specifics,
    916         base::Time(),
    917         syncer::AttachmentIdList(),
    918         syncer::AttachmentServiceProxyForTest::Create()));
    919     FillTrackingSpecifics(BuildFaviconData(i),
    920                           tracking_specifics.mutable_favicon_tracking());
    921     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
    922         1,
    923         tracking_specifics,
    924         base::Time(),
    925         syncer::AttachmentIdList(),
    926         syncer::AttachmentServiceProxyForTest::Create()));
    927   }
    928 
    929   SetUpInitialSync(initial_image_data, initial_tracking_data);
    930 
    931   // Now receive the new icons as an update.
    932   cache()->ProcessSyncChanges(FROM_HERE, new_changes);
    933   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    934   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    935 }
    936 
    937 // Recieving the same icons as the local data should have no effect.
    938 TEST_F(SyncFaviconCacheTest, ReceiveSameImages) {
    939   syncer::SyncDataList initial_image_data, initial_tracking_data;
    940   syncer::SyncChangeList same_changes;
    941   std::vector<int> expected_icons;
    942   for (int i = 0; i < kFaviconBatchSize; ++i) {
    943     expected_icons.push_back(i);
    944     TestFaviconData test_data = BuildFaviconData(i);
    945     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    946     FillImageSpecifics(test_data,
    947                        image_specifics.mutable_favicon_image());
    948     same_changes.push_back(syncer::SyncChange(
    949         FROM_HERE,
    950         syncer::SyncChange::ACTION_UPDATE,
    951         syncer::SyncData::CreateRemoteData(
    952             1,
    953             image_specifics,
    954             base::Time(),
    955             syncer::AttachmentIdList(),
    956             syncer::AttachmentServiceProxyForTest::Create())));
    957     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
    958         1,
    959         image_specifics,
    960         base::Time(),
    961         syncer::AttachmentIdList(),
    962         syncer::AttachmentServiceProxyForTest::Create()));
    963     FillTrackingSpecifics(BuildFaviconData(i),
    964                           tracking_specifics.mutable_favicon_tracking());
    965     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
    966         1,
    967         tracking_specifics,
    968         base::Time(),
    969         syncer::AttachmentIdList(),
    970         syncer::AttachmentServiceProxyForTest::Create()));
    971   }
    972 
    973   SetUpInitialSync(initial_image_data, initial_tracking_data);
    974 
    975   // Now receive the new icons as an update.
    976   cache()->ProcessSyncChanges(FROM_HERE, same_changes);
    977   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
    978   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
    979 }
    980 
    981 // Receiving stale tracking (old visit times) should result in pushing back
    982 // the newer visit times to the remote syncer.
    983 TEST_F(SyncFaviconCacheTest, ReceiveStaleTracking) {
    984   syncer::SyncDataList initial_image_data, initial_tracking_data;
    985   syncer::SyncChangeList stale_changes;
    986   std::vector<int> expected_icons;
    987   std::vector<syncer::SyncChange::SyncChangeType> expected_change_types;
    988   for (int i = 0; i < kFaviconBatchSize; ++i) {
    989     expected_icons.push_back(i);
    990     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
    991     FillImageSpecifics(BuildFaviconData(i),
    992                        image_specifics.mutable_favicon_image());
    993     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
    994         1,
    995         image_specifics,
    996         base::Time(),
    997         syncer::AttachmentIdList(),
    998         syncer::AttachmentServiceProxyForTest::Create()));
    999     expected_change_types.push_back(syncer::SyncChange::ACTION_UPDATE);
   1000     FillTrackingSpecifics(BuildFaviconData(i),
   1001                           tracking_specifics.mutable_favicon_tracking());
   1002     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1003         1,
   1004         tracking_specifics,
   1005         base::Time(),
   1006         syncer::AttachmentIdList(),
   1007         syncer::AttachmentServiceProxyForTest::Create()));
   1008     tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(-1);
   1009     stale_changes.push_back(syncer::SyncChange(
   1010         FROM_HERE,
   1011         syncer::SyncChange::ACTION_UPDATE,
   1012         syncer::SyncData::CreateRemoteData(
   1013             1,
   1014             tracking_specifics,
   1015             base::Time(),
   1016             syncer::AttachmentIdList(),
   1017             syncer::AttachmentServiceProxyForTest::Create())));
   1018   }
   1019 
   1020   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1021 
   1022   // Now receive the same icons as an update, but with missing image data.
   1023   cache()->ProcessSyncChanges(FROM_HERE, stale_changes);
   1024   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1025   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
   1026   ASSERT_EQ((unsigned long)kFaviconBatchSize, changes.size());
   1027   ASSERT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING,
   1028                             expected_change_types,
   1029                             expected_icons,
   1030                             changes));
   1031 }
   1032 
   1033 // New tracking information should be added locally without pushing anything
   1034 // back to the remote syncer.
   1035 TEST_F(SyncFaviconCacheTest, ReceiveNewTracking) {
   1036   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1037   syncer::SyncChangeList new_changes;
   1038   std::vector<int> expected_icons;
   1039   // We start from one here so that we don't have to deal with a -1 visit time.
   1040   for (int i = 1; i <= kFaviconBatchSize; ++i) {
   1041     expected_icons.push_back(i);
   1042     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1043     FillImageSpecifics(BuildFaviconData(i),
   1044                        image_specifics.mutable_favicon_image());
   1045     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1046         1,
   1047         image_specifics,
   1048         base::Time(),
   1049         syncer::AttachmentIdList(),
   1050         syncer::AttachmentServiceProxyForTest::Create()));
   1051     FillTrackingSpecifics(BuildFaviconData(i),
   1052                           tracking_specifics.mutable_favicon_tracking());
   1053     new_changes.push_back(syncer::SyncChange(
   1054         FROM_HERE,
   1055         syncer::SyncChange::ACTION_UPDATE,
   1056         syncer::SyncData::CreateRemoteData(
   1057             1,
   1058             tracking_specifics,
   1059             base::Time(),
   1060             syncer::AttachmentIdList(),
   1061             syncer::AttachmentServiceProxyForTest::Create())));
   1062     tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(i-1);
   1063     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1064         1,
   1065         tracking_specifics,
   1066         base::Time(),
   1067         syncer::AttachmentIdList(),
   1068         syncer::AttachmentServiceProxyForTest::Create()));
   1069   }
   1070 
   1071   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1072 
   1073   // Now receive the new icons as an update.
   1074   cache()->ProcessSyncChanges(FROM_HERE, new_changes);
   1075   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1076   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
   1077 }
   1078 
   1079 // Receiving the same tracking information as the local data should have no
   1080 // effect.
   1081 TEST_F(SyncFaviconCacheTest, ReceiveSameTracking) {
   1082   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1083   syncer::SyncChangeList same_changes;
   1084   std::vector<int> expected_icons;
   1085   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1086     expected_icons.push_back(i);
   1087     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1088     FillImageSpecifics(BuildFaviconData(i),
   1089                        image_specifics.mutable_favicon_image());
   1090     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1091         1,
   1092         image_specifics,
   1093         base::Time(),
   1094         syncer::AttachmentIdList(),
   1095         syncer::AttachmentServiceProxyForTest::Create()));
   1096     FillTrackingSpecifics(BuildFaviconData(i),
   1097                           tracking_specifics.mutable_favicon_tracking());
   1098     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1099         1,
   1100         tracking_specifics,
   1101         base::Time(),
   1102         syncer::AttachmentIdList(),
   1103         syncer::AttachmentServiceProxyForTest::Create()));
   1104     same_changes.push_back(syncer::SyncChange(
   1105         FROM_HERE,
   1106         syncer::SyncChange::ACTION_UPDATE,
   1107         syncer::SyncData::CreateRemoteData(
   1108             1,
   1109             tracking_specifics,
   1110             base::Time(),
   1111             syncer::AttachmentIdList(),
   1112             syncer::AttachmentServiceProxyForTest::Create())));
   1113   }
   1114 
   1115   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1116 
   1117   // Now receive the new icons as an update.
   1118   cache()->ProcessSyncChanges(FROM_HERE, same_changes);
   1119   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1120   ASSERT_TRUE(VerifyLocalIcons(expected_icons));
   1121 }
   1122 
   1123 // Verify we can delete favicons after setting up sync.
   1124 TEST_F(SyncFaviconCacheTest, DeleteFavicons) {
   1125   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1126   syncer::SyncChangeList tracking_deletions, image_deletions;
   1127   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1128     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1129     FillImageSpecifics(BuildFaviconData(i),
   1130                        image_specifics.mutable_favicon_image());
   1131     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1132         1,
   1133         image_specifics,
   1134         base::Time(),
   1135         syncer::AttachmentIdList(),
   1136         syncer::AttachmentServiceProxyForTest::Create()));
   1137     FillTrackingSpecifics(BuildFaviconData(i),
   1138                           tracking_specifics.mutable_favicon_tracking());
   1139     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1140         1,
   1141         tracking_specifics,
   1142         base::Time(),
   1143         syncer::AttachmentIdList(),
   1144         syncer::AttachmentServiceProxyForTest::Create()));
   1145     tracking_deletions.push_back(syncer::SyncChange(
   1146         FROM_HERE,
   1147         syncer::SyncChange::ACTION_DELETE,
   1148         syncer::SyncData::CreateRemoteData(
   1149             1,
   1150             tracking_specifics,
   1151             base::Time(),
   1152             syncer::AttachmentIdList(),
   1153             syncer::AttachmentServiceProxyForTest::Create())));
   1154     image_deletions.push_back(syncer::SyncChange(
   1155         FROM_HERE,
   1156         syncer::SyncChange::ACTION_DELETE,
   1157         syncer::SyncData::CreateRemoteData(
   1158             1,
   1159             image_specifics,
   1160             base::Time(),
   1161             syncer::AttachmentIdList(),
   1162             syncer::AttachmentServiceProxyForTest::Create())));
   1163   }
   1164 
   1165   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1166 
   1167   // Now receive the tracking deletions. Since we'll still have orphan data,
   1168   // the favicon count should remain the same.
   1169   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1170   cache()->ProcessSyncChanges(FROM_HERE, tracking_deletions);
   1171   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1172   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1173 
   1174   // Once the image deletions arrive, the favicon count should be 0 again.
   1175   cache()->ProcessSyncChanges(FROM_HERE, image_deletions);
   1176   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1177   EXPECT_EQ(0U, GetFaviconCount());
   1178 }
   1179 
   1180 // Ensure that MergeDataAndStartSyncing enforces the sync favicon limit by
   1181 // dropping local icons.
   1182 TEST_F(SyncFaviconCacheTest, ExpireOnMergeData) {
   1183   std::vector<int> expected_icons;
   1184   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1185 
   1186   // Set up sync so it has the maximum number of favicons, while the local has
   1187   // the same amount of different favicons.
   1188   for (int i = 0; i < kMaxSyncFavicons; ++i) {
   1189     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1190     FillImageSpecifics(BuildFaviconData(i),
   1191                        image_specifics.mutable_favicon_image());
   1192     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1193         1,
   1194         image_specifics,
   1195         base::Time(),
   1196         syncer::AttachmentIdList(),
   1197         syncer::AttachmentServiceProxyForTest::Create()));
   1198     FillTrackingSpecifics(BuildFaviconData(i),
   1199                           tracking_specifics.mutable_favicon_tracking());
   1200     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1201         1,
   1202         tracking_specifics,
   1203         base::Time(),
   1204         syncer::AttachmentIdList(),
   1205         syncer::AttachmentServiceProxyForTest::Create()));
   1206     expected_icons.push_back(i);
   1207 
   1208     TestFaviconData favicon = BuildFaviconData(i+kMaxSyncFavicons);
   1209     TriggerSyncFaviconReceived(favicon.page_url,
   1210                                favicon.icon_url,
   1211                                favicon.image_16,
   1212                                i+kMaxSyncFavicons);
   1213   }
   1214 
   1215   EXPECT_FALSE(VerifyLocalIcons(expected_icons));
   1216 
   1217   // Drops image part of the unsynced icons.
   1218   syncer::SyncMergeResult merge_result =
   1219       cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
   1220                                         initial_image_data,
   1221                                         CreateAndPassProcessor(),
   1222                                         CreateAndPassSyncErrorFactory());
   1223   EXPECT_EQ((unsigned long)kMaxSyncFavicons * 2,
   1224             GetFaviconCount());  // Still have tracking.
   1225   EXPECT_EQ((unsigned long)kMaxSyncFavicons,
   1226             cache()->GetAllSyncData(syncer::FAVICON_IMAGES).size());
   1227   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1228   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_added());
   1229   EXPECT_EQ(0, merge_result.num_items_modified());
   1230   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_deleted());
   1231   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_before_association());
   1232   EXPECT_EQ(kMaxSyncFavicons * 2, merge_result.num_items_after_association());
   1233 
   1234   // Drops tracking part of the unsynced icons.
   1235   merge_result =
   1236       cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
   1237                                         initial_tracking_data,
   1238                                         CreateAndPassProcessor(),
   1239                                         CreateAndPassSyncErrorFactory());
   1240   EXPECT_EQ((unsigned long)kMaxSyncFavicons,
   1241             cache()->GetAllSyncData(syncer::FAVICON_TRACKING).size());
   1242   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1243   EXPECT_EQ(0, merge_result.num_items_added());
   1244   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_modified());
   1245   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_deleted());
   1246   EXPECT_EQ(kMaxSyncFavicons * 2, merge_result.num_items_before_association());
   1247   EXPECT_EQ(kMaxSyncFavicons, merge_result.num_items_after_association());
   1248 
   1249   EXPECT_TRUE(VerifyLocalIcons(expected_icons));
   1250 }
   1251 
   1252 // Receiving sync additions (via ProcessSyncChanges) should not trigger
   1253 // expirations.
   1254 TEST_F(SyncFaviconCacheTest, NoExpireOnProcessSyncChanges) {
   1255   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1256   syncer::SyncChangeList image_changes, tracking_changes;
   1257   std::vector<int> expected_icons;
   1258   for (int i = 0; i < kMaxSyncFavicons; ++i) {
   1259     expected_icons.push_back(i);
   1260     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1261     FillImageSpecifics(BuildFaviconData(i),
   1262                        image_specifics.mutable_favicon_image());
   1263     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1264         1,
   1265         image_specifics,
   1266         base::Time(),
   1267         syncer::AttachmentIdList(),
   1268         syncer::AttachmentServiceProxyForTest::Create()));
   1269     FillTrackingSpecifics(BuildFaviconData(i),
   1270                           tracking_specifics.mutable_favicon_tracking());
   1271     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1272         1,
   1273         tracking_specifics,
   1274         base::Time(),
   1275         syncer::AttachmentIdList(),
   1276         syncer::AttachmentServiceProxyForTest::Create()));
   1277     // Set up new tracking specifics for the icons received at change time.
   1278     expected_icons.push_back(i + kMaxSyncFavicons);
   1279     FillImageSpecifics(BuildFaviconData(i + kMaxSyncFavicons),
   1280                        image_specifics.mutable_favicon_image());
   1281     image_changes.push_back(syncer::SyncChange(
   1282         FROM_HERE,
   1283         syncer::SyncChange::ACTION_ADD,
   1284         syncer::SyncData::CreateRemoteData(
   1285             1,
   1286             image_specifics,
   1287             base::Time(),
   1288             syncer::AttachmentIdList(),
   1289             syncer::AttachmentServiceProxyForTest::Create())));
   1290     FillTrackingSpecifics(BuildFaviconData(i + kMaxSyncFavicons),
   1291                           tracking_specifics.mutable_favicon_tracking());
   1292     tracking_changes.push_back(syncer::SyncChange(
   1293         FROM_HERE,
   1294         syncer::SyncChange::ACTION_ADD,
   1295         syncer::SyncData::CreateRemoteData(
   1296             1,
   1297             tracking_specifics,
   1298             base::Time(),
   1299             syncer::AttachmentIdList(),
   1300             syncer::AttachmentServiceProxyForTest::Create())));
   1301   }
   1302 
   1303   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1304 
   1305   // Now receive the new icons as an update.
   1306   EXPECT_EQ((unsigned long)kMaxSyncFavicons, GetFaviconCount());
   1307   cache()->ProcessSyncChanges(FROM_HERE, image_changes);
   1308   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1309   cache()->ProcessSyncChanges(FROM_HERE, tracking_changes);
   1310   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1311   EXPECT_TRUE(VerifyLocalIcons(expected_icons));
   1312   EXPECT_GT(GetFaviconCount(), (unsigned long)kMaxSyncFavicons);
   1313 }
   1314 
   1315 // Test that visiting a new page triggers a favicon load and a sync addition.
   1316 TEST_F(SyncFaviconCacheTest, AddOnFaviconVisited) {
   1317   EXPECT_EQ(0U, GetFaviconCount());
   1318   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1319   std::vector<int> expected_icons;
   1320 
   1321   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1322     expected_icons.push_back(i);
   1323     TestFaviconData test_data = BuildFaviconData(i);
   1324     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1325   }
   1326 
   1327   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetTaskCount());
   1328 
   1329   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1330     TestFaviconData test_data = BuildFaviconData(i);
   1331     OnCustomFaviconDataAvailable(test_data);
   1332 
   1333     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1334     ASSERT_EQ(2U, changes.size());
   1335     EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
   1336     EXPECT_EQ(syncer::FAVICON_IMAGES, changes[0].sync_data().GetDataType());
   1337     EXPECT_TRUE(
   1338         CompareFaviconDataToSpecifics(test_data,
   1339                                       changes[0].sync_data().GetSpecifics()));
   1340     EXPECT_EQ(syncer::FAVICON_TRACKING, changes[1].sync_data().GetDataType());
   1341     // Just verify the favicon url for the tracking specifics and that the
   1342     // timestamp is non-null.
   1343     EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[1].change_type());
   1344     EXPECT_EQ(test_data.icon_url.spec(),
   1345               changes[1].sync_data().GetSpecifics().favicon_tracking().
   1346                   favicon_url());
   1347     EXPECT_NE(changes[1].sync_data().GetSpecifics().favicon_tracking().
   1348                   last_visit_time_ms(), 0);
   1349   }
   1350 
   1351   EXPECT_EQ(0U, GetTaskCount());
   1352   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1353 }
   1354 
   1355 // Test that visiting a known page does not trigger a favicon load and just
   1356 // updates the sync tracking info.
   1357 TEST_F(SyncFaviconCacheTest, UpdateOnFaviconVisited) {
   1358   EXPECT_EQ(0U, GetFaviconCount());
   1359   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1360   std::vector<int> expected_icons;
   1361 
   1362   // Add the favicons.
   1363   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1364     expected_icons.push_back(i);
   1365     TestFaviconData test_data = BuildFaviconData(i);
   1366     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1367     OnCustomFaviconDataAvailable(test_data);
   1368   }
   1369   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1370 
   1371   // Visit the favicons again.
   1372   EXPECT_EQ(0U, GetTaskCount());
   1373   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1374     TestFaviconData test_data = BuildFaviconData(i);
   1375     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1376 
   1377     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1378     ASSERT_EQ(1U, changes.size());
   1379     // Just verify the favicon url for the tracking specifics and that the
   1380     // timestamp is non-null.
   1381     EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
   1382     EXPECT_EQ(test_data.icon_url.spec(),
   1383               changes[0].sync_data().GetSpecifics().favicon_tracking().
   1384                   favicon_url());
   1385     EXPECT_NE(changes[0].sync_data().GetSpecifics().favicon_tracking().
   1386                   last_visit_time_ms(), 0);
   1387   }
   1388   EXPECT_EQ(0U, GetTaskCount());
   1389   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1390 }
   1391 
   1392 // Ensure we properly expire old synced favicons as new ones are updated.
   1393 TEST_F(SyncFaviconCacheTest, ExpireOnFaviconVisited) {
   1394   EXPECT_EQ(0U, GetFaviconCount());
   1395   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1396   std::vector<int> expected_icons;
   1397 
   1398   // Add the initial favicons.
   1399   for (int i = 0; i < kMaxSyncFavicons; ++i) {
   1400     expected_icons.push_back(i);
   1401     TestFaviconData test_data = BuildFaviconData(i);
   1402     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1403     OnCustomFaviconDataAvailable(test_data);
   1404   }
   1405   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1406 
   1407   // Visit some new favicons, triggering expirations of the old favicons.
   1408   EXPECT_EQ(0U, GetTaskCount());
   1409   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1410     TestFaviconData old_favicon = BuildFaviconData(i);
   1411     TestFaviconData test_data = BuildFaviconData(i + kMaxSyncFavicons);
   1412     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1413     OnCustomFaviconDataAvailable(test_data);
   1414 
   1415     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1416     ASSERT_EQ(4U, changes.size());
   1417     EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
   1418     EXPECT_TRUE(
   1419         CompareFaviconDataToSpecifics(test_data,
   1420                                       changes[0].sync_data().GetSpecifics()));
   1421     EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, changes[1].change_type());
   1422     EXPECT_EQ(old_favicon.icon_url.spec(),
   1423               syncer::SyncDataLocal(changes[1].sync_data()).GetTag());
   1424 
   1425     EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[2].change_type());
   1426     EXPECT_EQ(test_data.icon_url.spec(),
   1427               changes[2].sync_data().GetSpecifics().favicon_tracking().
   1428                   favicon_url());
   1429     EXPECT_NE(changes[2].sync_data().GetSpecifics().favicon_tracking().
   1430                   last_visit_time_ms(), 0);
   1431     EXPECT_EQ(syncer::SyncChange::ACTION_DELETE, changes[3].change_type());
   1432     EXPECT_EQ(old_favicon.icon_url.spec(),
   1433               syncer::SyncDataLocal(changes[3].sync_data()).GetTag());
   1434   }
   1435 
   1436   EXPECT_EQ(0U, GetTaskCount());
   1437   EXPECT_EQ((unsigned long)kMaxSyncFavicons, GetFaviconCount());
   1438 }
   1439 
   1440 // A full history clear notification should result in all synced favicons being
   1441 // deleted.
   1442 TEST_F(SyncFaviconCacheTest, HistoryFullClear) {
   1443   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1444   std::vector<int> expected_icons;
   1445   std::vector<syncer::SyncChange::SyncChangeType> expected_deletions;
   1446   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1447     expected_icons.push_back(i);
   1448     expected_deletions.push_back(syncer::SyncChange::ACTION_DELETE);
   1449     TestFaviconData test_data = BuildFaviconData(i);
   1450     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1451     FillImageSpecifics(test_data,
   1452                        image_specifics.mutable_favicon_image());
   1453     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1454         1,
   1455         image_specifics,
   1456         base::Time(),
   1457         syncer::AttachmentIdList(),
   1458         syncer::AttachmentServiceProxyForTest::Create()));
   1459     FillTrackingSpecifics(BuildFaviconData(i),
   1460                           tracking_specifics.mutable_favicon_tracking());
   1461     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1462         1,
   1463         tracking_specifics,
   1464         base::Time(),
   1465         syncer::AttachmentIdList(),
   1466         syncer::AttachmentServiceProxyForTest::Create()));
   1467   }
   1468 
   1469   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1470   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1471   EXPECT_TRUE(changes.empty());
   1472 
   1473   history::URLsDeletedDetails deletions;
   1474   deletions.all_history = true;
   1475   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1476   content::NotificationService::current()->Notify(
   1477         chrome::NOTIFICATION_HISTORY_URLS_DELETED,
   1478         content::Source<Profile>(NULL),
   1479         content::Details<history::URLsDeletedDetails>(&deletions));
   1480   EXPECT_EQ(0U, GetFaviconCount());
   1481   changes = processor()->GetAndResetChangeList();
   1482   ASSERT_EQ(changes.size(), (unsigned long)kFaviconBatchSize*2);
   1483   syncer::SyncChangeList changes_1, changes_2;
   1484   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1485     changes_1.push_back(changes[i]);
   1486     changes_2.push_back(changes[i + kFaviconBatchSize]);
   1487   }
   1488   VerifyChanges(syncer::FAVICON_IMAGES,
   1489                 expected_deletions,
   1490                 expected_icons,
   1491                 changes_1);
   1492   VerifyChanges(syncer::FAVICON_TRACKING,
   1493                 expected_deletions,
   1494                 expected_icons,
   1495                 changes_2);
   1496 }
   1497 
   1498 // A partial history clear notification should result in the expired favicons
   1499 // also being deleted from sync.
   1500 TEST_F(SyncFaviconCacheTest, HistorySubsetClear) {
   1501   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1502   std::vector<int> expected_icons;
   1503   std::vector<syncer::SyncChange::SyncChangeType> expected_deletions;
   1504   history::URLsDeletedDetails deletions;
   1505   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1506     TestFaviconData test_data = BuildFaviconData(i);
   1507     if (i < kFaviconBatchSize/2) {
   1508       expected_icons.push_back(i);
   1509       expected_deletions.push_back(syncer::SyncChange::ACTION_DELETE);
   1510       deletions.favicon_urls.insert(test_data.icon_url);
   1511     }
   1512     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1513     FillImageSpecifics(test_data,
   1514                        image_specifics.mutable_favicon_image());
   1515     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1516         1,
   1517         image_specifics,
   1518         base::Time(),
   1519         syncer::AttachmentIdList(),
   1520         syncer::AttachmentServiceProxyForTest::Create()));
   1521     FillTrackingSpecifics(BuildFaviconData(i),
   1522                           tracking_specifics.mutable_favicon_tracking());
   1523     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1524         1,
   1525         tracking_specifics,
   1526         base::Time(),
   1527         syncer::AttachmentIdList(),
   1528         syncer::AttachmentServiceProxyForTest::Create()));
   1529   }
   1530 
   1531   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1532   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1533   EXPECT_TRUE(changes.empty());
   1534 
   1535   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1536   content::NotificationService::current()->Notify(
   1537         chrome::NOTIFICATION_HISTORY_URLS_DELETED,
   1538         content::Source<Profile>(NULL),
   1539         content::Details<history::URLsDeletedDetails>(&deletions));
   1540   EXPECT_EQ((unsigned long)kFaviconBatchSize/2, GetFaviconCount());
   1541   changes = processor()->GetAndResetChangeList();
   1542   ASSERT_EQ(changes.size(), (unsigned long)kFaviconBatchSize);
   1543   syncer::SyncChangeList changes_1, changes_2;
   1544   for (size_t i = 0; i < kFaviconBatchSize/2; ++i) {
   1545     changes_1.push_back(changes[i]);
   1546     changes_2.push_back(changes[i + kFaviconBatchSize/2]);
   1547   }
   1548   VerifyChanges(syncer::FAVICON_IMAGES,
   1549                 expected_deletions,
   1550                 expected_icons,
   1551                 changes_1);
   1552   VerifyChanges(syncer::FAVICON_TRACKING,
   1553                 expected_deletions,
   1554                 expected_icons,
   1555                 changes_2);
   1556 }
   1557 
   1558 // Any favicon urls with the "data" scheme should be ignored.
   1559 TEST_F(SyncFaviconCacheTest, IgnoreDataScheme) {
   1560   EXPECT_EQ(0U, GetFaviconCount());
   1561   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1562   std::vector<int> expected_icons;
   1563 
   1564   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1565     TestFaviconData test_data = BuildFaviconData(i);
   1566     cache()->OnFaviconVisited(test_data.page_url, GURL());
   1567   }
   1568 
   1569   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetTaskCount());
   1570 
   1571   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1572     TestFaviconData test_data = BuildFaviconData(i);
   1573     test_data.icon_url = GURL("data:image/png;base64;blabla");
   1574     EXPECT_TRUE(test_data.icon_url.is_valid());
   1575     OnCustomFaviconDataAvailable(test_data);
   1576   }
   1577 
   1578   EXPECT_EQ(0U, GetTaskCount());
   1579   EXPECT_EQ(0U, GetFaviconCount());
   1580   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1581   EXPECT_TRUE(changes.empty());
   1582 }
   1583 
   1584 // When visiting a page we've already loaded the favicon for, don't attempt to
   1585 // reload the favicon, just update the visit time using the cached icon url.
   1586 TEST_F(SyncFaviconCacheTest, ReuseCachedIconUrl) {
   1587   EXPECT_EQ(0U, GetFaviconCount());
   1588   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1589   std::vector<int> expected_icons;
   1590 
   1591   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1592     expected_icons.push_back(i);
   1593     TestFaviconData test_data = BuildFaviconData(i);
   1594     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1595   }
   1596 
   1597   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetTaskCount());
   1598 
   1599   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1600     TestFaviconData test_data = BuildFaviconData(i);
   1601     OnCustomFaviconDataAvailable(test_data);
   1602   }
   1603   processor()->GetAndResetChangeList();
   1604   EXPECT_EQ(0U, GetTaskCount());
   1605   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1606 
   1607   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1608     TestFaviconData test_data = BuildFaviconData(i);
   1609     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1610     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1611     ASSERT_EQ(1U, changes.size());
   1612     // Just verify the favicon url for the tracking specifics and that the
   1613     // timestamp is non-null.
   1614     EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
   1615     EXPECT_EQ(test_data.icon_url.spec(),
   1616               changes[0].sync_data().GetSpecifics().favicon_tracking().
   1617                   favicon_url());
   1618     EXPECT_NE(changes[0].sync_data().GetSpecifics().favicon_tracking().
   1619                   last_visit_time_ms(), 0);
   1620   }
   1621   EXPECT_EQ(0U, GetTaskCount());
   1622 }
   1623 
   1624 // If we wind up with orphan image/tracking nodes, then receive an update
   1625 // for those favicons, we should lazily create the missing nodes.
   1626 TEST_F(SyncFaviconCacheTest, UpdatedOrphans) {
   1627   EXPECT_EQ(0U, GetFaviconCount());
   1628   SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
   1629 
   1630   syncer::SyncChangeList initial_image_changes;
   1631   syncer::SyncChangeList initial_tracking_changes;
   1632   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1633     TestFaviconData test_data = BuildFaviconData(i);
   1634     // Even favicons have image data but no tracking data. Odd favicons have
   1635     // tracking data but no image data.
   1636     if (i % 2 == 0) {
   1637       sync_pb::EntitySpecifics image_specifics;
   1638       FillImageSpecifics(BuildFaviconData(i),
   1639                          image_specifics.mutable_favicon_image());
   1640       initial_image_changes.push_back(syncer::SyncChange(
   1641           FROM_HERE,
   1642           syncer::SyncChange::ACTION_ADD,
   1643           syncer::SyncData::CreateRemoteData(
   1644               1,
   1645               image_specifics,
   1646               base::Time(),
   1647               syncer::AttachmentIdList(),
   1648               syncer::AttachmentServiceProxyForTest::Create())));
   1649     } else {
   1650       sync_pb::EntitySpecifics tracking_specifics;
   1651       FillTrackingSpecifics(BuildFaviconData(i),
   1652                             tracking_specifics.mutable_favicon_tracking());
   1653       initial_tracking_changes.push_back(syncer::SyncChange(
   1654           FROM_HERE,
   1655           syncer::SyncChange::ACTION_ADD,
   1656           syncer::SyncData::CreateRemoteData(
   1657               1,
   1658               tracking_specifics,
   1659               base::Time(),
   1660               syncer::AttachmentIdList(),
   1661               syncer::AttachmentServiceProxyForTest::Create())));
   1662     }
   1663   }
   1664 
   1665   cache()->ProcessSyncChanges(FROM_HERE, initial_image_changes);
   1666   cache()->ProcessSyncChanges(FROM_HERE, initial_tracking_changes);
   1667   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1668   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1669 
   1670   for (int i = 0; i < kFaviconBatchSize/2; ++i) {
   1671     TestFaviconData test_data = BuildFaviconData(i);
   1672     cache()->OnFaviconVisited(test_data.page_url, GURL());
   1673     EXPECT_EQ(1U, GetTaskCount());
   1674     OnCustomFaviconDataAvailable(test_data);
   1675     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1676 
   1677     // Even favicons had image data, so should now receive new tracking data
   1678     // and updated image data (we allow one update after the initial add).
   1679     // Odd favicons had tracking so should now receive new image data and
   1680     // updated tracking data.
   1681     if (i % 2 == 0) {
   1682       ASSERT_EQ(2U, changes.size());
   1683       EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
   1684       EXPECT_TRUE(
   1685           CompareFaviconDataToSpecifics(test_data,
   1686                                         changes[0].sync_data().GetSpecifics()));
   1687       EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[1].change_type());
   1688       EXPECT_EQ(test_data.icon_url.spec(),
   1689                 changes[1].sync_data().GetSpecifics().favicon_tracking().
   1690                     favicon_url());
   1691       EXPECT_NE(changes[1].sync_data().GetSpecifics().favicon_tracking().
   1692                     last_visit_time_ms(), 0);
   1693     } else {
   1694       ASSERT_EQ(2U, changes.size());
   1695       EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type());
   1696       EXPECT_TRUE(
   1697           CompareFaviconDataToSpecifics(test_data,
   1698                                         changes[0].sync_data().GetSpecifics()));
   1699       EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[1].change_type());
   1700       EXPECT_EQ(test_data.icon_url.spec(),
   1701                 changes[1].sync_data().GetSpecifics().favicon_tracking().
   1702                     favicon_url());
   1703       EXPECT_NE(changes[1].sync_data().GetSpecifics().favicon_tracking().
   1704                     last_visit_time_ms(), 0);
   1705     }
   1706   }
   1707 
   1708   EXPECT_EQ(0U, GetTaskCount());
   1709   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1710 }
   1711 
   1712 // Verify that orphaned favicon images don't result in creating invalid
   1713 // favicon tracking data.
   1714 TEST_F(SyncFaviconCacheTest, PartialAssociationInfo) {
   1715   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1716   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1717     sync_pb::EntitySpecifics image_specifics;
   1718     FillImageSpecifics(BuildFaviconData(i),
   1719                        image_specifics.mutable_favicon_image());
   1720     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1721         1,
   1722         image_specifics,
   1723         base::Time(),
   1724         syncer::AttachmentIdList(),
   1725         syncer::AttachmentServiceProxyForTest::Create()));
   1726     image_specifics.mutable_favicon_image()->clear_favicon_web();
   1727   }
   1728 
   1729   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1730   syncer::SyncChangeList change_list = processor()->GetAndResetChangeList();
   1731   EXPECT_TRUE(change_list.empty());
   1732   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1733 }
   1734 
   1735 // Tests that we don't choke if a favicon visit node with a null visit time is
   1736 // present (see crbug.com/258196) and an update is made.
   1737 TEST_F(SyncFaviconCacheTest, NullFaviconVisitTime) {
   1738   EXPECT_EQ(0U, GetFaviconCount());
   1739 
   1740   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1741   std::vector<int> expected_icons;
   1742   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1743     expected_icons.push_back(i);
   1744     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1745     FillImageSpecifics(BuildFaviconData(i),
   1746                        image_specifics.mutable_favicon_image());
   1747     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1748         1,
   1749         image_specifics,
   1750         base::Time(),
   1751         syncer::AttachmentIdList(),
   1752         syncer::AttachmentServiceProxyForTest::Create()));
   1753     FillTrackingSpecifics(BuildFaviconData(i),
   1754                           tracking_specifics.mutable_favicon_tracking());
   1755     tracking_specifics.mutable_favicon_tracking()->set_last_visit_time_ms(
   1756         syncer::TimeToProtoTime(base::Time()));
   1757     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1758         1,
   1759         tracking_specifics,
   1760         base::Time(),
   1761         syncer::AttachmentIdList(),
   1762         syncer::AttachmentServiceProxyForTest::Create()));
   1763   }
   1764 
   1765   cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES,
   1766                                     initial_image_data,
   1767                                     CreateAndPassProcessor(),
   1768                                     CreateAndPassSyncErrorFactory());
   1769   ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
   1770   cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING,
   1771                                     initial_tracking_data,
   1772                                     CreateAndPassProcessor(),
   1773                                     CreateAndPassSyncErrorFactory());
   1774   ASSERT_EQ((unsigned long)kFaviconBatchSize,
   1775             processor()->GetAndResetChangeList().size());
   1776   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1777 
   1778   // Visit the favicons again.
   1779   EXPECT_EQ(0U, GetTaskCount());
   1780   for (int i = 0; i < kFaviconBatchSize; ++i) {
   1781     TestFaviconData test_data = BuildFaviconData(i);
   1782     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1783 
   1784     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1785     ASSERT_EQ(1U, changes.size());
   1786     // Just verify the favicon url for the tracking specifics and that the
   1787     // timestamp is non-null.
   1788     EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type());
   1789     EXPECT_EQ(test_data.icon_url.spec(),
   1790               changes[0].sync_data().GetSpecifics().favicon_tracking().
   1791                   favicon_url());
   1792     EXPECT_NE(changes[0].sync_data().GetSpecifics().favicon_tracking().
   1793                   last_visit_time_ms(), 0);
   1794   }
   1795   EXPECT_EQ(0U, GetTaskCount());
   1796   EXPECT_EQ((unsigned long)kFaviconBatchSize, GetFaviconCount());
   1797 }
   1798 
   1799 // If another synced client has a clock skewed towards the future, it's possible
   1800 // that favicons added locally will be expired as they are added. Ensure this
   1801 // doesn't crash (see crbug.com/306150).
   1802 TEST_F(SyncFaviconCacheTest, VisitFaviconClockSkew) {
   1803   EXPECT_EQ(0U, GetFaviconCount());
   1804   const int kClockSkew = 20;  // 20 minutes in the future.
   1805 
   1806   // Set up sync with kMaxSyncFavicons starting kClockSkew minutes in the
   1807   // future.
   1808   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1809   for (int i = 0; i < kMaxSyncFavicons; ++i) {
   1810     sync_pb::EntitySpecifics image_specifics, tracking_specifics;
   1811     TestFaviconData test_data = BuildFaviconData(i);
   1812     test_data.last_visit_time =
   1813         syncer::TimeToProtoTime(
   1814             base::Time::Now() + base::TimeDelta::FromMinutes(kClockSkew));
   1815     FillImageSpecifics(test_data,
   1816                        image_specifics.mutable_favicon_image());
   1817     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1818         1,
   1819         image_specifics,
   1820         base::Time(),
   1821         syncer::AttachmentIdList(),
   1822         syncer::AttachmentServiceProxyForTest::Create()));
   1823     FillTrackingSpecifics(test_data,
   1824                           tracking_specifics.mutable_favicon_tracking());
   1825     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1826         1,
   1827         tracking_specifics,
   1828         base::Time(),
   1829         syncer::AttachmentIdList(),
   1830         syncer::AttachmentServiceProxyForTest::Create()));
   1831   }
   1832   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1833 
   1834   // Visit some new favicons with local time, which will be expired as they
   1835   // are added.
   1836   EXPECT_EQ(0U, GetTaskCount());
   1837   for (int i = 0; i < kClockSkew; ++i) {
   1838     TestFaviconData test_data = BuildFaviconData(i + kMaxSyncFavicons);
   1839     cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1840     OnCustomFaviconDataAvailable(test_data);
   1841 
   1842     // The changes will be an add followed by a delete for both the image and
   1843     // tracking info.
   1844     syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1845     ASSERT_EQ(changes.size(), 4U);
   1846     ASSERT_EQ(changes[0].change_type(), syncer::SyncChange::ACTION_ADD);
   1847     ASSERT_EQ(changes[0].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
   1848     ASSERT_EQ(changes[1].change_type(), syncer::SyncChange::ACTION_DELETE);
   1849     ASSERT_EQ(changes[1].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
   1850     ASSERT_EQ(changes[2].change_type(), syncer::SyncChange::ACTION_ADD);
   1851     ASSERT_EQ(changes[2].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
   1852     ASSERT_EQ(changes[3].change_type(), syncer::SyncChange::ACTION_DELETE);
   1853     ASSERT_EQ(changes[3].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
   1854   }
   1855   EXPECT_EQ(0U, GetTaskCount());
   1856   EXPECT_EQ((unsigned long)kMaxSyncFavicons, GetFaviconCount());
   1857 }
   1858 
   1859 // Simulate a case where the set of tracking info and image info doesn't match,
   1860 // and there is more tracking info than the max. A local update should correctly
   1861 // determine whether to update/add an image/tracking entity.
   1862 TEST_F(SyncFaviconCacheTest, MixedThreshold) {
   1863   // First go through and add local favicons.
   1864   for (int i = kMaxSyncFavicons; i < kMaxSyncFavicons + 5; ++i) {
   1865     TestFaviconData favicon = BuildFaviconData(i);
   1866     TriggerSyncFaviconReceived(favicon.page_url,
   1867                                favicon.icon_url,
   1868                                favicon.image_16,
   1869                                favicon.last_visit_time);
   1870   }
   1871 
   1872   syncer::SyncDataList initial_image_data, initial_tracking_data;
   1873   // Then sync with enough favicons such that the tracking info is over the max
   1874   // after merge completes.
   1875   for (int i = 0; i < kMaxSyncFavicons; ++i) {
   1876     sync_pb::EntitySpecifics image_specifics;
   1877     // Push the images forward by 5, to match the unsynced favicons.
   1878     FillImageSpecifics(BuildFaviconData(i + 5),
   1879                        image_specifics.mutable_favicon_image());
   1880     initial_image_data.push_back(syncer::SyncData::CreateRemoteData(
   1881         1,
   1882         image_specifics,
   1883         base::Time(),
   1884         syncer::AttachmentIdList(),
   1885         syncer::AttachmentServiceProxyForTest::Create()));
   1886 
   1887     sync_pb::EntitySpecifics tracking_specifics;
   1888     FillTrackingSpecifics(BuildFaviconData(i),
   1889                           tracking_specifics.mutable_favicon_tracking());
   1890     initial_tracking_data.push_back(syncer::SyncData::CreateRemoteData(
   1891         1,
   1892         tracking_specifics,
   1893         base::Time(),
   1894         syncer::AttachmentIdList(),
   1895         syncer::AttachmentServiceProxyForTest::Create()));
   1896   }
   1897   SetUpInitialSync(initial_image_data, initial_tracking_data);
   1898 
   1899   // The local unsynced tracking info should be dropped, but not deleted.
   1900   EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
   1901 
   1902   // Because the image and tracking data don't overlap, the total number of
   1903   // favicons is still over the limit.
   1904   EXPECT_EQ((unsigned long)kMaxSyncFavicons + 5, GetFaviconCount());
   1905 
   1906   // Trigger a tracking change for one of the favicons whose tracking info
   1907   // was dropped, resulting in a tracking add and expiration of the orphaned
   1908   // images.
   1909   TestFaviconData test_data = BuildFaviconData(kMaxSyncFavicons);
   1910   cache()->OnFaviconVisited(test_data.page_url, test_data.icon_url);
   1911 
   1912   syncer::SyncChangeList changes = processor()->GetAndResetChangeList();
   1913   // 1 image update, 5 image deletions, 1 tracking deletion.
   1914   ASSERT_EQ(6U, changes.size());
   1915   // Expire image for favicon[kMaxSyncFavicons + 1].
   1916   EXPECT_EQ(changes[0].change_type(), syncer::SyncChange::ACTION_DELETE);
   1917   EXPECT_EQ(changes[0].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
   1918   EXPECT_EQ(kMaxSyncFavicons + 1, GetFaviconId(changes[0]));
   1919   // Expire image for favicon[kMaxSyncFavicons + 2].
   1920   EXPECT_EQ(changes[1].change_type(), syncer::SyncChange::ACTION_DELETE);
   1921   EXPECT_EQ(changes[1].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
   1922   EXPECT_EQ(kMaxSyncFavicons + 2, GetFaviconId(changes[1]));
   1923   // Expire image for favicon[kMaxSyncFavicons + 3].
   1924   EXPECT_EQ(changes[2].change_type(), syncer::SyncChange::ACTION_DELETE);
   1925   EXPECT_EQ(changes[2].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
   1926   EXPECT_EQ(kMaxSyncFavicons + 3, GetFaviconId(changes[2]));
   1927   // Expire image for favicon[kMaxSyncFavicons + 4].
   1928   EXPECT_EQ(changes[3].change_type(), syncer::SyncChange::ACTION_DELETE);
   1929   EXPECT_EQ(changes[3].sync_data().GetDataType(), syncer::FAVICON_IMAGES);
   1930   EXPECT_EQ(kMaxSyncFavicons + 4, GetFaviconId(changes[3]));
   1931   // Update tracking for favicon[kMaxSyncFavicons].
   1932   EXPECT_EQ(changes[4].change_type(), syncer::SyncChange::ACTION_ADD);
   1933   EXPECT_EQ(changes[4].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
   1934   EXPECT_EQ(kMaxSyncFavicons, GetFaviconId(changes[4]));
   1935   // Expire tracking for favicon[0].
   1936   EXPECT_EQ(changes[5].change_type(), syncer::SyncChange::ACTION_DELETE);
   1937   EXPECT_EQ(changes[5].sync_data().GetDataType(), syncer::FAVICON_TRACKING);
   1938   EXPECT_EQ(0, GetFaviconId(changes[5]));
   1939 }
   1940 
   1941 }  // namespace browser_sync
   1942