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/stringprintf.h"
9 #include "base/time/time.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/history/history_notifications.h"
12 #include "content/public/browser/notification_service.h"
13 #include "sync/api/sync_error_factory_mock.h"
14 #include "sync/api/time.h"
15 #include "sync/protocol/favicon_image_specifics.pb.h"
16 #include "sync/protocol/favicon_tracking_specifics.pb.h"
17 #include "sync/protocol/sync.pb.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 namespace browser_sync
{
24 // Total number of favicons to use in sync test batches.
25 const int kFaviconBatchSize
= 10;
27 // Maximum number of favicons to sync.
28 const int kMaxSyncFavicons
= kFaviconBatchSize
*2;
30 // TestChangeProcessor --------------------------------------------------------
32 // Dummy SyncChangeProcessor used to help review what SyncChanges are pushed
34 class TestChangeProcessor
: public syncer::SyncChangeProcessor
{
36 TestChangeProcessor();
37 virtual ~TestChangeProcessor();
39 // Store a copy of all the changes passed in so we can examine them later.
40 virtual syncer::SyncError
ProcessSyncChanges(
41 const tracked_objects::Location
& from_here
,
42 const syncer::SyncChangeList
& change_list
) OVERRIDE
;
44 virtual syncer::SyncDataList
GetAllSyncData(syncer::ModelType type
) const
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_
);
65 void set_erroneous(bool erroneous
) { erroneous_
= erroneous
; }
68 // Track the changes received in ProcessSyncChanges.
69 std::map
<std::string
, syncer::SyncChange
> change_map_
;
70 syncer::SyncChangeList change_list_
;
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
) {
86 return syncer::SyncError(
88 syncer::SyncError::DATATYPE_ERROR
,
90 change_list
[0].sync_data().GetDataType());
93 change_list_
.insert(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();
105 // SyncChangeProcessorDelegate ------------------------------------------------
107 class SyncChangeProcessorDelegate
: public syncer::SyncChangeProcessor
{
109 explicit SyncChangeProcessorDelegate(syncer::SyncChangeProcessor
* recipient
);
110 virtual ~SyncChangeProcessorDelegate();
112 // syncer::SyncChangeProcessor implementation.
113 virtual syncer::SyncError
ProcessSyncChanges(
114 const tracked_objects::Location
& from_here
,
115 const syncer::SyncChangeList
& change_list
) OVERRIDE
;
117 virtual syncer::SyncDataList
GetAllSyncData(syncer::ModelType type
) const
119 return recipient_
->GetAllSyncData(type
);
123 // The recipient of all sync changes.
124 syncer::SyncChangeProcessor
* recipient_
;
126 DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorDelegate
);
129 SyncChangeProcessorDelegate::SyncChangeProcessorDelegate(
130 syncer::SyncChangeProcessor
* recipient
)
131 : recipient_(recipient
) {
135 SyncChangeProcessorDelegate::~SyncChangeProcessorDelegate() {
138 syncer::SyncError
SyncChangeProcessorDelegate::ProcessSyncChanges(
139 const tracked_objects::Location
& from_here
,
140 const syncer::SyncChangeList
& change_list
) {
141 return recipient_
->ProcessSyncChanges(from_here
, change_list
);
144 // TestFaviconData ------------------------------------------------------------
145 struct TestFaviconData
{
146 TestFaviconData() : last_visit_time(0), is_bookmarked(false) {}
149 std::string image_16
;
150 std::string image_32
;
151 std::string image_64
;
152 int64 last_visit_time
;
156 TestFaviconData
BuildFaviconData(int index
) {
157 TestFaviconData data
;
158 data
.page_url
= GURL(base::StringPrintf("http://bla.com/%.2i.html", index
));
159 data
.icon_url
= GURL(base::StringPrintf("http://bla.com/%.2i.ico", index
));
160 data
.image_16
= base::StringPrintf("16 %i", index
);
161 // TODO(zea): enable this once the cache supports writing them.
162 // data.image_32 = base::StringPrintf("32 %i", index);
163 // data.image_64 = base::StringPrintf("64 %i", index);
164 data
.last_visit_time
= index
;
168 void FillImageSpecifics(
169 const TestFaviconData
& test_data
,
170 sync_pb::FaviconImageSpecifics
* image_specifics
) {
171 image_specifics
->set_favicon_url(test_data
.icon_url
.spec());
172 if (!test_data
.image_16
.empty()) {
173 image_specifics
->mutable_favicon_web()->set_height(16);
174 image_specifics
->mutable_favicon_web()->set_width(16);
175 image_specifics
->mutable_favicon_web()->set_favicon(test_data
.image_16
);
177 if (!test_data
.image_32
.empty()) {
178 image_specifics
->mutable_favicon_web_32()->set_height(32);
179 image_specifics
->mutable_favicon_web_32()->set_width(32);
180 image_specifics
->mutable_favicon_web_32()->set_favicon(test_data
.image_32
);
182 if (!test_data
.image_64
.empty()) {
183 image_specifics
->mutable_favicon_touch_64()->set_height(64);
184 image_specifics
->mutable_favicon_touch_64()->set_width(64);
185 image_specifics
->mutable_favicon_touch_64()->
186 set_favicon(test_data
.image_64
);
190 void FillTrackingSpecifics(
191 const TestFaviconData
& test_data
,
192 sync_pb::FaviconTrackingSpecifics
* tracking_specifics
) {
193 tracking_specifics
->set_favicon_url(test_data
.icon_url
.spec());
194 tracking_specifics
->set_last_visit_time_ms(test_data
.last_visit_time
);
195 tracking_specifics
->set_is_bookmarked(test_data
.is_bookmarked
);
198 testing::AssertionResult
CompareFaviconDataToSpecifics(
199 const TestFaviconData
& test_data
,
200 const sync_pb::EntitySpecifics
& specifics
) {
201 if (specifics
.has_favicon_image()) {
202 sync_pb::FaviconImageSpecifics image_specifics
= specifics
.favicon_image();
203 if (image_specifics
.favicon_url() != test_data
.icon_url
.spec())
204 return testing::AssertionFailure() << "Image icon url doesn't match.";
205 if (!test_data
.image_16
.empty()) {
206 if (image_specifics
.favicon_web().favicon() != test_data
.image_16
||
207 image_specifics
.favicon_web().height() != 16 ||
208 image_specifics
.favicon_web().width() != 16) {
209 return testing::AssertionFailure() << "16p image data doesn't match.";
211 } else if (image_specifics
.has_favicon_web()) {
212 return testing::AssertionFailure() << "Missing 16p favicon.";
214 if (!test_data
.image_32
.empty()) {
215 if (image_specifics
.favicon_web_32().favicon() != test_data
.image_32
||
216 image_specifics
.favicon_web().height() != 32 ||
217 image_specifics
.favicon_web().width() != 32) {
218 return testing::AssertionFailure() << "32p image data doesn't match.";
220 } else if (image_specifics
.has_favicon_web_32()) {
221 return testing::AssertionFailure() << "Missing 32p favicon.";
223 if (!test_data
.image_64
.empty()) {
224 if (image_specifics
.favicon_touch_64().favicon() != test_data
.image_64
||
225 image_specifics
.favicon_web().height() != 64 ||
226 image_specifics
.favicon_web().width() != 64) {
227 return testing::AssertionFailure() << "64p image data doesn't match.";
229 } else if (image_specifics
.has_favicon_touch_64()) {
230 return testing::AssertionFailure() << "Missing 64p favicon.";
233 sync_pb::FaviconTrackingSpecifics tracking_specifics
=
234 specifics
.favicon_tracking();
235 if (tracking_specifics
.favicon_url() != test_data
.icon_url
.spec())
236 return testing::AssertionFailure() << "Tracking icon url doesn't match.";
237 if (tracking_specifics
.last_visit_time_ms() != test_data
.last_visit_time
)
238 return testing::AssertionFailure() << "Visit time doesn't match.";
239 if (tracking_specifics
.is_bookmarked() != test_data
.is_bookmarked
)
240 return testing::AssertionFailure() << "Bookmark status doens't match.";
242 return testing::AssertionSuccess();
245 testing::AssertionResult
VerifyChanges(
246 syncer::ModelType expected_model_type
,
247 const std::vector
<syncer::SyncChange::SyncChangeType
>&
248 expected_change_types
,
249 const std::vector
<int>& expected_icons
,
250 const syncer::SyncChangeList
& change_list
) {
251 DCHECK_EQ(expected_change_types
.size(), expected_icons
.size());
252 if (change_list
.size() != expected_icons
.size())
253 return testing::AssertionFailure() << "Change list size doesn't match.";
254 for (size_t i
= 0; i
< expected_icons
.size(); ++i
) {
255 TestFaviconData data
= BuildFaviconData(expected_icons
[i
]);
256 if (change_list
[i
].sync_data().GetDataType() != expected_model_type
)
257 return testing::AssertionFailure() << "Change datatype doesn't match.";
258 if (change_list
[i
].change_type() != expected_change_types
[i
])
259 return testing::AssertionFailure() << "Change type doesn't match.";
260 if (change_list
[i
].change_type() == syncer::SyncChange::ACTION_DELETE
) {
261 if (change_list
[i
].sync_data().GetTag() != data
.icon_url
.spec())
262 return testing::AssertionFailure() << "Deletion url does not match.";
264 testing::AssertionResult compare_result
=
265 CompareFaviconDataToSpecifics(
267 change_list
[i
].sync_data().GetSpecifics());
269 return compare_result
;
272 return testing::AssertionSuccess();
277 class SyncFaviconCacheTest
: public testing::Test
{
279 SyncFaviconCacheTest();
280 virtual ~SyncFaviconCacheTest() {}
282 void SetUpInitialSync(const syncer::SyncDataList
& initial_image_data
,
283 const syncer::SyncDataList
& initial_tracking_data
);
285 size_t GetFaviconCount() const;
286 size_t GetTaskCount() const;
288 testing::AssertionResult
ExpectFaviconEquals(
289 const std::string
& page_url
,
290 const std::string
& bytes
) const;
291 testing::AssertionResult
VerifyLocalIcons(
292 const std::vector
<int>& expected_icons
);
293 testing::AssertionResult
VerifyLocalCustomIcons(
294 const std::vector
<TestFaviconData
>& expected_icons
);
296 scoped_ptr
<syncer::SyncChangeProcessor
> CreateAndPassProcessor();
297 scoped_ptr
<syncer::SyncErrorFactory
> CreateAndPassSyncErrorFactory();
299 FaviconCache
* cache() { return &cache_
; }
300 TestChangeProcessor
* processor() { return sync_processor_
.get(); }
302 // Finish an outstanding favicon load for the icon described in |test_data|.
303 void OnCustomFaviconDataAvailable(const TestFaviconData
& test_data
);
305 // Helper method to run the message loop after invoking
306 // OnReceivedSyncFavicon, which posts an internal task.
307 void TriggerSyncFaviconReceived(const GURL
& page_url
,
308 const GURL
& icon_url
,
309 const std::string
& icon_bytes
,
310 int64 last_visit_time_ms
);
313 base::MessageLoopForUI message_loop_
;
316 // Our dummy ChangeProcessor used to inspect changes pushed to Sync.
317 scoped_ptr
<TestChangeProcessor
> sync_processor_
;
318 scoped_ptr
<SyncChangeProcessorDelegate
> sync_processor_delegate_
;
321 SyncFaviconCacheTest::SyncFaviconCacheTest()
322 : cache_(NULL
, kMaxSyncFavicons
),
323 sync_processor_(new TestChangeProcessor
),
324 sync_processor_delegate_(new SyncChangeProcessorDelegate(
325 sync_processor_
.get())) {
328 void SyncFaviconCacheTest::SetUpInitialSync(
329 const syncer::SyncDataList
& initial_image_data
,
330 const syncer::SyncDataList
& initial_tracking_data
) {
331 cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES
,
333 CreateAndPassProcessor(),
334 CreateAndPassSyncErrorFactory());
335 ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
336 cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING
,
337 initial_tracking_data
,
338 CreateAndPassProcessor(),
339 CreateAndPassSyncErrorFactory());
340 ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
343 size_t SyncFaviconCacheTest::GetFaviconCount() const {
344 return cache_
.NumFaviconsForTest();
347 size_t SyncFaviconCacheTest::GetTaskCount() const {
348 return cache_
.NumTasksForTest();
351 testing::AssertionResult
SyncFaviconCacheTest::ExpectFaviconEquals(
352 const std::string
& page_url
,
353 const std::string
& bytes
) const {
355 scoped_refptr
<base::RefCountedMemory
> favicon
;
356 if (!cache_
.GetSyncedFaviconForPageURL(gurl
, &favicon
))
357 return testing::AssertionFailure() << "Favicon is missing.";
358 if (favicon
->size() != bytes
.size())
359 return testing::AssertionFailure() << "Favicon sizes don't match.";
360 for (size_t i
= 0; i
< favicon
->size(); ++i
) {
361 if (bytes
[i
] != *(favicon
->front() + i
))
362 return testing::AssertionFailure() << "Favicon data doesn't match.";
364 return testing::AssertionSuccess();
367 testing::AssertionResult
SyncFaviconCacheTest::VerifyLocalIcons(
368 const std::vector
<int>& expected_icons
) {
369 std::vector
<TestFaviconData
> expected_custom_icons
;
370 for (size_t i
= 0; i
< expected_icons
.size(); ++i
) {
371 expected_custom_icons
.push_back(BuildFaviconData(expected_icons
[i
]));
373 return VerifyLocalCustomIcons(expected_custom_icons
);
377 testing::AssertionResult
SyncFaviconCacheTest::VerifyLocalCustomIcons(
378 const std::vector
<TestFaviconData
>& expected_custom_icons
) {
379 syncer::SyncDataList image_data_list
=
380 cache()->GetAllSyncData(syncer::FAVICON_IMAGES
);
381 syncer::SyncDataList tracking_data_list
=
382 cache()->GetAllSyncData(syncer::FAVICON_TRACKING
);
383 if (expected_custom_icons
.size() > image_data_list
.size() ||
384 expected_custom_icons
.size() > tracking_data_list
.size())
385 return testing::AssertionFailure() << "Number of icons doesn't match.";
386 for (size_t i
= 0; i
< expected_custom_icons
.size(); ++i
) {
387 const TestFaviconData
& test_data
= expected_custom_icons
[i
];
388 // Find the test data in the data lists. Assume that both lists have the
389 // same ordering, which may not match the |expected_custom_icons| ordering.
390 bool found_match
= false;
391 for (size_t j
= 0; j
< image_data_list
.size(); ++j
) {
392 if (image_data_list
[j
].GetTitle() != test_data
.icon_url
.spec())
395 const sync_pb::FaviconImageSpecifics
& image_specifics
=
396 image_data_list
[j
].GetSpecifics().favicon_image();
397 sync_pb::FaviconImageSpecifics expected_image_specifics
;
398 FillImageSpecifics(test_data
, &expected_image_specifics
);
399 if (image_specifics
.SerializeAsString() !=
400 expected_image_specifics
.SerializeAsString()) {
401 return testing::AssertionFailure() << "Image data doesn't match.";
403 const sync_pb::FaviconTrackingSpecifics
& tracking_specifics
=
404 tracking_data_list
[j
].GetSpecifics().favicon_tracking();
405 sync_pb::FaviconTrackingSpecifics expected_tracking_specifics
;
406 FillTrackingSpecifics(test_data
, &expected_tracking_specifics
);
407 if (tracking_specifics
.SerializeAsString() !=
408 expected_tracking_specifics
.SerializeAsString()) {
409 return testing::AssertionFailure() << "Tracking data doesn't match.";
413 return testing::AssertionFailure() << "Could not find favicon.";
415 return testing::AssertionSuccess();
418 scoped_ptr
<syncer::SyncChangeProcessor
>
419 SyncFaviconCacheTest::CreateAndPassProcessor() {
420 return scoped_ptr
<syncer::SyncChangeProcessor
>(
421 new SyncChangeProcessorDelegate(sync_processor_
.get()));
424 scoped_ptr
<syncer::SyncErrorFactory
> SyncFaviconCacheTest::
425 CreateAndPassSyncErrorFactory() {
426 return scoped_ptr
<syncer::SyncErrorFactory
>(
427 new syncer::SyncErrorFactoryMock());
430 void SyncFaviconCacheTest::OnCustomFaviconDataAvailable(
431 const TestFaviconData
& test_data
) {
432 std::vector
<chrome::FaviconBitmapResult
> bitmap_results
;
433 if (!test_data
.image_16
.empty()) {
434 chrome::FaviconBitmapResult bitmap_result
;
435 bitmap_result
.icon_url
= test_data
.icon_url
;
436 bitmap_result
.pixel_size
.set_width(16);
437 bitmap_result
.pixel_size
.set_height(16);
438 base::RefCountedString
* temp_string
= new base::RefCountedString();
439 temp_string
->data() = test_data
.image_16
;
440 bitmap_result
.bitmap_data
= temp_string
;
441 bitmap_results
.push_back(bitmap_result
);
443 if (!test_data
.image_32
.empty()) {
444 chrome::FaviconBitmapResult bitmap_result
;
445 bitmap_result
.icon_url
= test_data
.icon_url
;
446 bitmap_result
.pixel_size
.set_width(32);
447 bitmap_result
.pixel_size
.set_height(32);
448 base::RefCountedString
* temp_string
= new base::RefCountedString();
449 temp_string
->data() = test_data
.image_32
;
450 bitmap_result
.bitmap_data
= temp_string
;
451 bitmap_results
.push_back(bitmap_result
);
453 if (!test_data
.image_64
.empty()) {
454 chrome::FaviconBitmapResult bitmap_result
;
455 bitmap_result
.icon_url
= test_data
.icon_url
;
456 bitmap_result
.pixel_size
.set_width(64);
457 bitmap_result
.pixel_size
.set_height(64);
458 base::RefCountedString
* temp_string
= new base::RefCountedString();
459 temp_string
->data() = test_data
.image_64
;
460 bitmap_result
.bitmap_data
= temp_string
;
461 bitmap_results
.push_back(bitmap_result
);
463 cache()->OnFaviconDataAvailable(test_data
.page_url
, bitmap_results
);
466 void SyncFaviconCacheTest::TriggerSyncFaviconReceived(
467 const GURL
& page_url
,
468 const GURL
& icon_url
,
469 const std::string
& icon_bytes
,
470 int64 last_visit_time_ms
) {
471 cache()->OnReceivedSyncFavicon(page_url
,
475 message_loop_
.RunUntilIdle();
478 // A freshly constructed cache should be empty.
479 TEST_F(SyncFaviconCacheTest
, Empty
) {
480 EXPECT_EQ(0U, GetFaviconCount());
483 TEST_F(SyncFaviconCacheTest
, ReceiveSyncFavicon
) {
484 std::string page_url
= "http://www.google.com";
485 std::string fav_url
= "http://www.google.com/favicon.ico";
486 std::string bytes
= "bytes";
487 EXPECT_EQ(0U, GetFaviconCount());
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
, ReceiveEmptySyncFavicon
) {
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 EXPECT_EQ(0U, GetFaviconCount());
498 TriggerSyncFaviconReceived(GURL(page_url
),
502 EXPECT_EQ(0U, GetFaviconCount());
503 EXPECT_FALSE(ExpectFaviconEquals(page_url
, std::string()));
505 // Then receive the actual favicon.
506 TriggerSyncFaviconReceived(GURL(page_url
), GURL(fav_url
), bytes
, 0);
507 EXPECT_EQ(1U, GetFaviconCount());
508 EXPECT_TRUE(ExpectFaviconEquals(page_url
, bytes
));
511 TEST_F(SyncFaviconCacheTest
, ReceiveUpdatedSyncFavicon
) {
512 std::string page_url
= "http://www.google.com";
513 std::string fav_url
= "http://www.google.com/favicon.ico";
514 std::string bytes
= "bytes";
515 std::string bytes2
= "bytes2";
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 // The cache should not update existing favicons from tab sync favicons
522 // (which can be reassociated several times).
523 TriggerSyncFaviconReceived(GURL(page_url
), GURL(fav_url
), bytes2
, 0);
524 EXPECT_EQ(1U, GetFaviconCount());
525 EXPECT_TRUE(ExpectFaviconEquals(page_url
, bytes
));
526 EXPECT_FALSE(ExpectFaviconEquals(page_url
, bytes2
));
529 TEST_F(SyncFaviconCacheTest
, MultipleMappings
) {
530 std::string page_url
= "http://www.google.com";
531 std::string page2_url
= "http://bla.google.com";
532 std::string fav_url
= "http://www.google.com/favicon.ico";
533 std::string bytes
= "bytes";
534 EXPECT_EQ(0U, GetFaviconCount());
535 TriggerSyncFaviconReceived(GURL(page_url
), GURL(fav_url
), bytes
, 0);
536 EXPECT_EQ(1U, GetFaviconCount());
537 EXPECT_TRUE(ExpectFaviconEquals(page_url
, bytes
));
539 // Map another page to the same favicon. They should share the same data.
540 TriggerSyncFaviconReceived(GURL(page2_url
), GURL(fav_url
), bytes
, 0);
541 EXPECT_EQ(1U, GetFaviconCount());
542 EXPECT_TRUE(ExpectFaviconEquals(page2_url
, bytes
));
545 TEST_F(SyncFaviconCacheTest
, SyncEmpty
) {
546 syncer::SyncMergeResult merge_result
=
547 cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES
,
548 syncer::SyncDataList(),
549 CreateAndPassProcessor(),
550 CreateAndPassSyncErrorFactory());
552 EXPECT_EQ(0U, cache()->GetAllSyncData(syncer::FAVICON_IMAGES
).size());
553 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
554 EXPECT_EQ(0, merge_result
.num_items_added());
555 EXPECT_EQ(0, merge_result
.num_items_modified());
556 EXPECT_EQ(0, merge_result
.num_items_deleted());
557 EXPECT_EQ(0, merge_result
.num_items_before_association());
558 EXPECT_EQ(0, merge_result
.num_items_after_association());
561 cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING
,
562 syncer::SyncDataList(),
563 CreateAndPassProcessor(),
564 CreateAndPassSyncErrorFactory());
566 EXPECT_EQ(0U, cache()->GetAllSyncData(syncer::FAVICON_TRACKING
).size());
567 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
568 EXPECT_EQ(0, merge_result
.num_items_added());
569 EXPECT_EQ(0, merge_result
.num_items_modified());
570 EXPECT_EQ(0, merge_result
.num_items_deleted());
571 EXPECT_EQ(0, merge_result
.num_items_before_association());
572 EXPECT_EQ(0, merge_result
.num_items_after_association());
575 // Setting up sync with existing local favicons should push those favicons into
577 TEST_F(SyncFaviconCacheTest
, SyncExistingLocal
) {
578 std::vector
<syncer::SyncChange::SyncChangeType
> expected_change_types
;
579 std::vector
<int> expected_icons
;
580 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
581 TestFaviconData favicon
= BuildFaviconData(i
);
582 TriggerSyncFaviconReceived(favicon
.page_url
,
586 expected_change_types
.push_back(syncer::SyncChange::ACTION_ADD
);
587 expected_icons
.push_back(i
);
590 syncer::SyncMergeResult merge_result
=
591 cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES
,
592 syncer::SyncDataList(),
593 CreateAndPassProcessor(),
594 CreateAndPassSyncErrorFactory());
595 EXPECT_EQ((unsigned long)kFaviconBatchSize
,
596 cache()->GetAllSyncData(syncer::FAVICON_IMAGES
).size());
597 syncer::SyncChangeList change_list
= processor()->GetAndResetChangeList();
598 EXPECT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES
,
599 expected_change_types
,
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 cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING
,
610 syncer::SyncDataList(),
611 CreateAndPassProcessor(),
612 CreateAndPassSyncErrorFactory());
613 EXPECT_EQ((unsigned long)kFaviconBatchSize
,
614 cache()->GetAllSyncData(syncer::FAVICON_TRACKING
).size());
615 change_list
= processor()->GetAndResetChangeList();
616 EXPECT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING
,
617 expected_change_types
,
620 EXPECT_EQ(0, merge_result
.num_items_added());
621 EXPECT_EQ(0, merge_result
.num_items_modified());
622 EXPECT_EQ(0, merge_result
.num_items_deleted());
623 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_before_association());
624 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_after_association());
627 // Setting up sync with existing sync data should load that data into the local
629 TEST_F(SyncFaviconCacheTest
, SyncExistingRemote
) {
630 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
631 std::vector
<int> expected_icons
;
632 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
633 expected_icons
.push_back(i
);
634 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
635 FillImageSpecifics(BuildFaviconData(i
),
636 image_specifics
.mutable_favicon_image());
637 initial_image_data
.push_back(
638 syncer::SyncData::CreateRemoteData(1,
641 FillTrackingSpecifics(BuildFaviconData(i
),
642 tracking_specifics
.mutable_favicon_tracking());
643 initial_tracking_data
.push_back(
644 syncer::SyncData::CreateRemoteData(1,
649 syncer::SyncMergeResult merge_result
=
650 cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES
,
652 CreateAndPassProcessor(),
653 CreateAndPassSyncErrorFactory());
654 EXPECT_EQ((unsigned long)kFaviconBatchSize
,
655 cache()->GetAllSyncData(syncer::FAVICON_IMAGES
).size());
656 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
657 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_added());
658 EXPECT_EQ(0, merge_result
.num_items_modified());
659 EXPECT_EQ(0, merge_result
.num_items_deleted());
660 EXPECT_EQ(0, merge_result
.num_items_before_association());
661 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_after_association());
664 cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING
,
665 initial_tracking_data
,
666 CreateAndPassProcessor(),
667 CreateAndPassSyncErrorFactory());
668 EXPECT_EQ((unsigned long)kFaviconBatchSize
,
669 cache()->GetAllSyncData(syncer::FAVICON_TRACKING
).size());
670 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
671 EXPECT_EQ(0, merge_result
.num_items_added());
672 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_modified());
673 EXPECT_EQ(0, merge_result
.num_items_deleted());
674 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_before_association());
675 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_after_association());
677 ASSERT_TRUE(VerifyLocalIcons(expected_icons
));
680 // Setting up sync with local data and sync data should merge the two image
681 // sets, with remote data having priority in case both exist.
682 TEST_F(SyncFaviconCacheTest
, SyncMergesImages
) {
683 // First go through and add local 16p favicons.
684 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
685 TestFaviconData favicon
= BuildFaviconData(i
);
686 TriggerSyncFaviconReceived(favicon
.page_url
,
692 // Then go through and create the initial sync data, which does not have 16p
693 // favicons for the first half, and has custom 16p favicons for the second.
694 std::vector
<syncer::SyncChange::SyncChangeType
> expected_change_types
;
695 std::vector
<int> expected_icons
;
696 std::vector
<TestFaviconData
> expected_data
;
697 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
698 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
699 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
700 TestFaviconData test_data
= BuildFaviconData(i
);
701 if (i
< kFaviconBatchSize
/2) {
702 test_data
.image_16
= std::string();
703 expected_icons
.push_back(i
);
704 expected_change_types
.push_back(syncer::SyncChange::ACTION_UPDATE
);
706 test_data
.image_16
+= "custom";
707 expected_data
.push_back(test_data
);
709 FillImageSpecifics(test_data
,
710 image_specifics
.mutable_favicon_image());
712 initial_image_data
.push_back(
713 syncer::SyncData::CreateRemoteData(1,
716 FillTrackingSpecifics(test_data
,
717 tracking_specifics
.mutable_favicon_tracking());
718 initial_tracking_data
.push_back(
719 syncer::SyncData::CreateRemoteData(1,
724 syncer::SyncMergeResult merge_result
=
725 cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES
,
727 CreateAndPassProcessor(),
728 CreateAndPassSyncErrorFactory());
729 EXPECT_EQ((unsigned long)kFaviconBatchSize
,
730 cache()->GetAllSyncData(syncer::FAVICON_IMAGES
).size());
731 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
732 EXPECT_EQ((unsigned long)kFaviconBatchSize
/2, changes
.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());
740 cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING
,
741 initial_tracking_data
,
742 CreateAndPassProcessor(),
743 CreateAndPassSyncErrorFactory());
744 EXPECT_EQ((unsigned long)kFaviconBatchSize
,
745 cache()->GetAllSyncData(syncer::FAVICON_TRACKING
).size());
746 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
747 EXPECT_EQ(0, merge_result
.num_items_added());
748 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_modified());
749 EXPECT_EQ(0, merge_result
.num_items_deleted());
750 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_before_association());
751 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_after_association());
753 ASSERT_TRUE(VerifyLocalIcons(expected_icons
));
754 ASSERT_TRUE(VerifyLocalCustomIcons(expected_data
));
755 ASSERT_TRUE(VerifyChanges(syncer::FAVICON_IMAGES
,
756 expected_change_types
,
761 // Setting up sync with local data and sync data should merge the two tracking
762 // sets, such that the visit time is the most recent.
763 TEST_F(SyncFaviconCacheTest
, SyncMergesTracking
) {
764 // First go through and add local 16p favicons.
765 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
766 TestFaviconData favicon
= BuildFaviconData(i
);
767 TriggerSyncFaviconReceived(favicon
.page_url
,
773 // Then go through and create the initial sync data, which for the first half
774 // the local has a newer visit, and for the second the remote does.
775 std::vector
<syncer::SyncChange::SyncChangeType
> expected_change_types
;
776 std::vector
<int> expected_icons
;
777 std::vector
<TestFaviconData
> expected_data
;
778 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
779 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
780 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
781 TestFaviconData test_data
= BuildFaviconData(i
);
782 if (i
< kFaviconBatchSize
/2) {
783 test_data
.last_visit_time
= i
-1;
784 expected_icons
.push_back(i
);
785 expected_change_types
.push_back(syncer::SyncChange::ACTION_UPDATE
);
787 test_data
.last_visit_time
= i
+1;
788 expected_data
.push_back(test_data
);
790 FillImageSpecifics(test_data
,
791 image_specifics
.mutable_favicon_image());
793 initial_image_data
.push_back(
794 syncer::SyncData::CreateRemoteData(1,
797 FillTrackingSpecifics(test_data
,
798 tracking_specifics
.mutable_favicon_tracking());
799 initial_tracking_data
.push_back(
800 syncer::SyncData::CreateRemoteData(1,
805 syncer::SyncMergeResult merge_result
=
806 cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES
,
808 CreateAndPassProcessor(),
809 CreateAndPassSyncErrorFactory());
810 EXPECT_EQ((unsigned long)kFaviconBatchSize
,
811 cache()->GetAllSyncData(syncer::FAVICON_IMAGES
).size());
812 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
813 EXPECT_EQ(0, merge_result
.num_items_added());
814 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_modified());
815 EXPECT_EQ(0, merge_result
.num_items_deleted());
816 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_before_association());
817 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_after_association());
820 cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING
,
821 initial_tracking_data
,
822 CreateAndPassProcessor(),
823 CreateAndPassSyncErrorFactory());
824 EXPECT_EQ((unsigned long)kFaviconBatchSize
,
825 cache()->GetAllSyncData(syncer::FAVICON_TRACKING
).size());
826 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
827 EXPECT_EQ((unsigned long)kFaviconBatchSize
/2, changes
.size());
828 EXPECT_EQ(0, merge_result
.num_items_added());
829 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_modified());
830 EXPECT_EQ(0, merge_result
.num_items_deleted());
831 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_before_association());
832 EXPECT_EQ(kFaviconBatchSize
, merge_result
.num_items_after_association());
834 ASSERT_TRUE(VerifyLocalIcons(expected_icons
));
835 ASSERT_TRUE(VerifyLocalCustomIcons(expected_data
));
836 ASSERT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING
,
837 expected_change_types
,
842 // Receiving old icons (missing image data) should result in pushing the new
843 // merged icons back to the remote syncer.
844 TEST_F(SyncFaviconCacheTest
, ReceiveStaleImages
) {
845 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
846 syncer::SyncChangeList stale_changes
;
847 std::vector
<int> expected_icons
;
848 std::vector
<syncer::SyncChange::SyncChangeType
> expected_change_types
;
849 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
850 expected_icons
.push_back(i
);
851 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
852 FillImageSpecifics(BuildFaviconData(i
),
853 image_specifics
.mutable_favicon_image());
854 initial_image_data
.push_back(
855 syncer::SyncData::CreateRemoteData(1,
858 expected_change_types
.push_back(syncer::SyncChange::ACTION_UPDATE
);
859 image_specifics
.mutable_favicon_image()->clear_favicon_web();
860 stale_changes
.push_back(
863 syncer::SyncChange::ACTION_UPDATE
,
864 syncer::SyncData::CreateRemoteData(1,
867 FillTrackingSpecifics(BuildFaviconData(i
),
868 tracking_specifics
.mutable_favicon_tracking());
869 initial_tracking_data
.push_back(
870 syncer::SyncData::CreateRemoteData(1,
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
,
888 // New icons should be added locally without pushing anything back to the
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(
903 syncer::SyncChange::ACTION_UPDATE
,
904 syncer::SyncData::CreateRemoteData(1,
907 image_specifics
.mutable_favicon_image()->mutable_favicon_web()->
908 mutable_favicon()->append("old");
909 initial_image_data
.push_back(
910 syncer::SyncData::CreateRemoteData(1,
913 FillTrackingSpecifics(BuildFaviconData(i
),
914 tracking_specifics
.mutable_favicon_tracking());
915 initial_tracking_data
.push_back(
916 syncer::SyncData::CreateRemoteData(1,
921 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
923 // Now receive the new icons as an update.
924 cache()->ProcessSyncChanges(FROM_HERE
, new_changes
);
925 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
926 ASSERT_TRUE(VerifyLocalIcons(expected_icons
));
929 // Recieving the same icons as the local data should have no effect.
930 TEST_F(SyncFaviconCacheTest
, ReceiveSameImages
) {
931 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
932 syncer::SyncChangeList same_changes
;
933 std::vector
<int> expected_icons
;
934 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
935 expected_icons
.push_back(i
);
936 TestFaviconData test_data
= BuildFaviconData(i
);
937 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
938 FillImageSpecifics(test_data
,
939 image_specifics
.mutable_favicon_image());
940 same_changes
.push_back(
943 syncer::SyncChange::ACTION_UPDATE
,
944 syncer::SyncData::CreateRemoteData(1,
947 initial_image_data
.push_back(
948 syncer::SyncData::CreateRemoteData(1,
951 FillTrackingSpecifics(BuildFaviconData(i
),
952 tracking_specifics
.mutable_favicon_tracking());
953 initial_tracking_data
.push_back(
954 syncer::SyncData::CreateRemoteData(1,
959 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
961 // Now receive the new icons as an update.
962 cache()->ProcessSyncChanges(FROM_HERE
, same_changes
);
963 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
964 ASSERT_TRUE(VerifyLocalIcons(expected_icons
));
967 // Receiving stale tracking (old visit times) should result in pushing back
968 // the newer visit times to the remote syncer.
969 TEST_F(SyncFaviconCacheTest
, ReceiveStaleTracking
) {
970 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
971 syncer::SyncChangeList stale_changes
;
972 std::vector
<int> expected_icons
;
973 std::vector
<syncer::SyncChange::SyncChangeType
> expected_change_types
;
974 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
975 expected_icons
.push_back(i
);
976 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
977 FillImageSpecifics(BuildFaviconData(i
),
978 image_specifics
.mutable_favicon_image());
979 initial_image_data
.push_back(
980 syncer::SyncData::CreateRemoteData(1,
983 expected_change_types
.push_back(syncer::SyncChange::ACTION_UPDATE
);
984 FillTrackingSpecifics(BuildFaviconData(i
),
985 tracking_specifics
.mutable_favicon_tracking());
986 initial_tracking_data
.push_back(
987 syncer::SyncData::CreateRemoteData(1,
990 tracking_specifics
.mutable_favicon_tracking()->set_last_visit_time_ms(-1);
991 stale_changes
.push_back(
994 syncer::SyncChange::ACTION_UPDATE
,
995 syncer::SyncData::CreateRemoteData(1,
1000 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
1002 // Now receive the same icons as an update, but with missing image data.
1003 cache()->ProcessSyncChanges(FROM_HERE
, stale_changes
);
1004 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1005 ASSERT_TRUE(VerifyLocalIcons(expected_icons
));
1006 ASSERT_EQ((unsigned long)kFaviconBatchSize
, changes
.size());
1007 ASSERT_TRUE(VerifyChanges(syncer::FAVICON_TRACKING
,
1008 expected_change_types
,
1013 // New tracking information should be added locally without pushing anything
1014 // back to the remote syncer.
1015 TEST_F(SyncFaviconCacheTest
, ReceiveNewTracking
) {
1016 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1017 syncer::SyncChangeList new_changes
;
1018 std::vector
<int> expected_icons
;
1019 // We start from one here so that we don't have to deal with a -1 visit time.
1020 for (int i
= 1; i
<= kFaviconBatchSize
; ++i
) {
1021 expected_icons
.push_back(i
);
1022 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
1023 FillImageSpecifics(BuildFaviconData(i
),
1024 image_specifics
.mutable_favicon_image());
1025 initial_image_data
.push_back(
1026 syncer::SyncData::CreateRemoteData(1,
1029 FillTrackingSpecifics(BuildFaviconData(i
),
1030 tracking_specifics
.mutable_favicon_tracking());
1031 new_changes
.push_back(
1034 syncer::SyncChange::ACTION_UPDATE
,
1035 syncer::SyncData::CreateRemoteData(1,
1038 tracking_specifics
.mutable_favicon_tracking()->set_last_visit_time_ms(i
-1);
1039 initial_tracking_data
.push_back(
1040 syncer::SyncData::CreateRemoteData(1,
1045 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
1047 // Now receive the new icons as an update.
1048 cache()->ProcessSyncChanges(FROM_HERE
, new_changes
);
1049 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
1050 ASSERT_TRUE(VerifyLocalIcons(expected_icons
));
1053 // Receiving the same tracking information as the local data should have no
1055 TEST_F(SyncFaviconCacheTest
, ReceiveSameTracking
) {
1056 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1057 syncer::SyncChangeList same_changes
;
1058 std::vector
<int> expected_icons
;
1059 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1060 expected_icons
.push_back(i
);
1061 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
1062 FillImageSpecifics(BuildFaviconData(i
),
1063 image_specifics
.mutable_favicon_image());
1064 initial_image_data
.push_back(
1065 syncer::SyncData::CreateRemoteData(1,
1068 FillTrackingSpecifics(BuildFaviconData(i
),
1069 tracking_specifics
.mutable_favicon_tracking());
1070 initial_tracking_data
.push_back(
1071 syncer::SyncData::CreateRemoteData(1,
1074 same_changes
.push_back(
1077 syncer::SyncChange::ACTION_UPDATE
,
1078 syncer::SyncData::CreateRemoteData(1,
1083 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
1085 // Now receive the new icons as an update.
1086 cache()->ProcessSyncChanges(FROM_HERE
, same_changes
);
1087 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
1088 ASSERT_TRUE(VerifyLocalIcons(expected_icons
));
1091 // Verify we can delete favicons after setting up sync.
1092 TEST_F(SyncFaviconCacheTest
, DeleteFavicons
) {
1093 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1094 syncer::SyncChangeList tracking_deletions
, image_deletions
;
1095 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1096 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
1097 FillImageSpecifics(BuildFaviconData(i
),
1098 image_specifics
.mutable_favicon_image());
1099 initial_image_data
.push_back(
1100 syncer::SyncData::CreateRemoteData(1,
1103 FillTrackingSpecifics(BuildFaviconData(i
),
1104 tracking_specifics
.mutable_favicon_tracking());
1105 initial_tracking_data
.push_back(
1106 syncer::SyncData::CreateRemoteData(1,
1109 tracking_deletions
.push_back(
1112 syncer::SyncChange::ACTION_DELETE
,
1113 syncer::SyncData::CreateRemoteData(1,
1116 image_deletions
.push_back(
1119 syncer::SyncChange::ACTION_DELETE
,
1120 syncer::SyncData::CreateRemoteData(1,
1125 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
1127 // Now receive the tracking deletions. Since we'll still have orphan data,
1128 // the favicon count should remain the same.
1129 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1130 cache()->ProcessSyncChanges(FROM_HERE
, tracking_deletions
);
1131 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
1132 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1134 // Once the image deletions arrive, the favicon count should be 0 again.
1135 cache()->ProcessSyncChanges(FROM_HERE
, image_deletions
);
1136 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
1137 EXPECT_EQ(0U, GetFaviconCount());
1140 // Ensure that MergeDataAndStartSyncing enforces the sync favicon limit by
1141 // dropping local icons.
1142 TEST_F(SyncFaviconCacheTest
, ExpireOnMergeData
) {
1143 std::vector
<int> expected_icons
;
1144 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1146 // Set up sync so it has the maximum number of favicons, while the local has
1147 // the same amount of different favicons.
1148 for (int i
= 0; i
< kMaxSyncFavicons
; ++i
) {
1149 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
1150 FillImageSpecifics(BuildFaviconData(i
),
1151 image_specifics
.mutable_favicon_image());
1152 initial_image_data
.push_back(
1153 syncer::SyncData::CreateRemoteData(1,
1156 FillTrackingSpecifics(BuildFaviconData(i
),
1157 tracking_specifics
.mutable_favicon_tracking());
1158 initial_tracking_data
.push_back(
1159 syncer::SyncData::CreateRemoteData(1,
1162 expected_icons
.push_back(i
);
1164 TestFaviconData favicon
= BuildFaviconData(i
+kMaxSyncFavicons
);
1165 TriggerSyncFaviconReceived(favicon
.page_url
,
1168 i
+kMaxSyncFavicons
);
1171 EXPECT_FALSE(VerifyLocalIcons(expected_icons
));
1173 syncer::SyncMergeResult merge_result
=
1174 cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES
,
1176 CreateAndPassProcessor(),
1177 CreateAndPassSyncErrorFactory());
1178 EXPECT_EQ((unsigned long)kMaxSyncFavicons
,
1179 cache()->GetAllSyncData(syncer::FAVICON_IMAGES
).size());
1180 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
1181 EXPECT_EQ(kMaxSyncFavicons
, merge_result
.num_items_added());
1182 EXPECT_EQ(0, merge_result
.num_items_modified());
1183 EXPECT_EQ(kMaxSyncFavicons
, merge_result
.num_items_deleted());
1184 EXPECT_EQ(kMaxSyncFavicons
, merge_result
.num_items_before_association());
1185 EXPECT_EQ(kMaxSyncFavicons
, merge_result
.num_items_after_association());
1188 cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING
,
1189 initial_tracking_data
,
1190 CreateAndPassProcessor(),
1191 CreateAndPassSyncErrorFactory());
1192 EXPECT_EQ((unsigned long)kMaxSyncFavicons
,
1193 cache()->GetAllSyncData(syncer::FAVICON_TRACKING
).size());
1194 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
1195 EXPECT_EQ(0, merge_result
.num_items_added());
1196 EXPECT_EQ(kMaxSyncFavicons
, merge_result
.num_items_modified());
1197 EXPECT_EQ(0, merge_result
.num_items_deleted());
1198 EXPECT_EQ(kMaxSyncFavicons
, merge_result
.num_items_before_association());
1199 EXPECT_EQ(kMaxSyncFavicons
, merge_result
.num_items_after_association());
1201 EXPECT_TRUE(VerifyLocalIcons(expected_icons
));
1204 // Receiving sync additions (via ProcessSyncChanges) should not trigger
1206 TEST_F(SyncFaviconCacheTest
, NoExpireOnProcessSyncChanges
) {
1207 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1208 syncer::SyncChangeList image_changes
, tracking_changes
;
1209 std::vector
<int> expected_icons
;
1210 for (int i
= 0; i
< kMaxSyncFavicons
; ++i
) {
1211 expected_icons
.push_back(i
);
1212 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
1213 FillImageSpecifics(BuildFaviconData(i
),
1214 image_specifics
.mutable_favicon_image());
1215 initial_image_data
.push_back(
1216 syncer::SyncData::CreateRemoteData(1,
1219 FillTrackingSpecifics(BuildFaviconData(i
),
1220 tracking_specifics
.mutable_favicon_tracking());
1221 initial_tracking_data
.push_back(
1222 syncer::SyncData::CreateRemoteData(1,
1225 // Set up new tracking specifics for the icons received at change time.
1226 expected_icons
.push_back(i
+ kMaxSyncFavicons
);
1227 FillImageSpecifics(BuildFaviconData(i
+ kMaxSyncFavicons
),
1228 image_specifics
.mutable_favicon_image());
1229 image_changes
.push_back(
1232 syncer::SyncChange::ACTION_ADD
,
1233 syncer::SyncData::CreateRemoteData(1,
1236 FillTrackingSpecifics(BuildFaviconData(i
+ kMaxSyncFavicons
),
1237 tracking_specifics
.mutable_favicon_tracking());
1238 tracking_changes
.push_back(
1241 syncer::SyncChange::ACTION_ADD
,
1242 syncer::SyncData::CreateRemoteData(1,
1247 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
1249 // Now receive the new icons as an update.
1250 EXPECT_EQ((unsigned long)kMaxSyncFavicons
, GetFaviconCount());
1251 cache()->ProcessSyncChanges(FROM_HERE
, image_changes
);
1252 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
1253 cache()->ProcessSyncChanges(FROM_HERE
, tracking_changes
);
1254 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
1255 EXPECT_TRUE(VerifyLocalIcons(expected_icons
));
1256 EXPECT_GT(GetFaviconCount(), (unsigned long)kMaxSyncFavicons
);
1259 // Test that visiting a new page triggers a favicon load and a sync addition.
1260 TEST_F(SyncFaviconCacheTest
, AddOnFaviconVisited
) {
1261 EXPECT_EQ(0U, GetFaviconCount());
1262 SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
1263 std::vector
<int> expected_icons
;
1265 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1266 expected_icons
.push_back(i
);
1267 TestFaviconData test_data
= BuildFaviconData(i
);
1268 cache()->OnFaviconVisited(test_data
.page_url
, test_data
.icon_url
);
1271 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetTaskCount());
1273 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1274 TestFaviconData test_data
= BuildFaviconData(i
);
1275 OnCustomFaviconDataAvailable(test_data
);
1277 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1278 ASSERT_EQ(2U, changes
.size());
1279 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, changes
[0].change_type());
1280 EXPECT_EQ(syncer::FAVICON_IMAGES
, changes
[0].sync_data().GetDataType());
1282 CompareFaviconDataToSpecifics(test_data
,
1283 changes
[0].sync_data().GetSpecifics()));
1284 EXPECT_EQ(syncer::FAVICON_TRACKING
, changes
[1].sync_data().GetDataType());
1285 // Just verify the favicon url for the tracking specifics and that the
1286 // timestamp is non-null.
1287 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, changes
[1].change_type());
1288 EXPECT_EQ(test_data
.icon_url
.spec(),
1289 changes
[1].sync_data().GetSpecifics().favicon_tracking().
1291 EXPECT_NE(changes
[1].sync_data().GetSpecifics().favicon_tracking().
1292 last_visit_time_ms(), 0);
1295 EXPECT_EQ(0U, GetTaskCount());
1296 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1299 // Test that visiting a known page does not trigger a favicon load and just
1300 // updates the sync tracking info.
1301 TEST_F(SyncFaviconCacheTest
, UpdateOnFaviconVisited
) {
1302 EXPECT_EQ(0U, GetFaviconCount());
1303 SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
1304 std::vector
<int> expected_icons
;
1306 // Add the favicons.
1307 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1308 expected_icons
.push_back(i
);
1309 TestFaviconData test_data
= BuildFaviconData(i
);
1310 cache()->OnFaviconVisited(test_data
.page_url
, test_data
.icon_url
);
1311 OnCustomFaviconDataAvailable(test_data
);
1313 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1315 // Visit the favicons again.
1316 EXPECT_EQ(0U, GetTaskCount());
1317 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1318 TestFaviconData test_data
= BuildFaviconData(i
);
1319 cache()->OnFaviconVisited(test_data
.page_url
, test_data
.icon_url
);
1321 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1322 ASSERT_EQ(1U, changes
.size());
1323 // Just verify the favicon url for the tracking specifics and that the
1324 // timestamp is non-null.
1325 EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE
, changes
[0].change_type());
1326 EXPECT_EQ(test_data
.icon_url
.spec(),
1327 changes
[0].sync_data().GetSpecifics().favicon_tracking().
1329 EXPECT_NE(changes
[0].sync_data().GetSpecifics().favicon_tracking().
1330 last_visit_time_ms(), 0);
1332 EXPECT_EQ(0U, GetTaskCount());
1333 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1336 // Ensure we properly expire old synced favicons as new ones are updated.
1337 TEST_F(SyncFaviconCacheTest
, ExpireOnFaviconVisited
) {
1338 EXPECT_EQ(0U, GetFaviconCount());
1339 SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
1340 std::vector
<int> expected_icons
;
1342 // Add the initial favicons.
1343 for (int i
= 0; i
< kMaxSyncFavicons
; ++i
) {
1344 expected_icons
.push_back(i
);
1345 TestFaviconData test_data
= BuildFaviconData(i
);
1346 cache()->OnFaviconVisited(test_data
.page_url
, test_data
.icon_url
);
1347 OnCustomFaviconDataAvailable(test_data
);
1349 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1351 // Visit some new favicons, triggering expirations of the old favicons.
1352 EXPECT_EQ(0U, GetTaskCount());
1353 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1354 TestFaviconData old_favicon
= BuildFaviconData(i
);
1355 TestFaviconData test_data
= BuildFaviconData(i
+ kMaxSyncFavicons
);
1356 cache()->OnFaviconVisited(test_data
.page_url
, test_data
.icon_url
);
1357 OnCustomFaviconDataAvailable(test_data
);
1359 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1360 ASSERT_EQ(4U, changes
.size());
1361 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, changes
[0].change_type());
1363 CompareFaviconDataToSpecifics(test_data
,
1364 changes
[0].sync_data().GetSpecifics()));
1365 EXPECT_EQ(syncer::SyncChange::ACTION_DELETE
, changes
[1].change_type());
1366 EXPECT_EQ(old_favicon
.icon_url
.spec(), changes
[1].sync_data().GetTag());
1368 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, changes
[2].change_type());
1369 EXPECT_EQ(test_data
.icon_url
.spec(),
1370 changes
[2].sync_data().GetSpecifics().favicon_tracking().
1372 EXPECT_NE(changes
[2].sync_data().GetSpecifics().favicon_tracking().
1373 last_visit_time_ms(), 0);
1374 EXPECT_EQ(syncer::SyncChange::ACTION_DELETE
, changes
[3].change_type());
1375 EXPECT_EQ(old_favicon
.icon_url
.spec(), changes
[3].sync_data().GetTag());
1378 EXPECT_EQ(0U, GetTaskCount());
1379 EXPECT_EQ((unsigned long)kMaxSyncFavicons
, GetFaviconCount());
1382 // A full history clear notification should result in all synced favicons being
1384 TEST_F(SyncFaviconCacheTest
, HistoryFullClear
) {
1385 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1386 std::vector
<int> expected_icons
;
1387 std::vector
<syncer::SyncChange::SyncChangeType
> expected_deletions
;
1388 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1389 expected_icons
.push_back(i
);
1390 expected_deletions
.push_back(syncer::SyncChange::ACTION_DELETE
);
1391 TestFaviconData test_data
= BuildFaviconData(i
);
1392 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
1393 FillImageSpecifics(test_data
,
1394 image_specifics
.mutable_favicon_image());
1395 initial_image_data
.push_back(
1396 syncer::SyncData::CreateRemoteData(1,
1399 FillTrackingSpecifics(BuildFaviconData(i
),
1400 tracking_specifics
.mutable_favicon_tracking());
1401 initial_tracking_data
.push_back(
1402 syncer::SyncData::CreateRemoteData(1,
1407 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
1408 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1409 EXPECT_TRUE(changes
.empty());
1411 history::URLsDeletedDetails deletions
;
1412 deletions
.all_history
= true;
1413 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1414 content::NotificationService::current()->Notify(
1415 chrome::NOTIFICATION_HISTORY_URLS_DELETED
,
1416 content::Source
<Profile
>(NULL
),
1417 content::Details
<history::URLsDeletedDetails
>(&deletions
));
1418 EXPECT_EQ(0U, GetFaviconCount());
1419 changes
= processor()->GetAndResetChangeList();
1420 ASSERT_EQ(changes
.size(), (unsigned long)kFaviconBatchSize
*2);
1421 syncer::SyncChangeList changes_1
, changes_2
;
1422 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1423 changes_1
.push_back(changes
[i
]);
1424 changes_2
.push_back(changes
[i
+ kFaviconBatchSize
]);
1426 VerifyChanges(syncer::FAVICON_IMAGES
,
1430 VerifyChanges(syncer::FAVICON_TRACKING
,
1436 // A partial history clear notification should result in the expired favicons
1437 // also being deleted from sync.
1438 TEST_F(SyncFaviconCacheTest
, HistorySubsetClear
) {
1439 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1440 std::vector
<int> expected_icons
;
1441 std::vector
<syncer::SyncChange::SyncChangeType
> expected_deletions
;
1442 history::URLsDeletedDetails deletions
;
1443 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1444 TestFaviconData test_data
= BuildFaviconData(i
);
1445 if (i
< kFaviconBatchSize
/2) {
1446 expected_icons
.push_back(i
);
1447 expected_deletions
.push_back(syncer::SyncChange::ACTION_DELETE
);
1448 deletions
.favicon_urls
.insert(test_data
.icon_url
);
1450 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
1451 FillImageSpecifics(test_data
,
1452 image_specifics
.mutable_favicon_image());
1453 initial_image_data
.push_back(
1454 syncer::SyncData::CreateRemoteData(1,
1457 FillTrackingSpecifics(BuildFaviconData(i
),
1458 tracking_specifics
.mutable_favicon_tracking());
1459 initial_tracking_data
.push_back(
1460 syncer::SyncData::CreateRemoteData(1,
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 content::NotificationService::current()->Notify(
1471 chrome::NOTIFICATION_HISTORY_URLS_DELETED
,
1472 content::Source
<Profile
>(NULL
),
1473 content::Details
<history::URLsDeletedDetails
>(&deletions
));
1474 EXPECT_EQ((unsigned long)kFaviconBatchSize
/2, GetFaviconCount());
1475 changes
= processor()->GetAndResetChangeList();
1476 ASSERT_EQ(changes
.size(), (unsigned long)kFaviconBatchSize
);
1477 syncer::SyncChangeList changes_1
, changes_2
;
1478 for (size_t i
= 0; i
< kFaviconBatchSize
/2; ++i
) {
1479 changes_1
.push_back(changes
[i
]);
1480 changes_2
.push_back(changes
[i
+ kFaviconBatchSize
/2]);
1482 VerifyChanges(syncer::FAVICON_IMAGES
,
1486 VerifyChanges(syncer::FAVICON_TRACKING
,
1492 // Any favicon urls with the "data" scheme should be ignored.
1493 TEST_F(SyncFaviconCacheTest
, IgnoreDataScheme
) {
1494 EXPECT_EQ(0U, GetFaviconCount());
1495 SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
1496 std::vector
<int> expected_icons
;
1498 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1499 TestFaviconData test_data
= BuildFaviconData(i
);
1500 cache()->OnFaviconVisited(test_data
.page_url
, GURL());
1503 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetTaskCount());
1505 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1506 TestFaviconData test_data
= BuildFaviconData(i
);
1507 test_data
.icon_url
= GURL("data:image/png;base64;blabla");
1508 EXPECT_TRUE(test_data
.icon_url
.is_valid());
1509 OnCustomFaviconDataAvailable(test_data
);
1512 EXPECT_EQ(0U, GetTaskCount());
1513 EXPECT_EQ(0U, GetFaviconCount());
1514 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1515 EXPECT_TRUE(changes
.empty());
1518 // When visiting a page we've already loaded the favicon for, don't attempt to
1519 // reload the favicon, just update the visit time using the cached icon url.
1520 TEST_F(SyncFaviconCacheTest
, ReuseCachedIconUrl
) {
1521 EXPECT_EQ(0U, GetFaviconCount());
1522 SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
1523 std::vector
<int> expected_icons
;
1525 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1526 expected_icons
.push_back(i
);
1527 TestFaviconData test_data
= BuildFaviconData(i
);
1528 cache()->OnFaviconVisited(test_data
.page_url
, test_data
.icon_url
);
1531 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetTaskCount());
1533 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1534 TestFaviconData test_data
= BuildFaviconData(i
);
1535 OnCustomFaviconDataAvailable(test_data
);
1537 processor()->GetAndResetChangeList();
1538 EXPECT_EQ(0U, GetTaskCount());
1539 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1541 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1542 TestFaviconData test_data
= BuildFaviconData(i
);
1543 cache()->OnFaviconVisited(test_data
.page_url
, test_data
.icon_url
);
1544 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1545 ASSERT_EQ(1U, changes
.size());
1546 // Just verify the favicon url for the tracking specifics and that the
1547 // timestamp is non-null.
1548 EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE
, changes
[0].change_type());
1549 EXPECT_EQ(test_data
.icon_url
.spec(),
1550 changes
[0].sync_data().GetSpecifics().favicon_tracking().
1552 EXPECT_NE(changes
[0].sync_data().GetSpecifics().favicon_tracking().
1553 last_visit_time_ms(), 0);
1555 EXPECT_EQ(0U, GetTaskCount());
1558 // If we wind up with orphan image/tracking nodes, then receive an update
1559 // for those favicons, we should lazily create the missing nodes.
1560 TEST_F(SyncFaviconCacheTest
, UpdatedOrphans
) {
1561 EXPECT_EQ(0U, GetFaviconCount());
1562 SetUpInitialSync(syncer::SyncDataList(), syncer::SyncDataList());
1564 syncer::SyncChangeList initial_image_changes
;
1565 syncer::SyncChangeList initial_tracking_changes
;
1566 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1567 TestFaviconData test_data
= BuildFaviconData(i
);
1568 // Even favicons have image data but no tracking data. Odd favicons have
1569 // tracking data but no image data.
1571 sync_pb::EntitySpecifics image_specifics
;
1572 FillImageSpecifics(BuildFaviconData(i
),
1573 image_specifics
.mutable_favicon_image());
1574 initial_image_changes
.push_back(
1575 syncer::SyncChange(FROM_HERE
,
1576 syncer::SyncChange::ACTION_ADD
,
1577 syncer::SyncData::CreateRemoteData(
1578 1, image_specifics
, base::Time())));
1580 sync_pb::EntitySpecifics tracking_specifics
;
1581 FillTrackingSpecifics(BuildFaviconData(i
),
1582 tracking_specifics
.mutable_favicon_tracking());
1583 initial_tracking_changes
.push_back(
1584 syncer::SyncChange(FROM_HERE
,
1585 syncer::SyncChange::ACTION_ADD
,
1586 syncer::SyncData::CreateRemoteData(
1587 1, tracking_specifics
, base::Time())));
1591 cache()->ProcessSyncChanges(FROM_HERE
, initial_image_changes
);
1592 cache()->ProcessSyncChanges(FROM_HERE
, initial_tracking_changes
);
1593 EXPECT_EQ(0U, processor()->GetAndResetChangeList().size());
1594 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1596 for (int i
= 0; i
< kFaviconBatchSize
/2; ++i
) {
1597 TestFaviconData test_data
= BuildFaviconData(i
);
1598 cache()->OnFaviconVisited(test_data
.page_url
, GURL());
1599 EXPECT_EQ(1U, GetTaskCount());
1600 OnCustomFaviconDataAvailable(test_data
);
1601 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1603 // Even favicons had image data, so should now receive new tracking data
1604 // and updated image data (we allow one update after the initial add).
1605 // Odd favicons had tracking so should now receive new image data and
1606 // updated tracking data.
1608 ASSERT_EQ(2U, changes
.size());
1609 EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE
, changes
[0].change_type());
1611 CompareFaviconDataToSpecifics(test_data
,
1612 changes
[0].sync_data().GetSpecifics()));
1613 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, changes
[1].change_type());
1614 EXPECT_EQ(test_data
.icon_url
.spec(),
1615 changes
[1].sync_data().GetSpecifics().favicon_tracking().
1617 EXPECT_NE(changes
[1].sync_data().GetSpecifics().favicon_tracking().
1618 last_visit_time_ms(), 0);
1620 ASSERT_EQ(2U, changes
.size());
1621 EXPECT_EQ(syncer::SyncChange::ACTION_ADD
, changes
[0].change_type());
1623 CompareFaviconDataToSpecifics(test_data
,
1624 changes
[0].sync_data().GetSpecifics()));
1625 EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE
, changes
[1].change_type());
1626 EXPECT_EQ(test_data
.icon_url
.spec(),
1627 changes
[1].sync_data().GetSpecifics().favicon_tracking().
1629 EXPECT_NE(changes
[1].sync_data().GetSpecifics().favicon_tracking().
1630 last_visit_time_ms(), 0);
1634 EXPECT_EQ(0U, GetTaskCount());
1635 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1638 // Verify that orphaned favicon images don't result in creating invalid
1639 // favicon tracking data.
1640 TEST_F(SyncFaviconCacheTest
, PartialAssociationInfo
) {
1641 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1642 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1643 sync_pb::EntitySpecifics image_specifics
;
1644 FillImageSpecifics(BuildFaviconData(i
),
1645 image_specifics
.mutable_favicon_image());
1646 initial_image_data
.push_back(
1647 syncer::SyncData::CreateRemoteData(1,
1650 image_specifics
.mutable_favicon_image()->clear_favicon_web();
1653 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
1654 syncer::SyncChangeList change_list
= processor()->GetAndResetChangeList();
1655 EXPECT_TRUE(change_list
.empty());
1656 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1659 // Tests that we don't choke if a favicon visit node with a null visit time is
1660 // present (see crbug.com/258196) and an update is made.
1661 TEST_F(SyncFaviconCacheTest
, NullFaviconVisitTime
) {
1662 EXPECT_EQ(0U, GetFaviconCount());
1664 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1665 std::vector
<int> expected_icons
;
1666 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1667 expected_icons
.push_back(i
);
1668 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
1669 FillImageSpecifics(BuildFaviconData(i
),
1670 image_specifics
.mutable_favicon_image());
1671 initial_image_data
.push_back(
1672 syncer::SyncData::CreateRemoteData(1,
1675 FillTrackingSpecifics(BuildFaviconData(i
),
1676 tracking_specifics
.mutable_favicon_tracking());
1677 tracking_specifics
.mutable_favicon_tracking()->set_last_visit_time_ms(
1678 syncer::TimeToProtoTime(base::Time()));
1679 initial_tracking_data
.push_back(
1680 syncer::SyncData::CreateRemoteData(1,
1685 cache()->MergeDataAndStartSyncing(syncer::FAVICON_IMAGES
,
1687 CreateAndPassProcessor(),
1688 CreateAndPassSyncErrorFactory());
1689 ASSERT_EQ(0U, processor()->GetAndResetChangeList().size());
1690 cache()->MergeDataAndStartSyncing(syncer::FAVICON_TRACKING
,
1691 initial_tracking_data
,
1692 CreateAndPassProcessor(),
1693 CreateAndPassSyncErrorFactory());
1694 ASSERT_EQ((unsigned long)kFaviconBatchSize
,
1695 processor()->GetAndResetChangeList().size());
1696 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1698 // Visit the favicons again.
1699 EXPECT_EQ(0U, GetTaskCount());
1700 for (int i
= 0; i
< kFaviconBatchSize
; ++i
) {
1701 TestFaviconData test_data
= BuildFaviconData(i
);
1702 cache()->OnFaviconVisited(test_data
.page_url
, test_data
.icon_url
);
1704 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1705 ASSERT_EQ(1U, changes
.size());
1706 // Just verify the favicon url for the tracking specifics and that the
1707 // timestamp is non-null.
1708 EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE
, changes
[0].change_type());
1709 EXPECT_EQ(test_data
.icon_url
.spec(),
1710 changes
[0].sync_data().GetSpecifics().favicon_tracking().
1712 EXPECT_NE(changes
[0].sync_data().GetSpecifics().favicon_tracking().
1713 last_visit_time_ms(), 0);
1715 EXPECT_EQ(0U, GetTaskCount());
1716 EXPECT_EQ((unsigned long)kFaviconBatchSize
, GetFaviconCount());
1719 // If another synced client has a clock skewed towards the future, it's possible
1720 // that favicons added locally will be expired as they are added. Ensure this
1721 // doesn't crash (see crbug.com/306150).
1722 TEST_F(SyncFaviconCacheTest
, VisitFaviconClockSkew
) {
1723 EXPECT_EQ(0U, GetFaviconCount());
1724 const int kClockSkew
= 20; // 20 minutes in the future.
1726 // Set up sync with kMaxSyncFavicons starting kClockSkew minutes in the
1728 syncer::SyncDataList initial_image_data
, initial_tracking_data
;
1729 for (int i
= 0; i
< kMaxSyncFavicons
; ++i
) {
1730 sync_pb::EntitySpecifics image_specifics
, tracking_specifics
;
1731 TestFaviconData test_data
= BuildFaviconData(i
);
1732 test_data
.last_visit_time
=
1733 syncer::TimeToProtoTime(
1734 base::Time::Now() + base::TimeDelta::FromMinutes(kClockSkew
));
1735 FillImageSpecifics(test_data
,
1736 image_specifics
.mutable_favicon_image());
1737 initial_image_data
.push_back(
1738 syncer::SyncData::CreateRemoteData(1,
1741 FillTrackingSpecifics(test_data
,
1742 tracking_specifics
.mutable_favicon_tracking());
1743 initial_tracking_data
.push_back(
1744 syncer::SyncData::CreateRemoteData(1,
1748 SetUpInitialSync(initial_image_data
, initial_tracking_data
);
1750 // Visit some new favicons with local time, which will be expired as they
1752 EXPECT_EQ(0U, GetTaskCount());
1753 for (int i
= 0; i
< kClockSkew
; ++i
) {
1754 TestFaviconData test_data
= BuildFaviconData(i
+ kMaxSyncFavicons
);
1755 cache()->OnFaviconVisited(test_data
.page_url
, test_data
.icon_url
);
1756 OnCustomFaviconDataAvailable(test_data
);
1758 // The changes will be an add followed by a delete for both the image and
1760 syncer::SyncChangeList changes
= processor()->GetAndResetChangeList();
1761 ASSERT_EQ(changes
.size(), 4U);
1762 ASSERT_EQ(changes
[0].change_type(), syncer::SyncChange::ACTION_ADD
);
1763 ASSERT_EQ(changes
[0].sync_data().GetDataType(), syncer::FAVICON_IMAGES
);
1764 ASSERT_EQ(changes
[1].change_type(), syncer::SyncChange::ACTION_DELETE
);
1765 ASSERT_EQ(changes
[1].sync_data().GetDataType(), syncer::FAVICON_IMAGES
);
1766 ASSERT_EQ(changes
[2].change_type(), syncer::SyncChange::ACTION_ADD
);
1767 ASSERT_EQ(changes
[2].sync_data().GetDataType(), syncer::FAVICON_TRACKING
);
1768 ASSERT_EQ(changes
[3].change_type(), syncer::SyncChange::ACTION_DELETE
);
1769 ASSERT_EQ(changes
[3].sync_data().GetDataType(), syncer::FAVICON_TRACKING
);
1771 EXPECT_EQ(0U, GetTaskCount());
1772 EXPECT_EQ((unsigned long)kMaxSyncFavicons
, GetFaviconCount());
1775 } // namespace browser_sync