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