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