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