OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stddef.h> | 5 #include <stddef.h> |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/files/file_enumerator.h" | 10 #include "base/files/file_enumerator.h" |
11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
12 #include "base/files/scoped_temp_dir.h" | 12 #include "base/files/scoped_temp_dir.h" |
13 #include "base/memory/ref_counted_memory.h" | 13 #include "base/memory/ref_counted_memory.h" |
14 #include "base/path_service.h" | 14 #include "base/path_service.h" |
15 #include "base/strings/stringprintf.h" | |
16 #include "build/build_config.h" | |
17 #include "components/history/core/browser/history_backend_client.h" | |
pkotwicz
2017/07/10 05:23:28
Do you need this include?
jkrcal
2017/07/10 16:14:30
Ah, correct. Thanks!
| |
15 #include "components/history/core/browser/thumbnail_database.h" | 18 #include "components/history/core/browser/thumbnail_database.h" |
16 #include "components/history/core/test/database_test_utils.h" | 19 #include "components/history/core/test/database_test_utils.h" |
17 #include "sql/connection.h" | 20 #include "sql/connection.h" |
18 #include "sql/recovery.h" | 21 #include "sql/recovery.h" |
19 #include "sql/test/scoped_error_expecter.h" | 22 #include "sql/test/scoped_error_expecter.h" |
20 #include "sql/test/test_helpers.h" | 23 #include "sql/test/test_helpers.h" |
24 #include "testing/gmock/include/gmock/gmock.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | 25 #include "testing/gtest/include/gtest/gtest.h" |
22 #include "third_party/sqlite/sqlite3.h" | 26 #include "third_party/sqlite/sqlite3.h" |
23 #include "url/gurl.h" | 27 #include "url/gurl.h" |
24 | 28 |
29 using testing::AllOf; | |
30 using testing::ElementsAre; | |
31 using testing::Field; | |
32 using testing::StrictMock; | |
pkotwicz
2017/07/10 05:23:28
Do you need this line?
jkrcal
2017/07/10 16:14:30
Done.
| |
33 using testing::Pair; | |
34 using testing::Return; | |
35 | |
25 namespace history { | 36 namespace history { |
26 | 37 |
27 namespace { | 38 namespace { |
28 | 39 |
29 // Blobs for the bitmap tests. These aren't real bitmaps. Golden | 40 // Blobs for the bitmap tests. These aren't real bitmaps. Golden |
30 // database files store the same blobs (see VersionN tests). | 41 // database files store the same blobs (see VersionN tests). |
31 const unsigned char kBlob1[] = | 42 const unsigned char kBlob1[] = |
32 "12346102356120394751634516591348710478123649165419234519234512349134"; | 43 "12346102356120394751634516591348710478123649165419234519234512349134"; |
33 const unsigned char kBlob2[] = | 44 const unsigned char kBlob2[] = |
34 "goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef"; | 45 "goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef"; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 } | 173 } |
163 | 174 |
164 bool CompareIconMappingIconUrl(const IconMapping& a, const IconMapping& b) { | 175 bool CompareIconMappingIconUrl(const IconMapping& a, const IconMapping& b) { |
165 return a.icon_url < b.icon_url; | 176 return a.icon_url < b.icon_url; |
166 } | 177 } |
167 | 178 |
168 void SortMappingsByIconUrl(std::vector<IconMapping>* mappings) { | 179 void SortMappingsByIconUrl(std::vector<IconMapping>* mappings) { |
169 std::sort(mappings->begin(), mappings->end(), &CompareIconMappingIconUrl); | 180 std::sort(mappings->begin(), mappings->end(), &CompareIconMappingIconUrl); |
170 } | 181 } |
171 | 182 |
183 class MockHistoryBackendClient : public HistoryBackendClient { | |
184 public: | |
185 // MOCK_METHOD0(~HistoryBackendClient, void()); | |
186 MOCK_METHOD1(IsBookmarked, bool(const GURL& url)); | |
187 MOCK_METHOD1(GetBookmarks, void(std::vector<URLAndTitle>* bookmarks)); | |
188 MOCK_METHOD0(ShouldReportDatabaseError, bool()); | |
189 MOCK_METHOD1(IsWebSafe, bool(const GURL& url)); | |
190 | |
191 #if defined(OS_ANDROID) | |
192 MOCK_METHOD4(OnHistoryBackendInitialized, | |
193 void(HistoryBackend* history_backend, | |
194 HistoryDatabase* history_database, | |
195 ThumbnailDatabase* thumbnail_database, | |
196 const base::FilePath& history_dir)); | |
197 MOCK_METHOD2(OnHistoryBackendDestroyed, | |
198 void(HistoryBackend* history_backend, | |
199 const base::FilePath& history_dir)); | |
200 #endif // defined(OS_ANDROID) | |
201 }; | |
202 | |
172 } // namespace | 203 } // namespace |
173 | 204 |
174 class ThumbnailDatabaseTest : public testing::Test { | 205 class ThumbnailDatabaseTest : public testing::Test { |
175 public: | 206 public: |
176 ThumbnailDatabaseTest() {} | 207 ThumbnailDatabaseTest() {} |
177 ~ThumbnailDatabaseTest() override {} | 208 ~ThumbnailDatabaseTest() override {} |
178 | 209 |
179 // Initialize a thumbnail database instance from the SQL file at | 210 // Initialize a thumbnail database instance from the SQL file at |
180 // |golden_path| in the "History/" subdirectory of test data. | 211 // |golden_path| in the "History/" subdirectory of test data. |
181 std::unique_ptr<ThumbnailDatabase> LoadFromGolden(const char* golden_path) { | 212 std::unique_ptr<ThumbnailDatabase> LoadFromGolden(const char* golden_path) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
360 db.TouchOnDemandFavicon(url, end); | 391 db.TouchOnDemandFavicon(url, end); |
361 | 392 |
362 base::Time last_updated; | 393 base::Time last_updated; |
363 base::Time last_requested; | 394 base::Time last_requested; |
364 EXPECT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, | 395 EXPECT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, |
365 nullptr, nullptr)); | 396 nullptr, nullptr)); |
366 EXPECT_EQ(start, last_updated); // Does not mess with last_updated. | 397 EXPECT_EQ(start, last_updated); // Does not mess with last_updated. |
367 EXPECT_EQ(base::Time(), last_requested); // No update. | 398 EXPECT_EQ(base::Time(), last_requested); // No update. |
368 } | 399 } |
369 | 400 |
401 // Test that ThumbnailDatabase::GetOldOnDemandFavicons() returns on-demand icons | |
402 // which were requested prior to the passed in timestamp. | |
403 TEST_F(ThumbnailDatabaseTest, GetOldOnDemandFaviconsReturnsOld) { | |
404 ThumbnailDatabase db(nullptr); | |
405 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | |
406 db.BeginTransaction(); | |
407 | |
408 base::Time start; | |
409 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); | |
410 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | |
411 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | |
412 | |
413 // Icon: old unused case. | |
pkotwicz
2017/07/10 05:23:28
You don't need the comment here because you have a
jkrcal
2017/07/10 16:14:30
Done.
| |
414 GURL url("http://google.com/favicon.ico"); | |
415 favicon_base::FaviconID icon = | |
416 db.AddFavicon(url, favicon_base::FAVICON, favicon, | |
417 FaviconBitmapType::ON_DEMAND, start, gfx::Size()); | |
418 ASSERT_NE(0, icon); | |
419 // Associate two different URLs with the icon. | |
420 GURL page_url1("http://google.com/1"); | |
421 ASSERT_NE(0, db.AddIconMapping(page_url1, icon)); | |
422 GURL page_url2("http://google.com/2"); | |
423 ASSERT_NE(0, db.AddIconMapping(page_url2, icon)); | |
424 | |
425 base::Time get_older_than = start + base::TimeDelta::FromSeconds(1); | |
426 auto map = db.GetOldOnDemandFavicons(get_older_than); | |
427 | |
428 // The icon is returned. | |
429 EXPECT_THAT(map, ElementsAre(Pair( | |
430 icon, AllOf(Field(&FaviconURLs::icon_url, url), | |
431 Field(&FaviconURLs::page_urls, | |
432 ElementsAre(page_url1, page_url2)))))); | |
433 } | |
434 | |
435 // Test that ThumbnailDatabase::GetOldOnDemandFavicons() returns on-visit icons | |
436 // if the on-visit icons have expired. We need this behavior in order to delete | |
437 // icons stored via HistoryService::SetOnDemandFavicons() prior to on-demand | |
438 // icons setting the "last_requested" time. | |
439 TEST_F(ThumbnailDatabaseTest, GetOldOnDemandFaviconsReturnsExpired) { | |
440 ThumbnailDatabase db(nullptr); | |
441 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | |
442 db.BeginTransaction(); | |
443 | |
444 base::Time start; | |
445 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); | |
446 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | |
447 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | |
448 | |
449 // Icon: standard favicon (not on-demand) but expired. | |
450 GURL url("http://google.com/favicon.ico"); | |
451 favicon_base::FaviconID icon = | |
452 db.AddFavicon(url, favicon_base::FAVICON, favicon, | |
453 FaviconBitmapType::ON_VISIT, start, gfx::Size()); | |
454 ASSERT_NE(0, icon); | |
455 GURL page_url("http://google.com/"); | |
456 ASSERT_NE(0, db.AddIconMapping(page_url, icon)); | |
457 ASSERT_TRUE(db.SetFaviconOutOfDate(icon)); | |
458 | |
459 // The threshold is ignored for expired icons. | |
460 auto map = db.GetOldOnDemandFavicons(/*threshold=*/base::Time::Now()); | |
461 | |
462 // The icon is returned. | |
463 EXPECT_THAT(map, | |
464 ElementsAre(Pair(icon, AllOf(Field(&FaviconURLs::icon_url, url), | |
465 Field(&FaviconURLs::page_urls, | |
466 ElementsAre(page_url)))))); | |
467 } | |
468 | |
469 // Test that ThumbnailDatabase::GetOldOnDemandFavicons() does not return | |
470 // on-demand icons which were requested after to the passed in timestamp. | |
pkotwicz
2017/07/10 05:23:28
Nit: "after to the" -> "after the"
jkrcal
2017/07/10 16:14:30
Done.
(sorry for not proof-reading your previous p
| |
471 TEST_F(ThumbnailDatabaseTest, GetOldOnDemandFaviconsDoesNotReturnFresh) { | |
472 ThumbnailDatabase db(nullptr); | |
473 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | |
474 db.BeginTransaction(); | |
475 | |
476 base::Time start; | |
477 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); | |
478 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | |
479 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | |
480 | |
481 // Icon: freshly used case. | |
482 GURL url("http://google.com/favicon.ico"); | |
483 favicon_base::FaviconID icon = | |
484 db.AddFavicon(url, favicon_base::FAVICON, favicon, | |
485 FaviconBitmapType::ON_DEMAND, start, gfx::Size()); | |
486 ASSERT_NE(0, icon); | |
487 ASSERT_NE(0, db.AddIconMapping(GURL("http://google.com/"), icon)); | |
488 | |
489 // Touch the icon 3 weeks later. | |
490 base::Time now = start + base::TimeDelta::FromDays(21); | |
491 EXPECT_TRUE(db.TouchOnDemandFavicon(url, now)); | |
492 | |
493 base::Time get_older_than = start + base::TimeDelta::FromSeconds(1); | |
494 auto list = db.GetOldOnDemandFavicons(get_older_than); | |
495 | |
496 // No icon is returned. | |
497 EXPECT_TRUE(list.empty()); | |
498 } | |
499 | |
500 // Test that ThumbnailDatabase::GetOldOnDemandFavicons() does not return | |
501 // non-expired on-visit icons. | |
502 TEST_F(ThumbnailDatabaseTest, GetOldOnDemandFaviconsDoesNotDeleteStandard) { | |
503 ThumbnailDatabase db(nullptr); | |
504 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | |
505 db.BeginTransaction(); | |
506 | |
507 base::Time start; | |
508 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); | |
509 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | |
510 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | |
511 | |
512 // Icon: standard favicon (not on-demand). | |
513 favicon_base::FaviconID icon = db.AddFavicon( | |
514 GURL("http://google.com/favicon.ico"), favicon_base::FAVICON, favicon, | |
515 FaviconBitmapType::ON_VISIT, start, gfx::Size()); | |
516 ASSERT_NE(0, icon); | |
517 ASSERT_NE(0, db.AddIconMapping(GURL("http://google.com/"), icon)); | |
518 | |
519 base::Time get_older_than = start + base::TimeDelta::FromSeconds(1); | |
520 auto list = db.GetOldOnDemandFavicons(get_older_than); | |
521 | |
522 // No icon is returned. | |
523 EXPECT_TRUE(list.empty()); | |
524 } | |
525 | |
370 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { | 526 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { |
371 ThumbnailDatabase db(NULL); | 527 ThumbnailDatabase db(NULL); |
372 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | 528 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
373 db.BeginTransaction(); | 529 db.BeginTransaction(); |
374 | 530 |
375 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | 531 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
376 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | 532 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
377 | 533 |
378 GURL url("http://google.com"); | 534 GURL url("http://google.com"); |
379 favicon_base::FaviconID id = db.AddFavicon(url, favicon_base::TOUCH_ICON); | 535 favicon_base::FaviconID id = db.AddFavicon(url, favicon_base::TOUCH_ICON); |
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1181 ThumbnailDatabase db(NULL); | 1337 ThumbnailDatabase db(NULL); |
1182 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); | 1338 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); |
1183 | 1339 |
1184 // Verify that the resulting schema is correct, whether it | 1340 // Verify that the resulting schema is correct, whether it |
1185 // involved razing the file or fixing things in place. | 1341 // involved razing the file or fixing things in place. |
1186 VerifyTablesAndColumns(&db.db_); | 1342 VerifyTablesAndColumns(&db.db_); |
1187 } | 1343 } |
1188 } | 1344 } |
1189 | 1345 |
1190 } // namespace history | 1346 } // namespace history |
OLD | NEW |