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