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