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 "components/history/core/browser/history_backend_client.h" |
15 #include "components/history/core/browser/thumbnail_database.h" | 16 #include "components/history/core/browser/thumbnail_database.h" |
16 #include "components/history/core/test/database_test_utils.h" | 17 #include "components/history/core/test/database_test_utils.h" |
17 #include "sql/connection.h" | 18 #include "sql/connection.h" |
18 #include "sql/recovery.h" | 19 #include "sql/recovery.h" |
19 #include "sql/test/scoped_error_expecter.h" | 20 #include "sql/test/scoped_error_expecter.h" |
20 #include "sql/test/test_helpers.h" | 21 #include "sql/test/test_helpers.h" |
| 22 #include "testing/gmock/include/gmock/gmock.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
22 #include "third_party/sqlite/sqlite3.h" | 24 #include "third_party/sqlite/sqlite3.h" |
23 #include "url/gurl.h" | 25 #include "url/gurl.h" |
24 | 26 |
| 27 using testing::StrictMock; |
| 28 using testing::Return; |
| 29 |
25 namespace history { | 30 namespace history { |
26 | 31 |
27 namespace { | 32 namespace { |
28 | 33 |
29 // Blobs for the bitmap tests. These aren't real bitmaps. Golden | 34 // Blobs for the bitmap tests. These aren't real bitmaps. Golden |
30 // database files store the same blobs (see VersionN tests). | 35 // database files store the same blobs (see VersionN tests). |
31 const unsigned char kBlob1[] = | 36 const unsigned char kBlob1[] = |
32 "12346102356120394751634516591348710478123649165419234519234512349134"; | 37 "12346102356120394751634516591348710478123649165419234519234512349134"; |
33 const unsigned char kBlob2[] = | 38 const unsigned char kBlob2[] = |
34 "goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef"; | 39 "goiwuegrqrcomizqyzkjalitbahxfjytrqvpqeroicxmnlkhlzunacxaneviawrtxcywhgef"; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 } | 167 } |
163 | 168 |
164 bool CompareIconMappingIconUrl(const IconMapping& a, const IconMapping& b) { | 169 bool CompareIconMappingIconUrl(const IconMapping& a, const IconMapping& b) { |
165 return a.icon_url < b.icon_url; | 170 return a.icon_url < b.icon_url; |
166 } | 171 } |
167 | 172 |
168 void SortMappingsByIconUrl(std::vector<IconMapping>* mappings) { | 173 void SortMappingsByIconUrl(std::vector<IconMapping>* mappings) { |
169 std::sort(mappings->begin(), mappings->end(), &CompareIconMappingIconUrl); | 174 std::sort(mappings->begin(), mappings->end(), &CompareIconMappingIconUrl); |
170 } | 175 } |
171 | 176 |
| 177 class MockHistoryBackendClient : public HistoryBackendClient { |
| 178 public: |
| 179 // MOCK_METHOD0(~HistoryBackendClient, void()); |
| 180 MOCK_METHOD1(IsBookmarked, bool(const GURL& url)); |
| 181 MOCK_METHOD1(GetBookmarks, void(std::vector<URLAndTitle>* bookmarks)); |
| 182 MOCK_METHOD0(ShouldReportDatabaseError, bool()); |
| 183 MOCK_METHOD1(IsWebSafe, bool(const GURL& url)); |
| 184 |
| 185 #if defined(OS_ANDROID) |
| 186 MOCK_METHOD4(OnHistoryBackendInitialized, |
| 187 void(HistoryBackend* history_backend, |
| 188 HistoryDatabase* history_database, |
| 189 ThumbnailDatabase* thumbnail_database, |
| 190 const base::FilePath& history_dir)); |
| 191 MOCK_METHOD2(OnHistoryBackendDestroyed, |
| 192 void(HistoryBackend* history_backend, |
| 193 const base::FilePath& history_dir)); |
| 194 #endif // defined(OS_ANDROID) |
| 195 }; |
| 196 |
172 } // namespace | 197 } // namespace |
173 | 198 |
174 class ThumbnailDatabaseTest : public testing::Test { | 199 class ThumbnailDatabaseTest : public testing::Test { |
175 public: | 200 public: |
176 ThumbnailDatabaseTest() {} | 201 ThumbnailDatabaseTest() {} |
177 ~ThumbnailDatabaseTest() override {} | 202 ~ThumbnailDatabaseTest() override {} |
178 | 203 |
179 // Initialize a thumbnail database instance from the SQL file at | 204 // Initialize a thumbnail database instance from the SQL file at |
180 // |golden_path| in the "History/" subdirectory of test data. | 205 // |golden_path| in the "History/" subdirectory of test data. |
181 std::unique_ptr<ThumbnailDatabase> LoadFromGolden(const char* golden_path) { | 206 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); | 385 db.TouchOnDemandFavicon(url, end); |
361 | 386 |
362 base::Time last_updated; | 387 base::Time last_updated; |
363 base::Time last_requested; | 388 base::Time last_requested; |
364 EXPECT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, | 389 EXPECT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, |
365 nullptr, nullptr)); | 390 nullptr, nullptr)); |
366 EXPECT_EQ(start, last_updated); // Does not mess with last_updated. | 391 EXPECT_EQ(start, last_updated); // Does not mess with last_updated. |
367 EXPECT_EQ(base::Time(), last_requested); // No update. | 392 EXPECT_EQ(base::Time(), last_requested); // No update. |
368 } | 393 } |
369 | 394 |
| 395 TEST_F(ThumbnailDatabaseTest, ClearOldOnDemandFaviconsSuccess) { |
| 396 StrictMock<MockHistoryBackendClient> mock_client; |
| 397 ThumbnailDatabase db(&mock_client); |
| 398 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
| 399 db.BeginTransaction(); |
| 400 |
| 401 base::Time start; |
| 402 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
| 403 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
| 404 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
| 405 |
| 406 // Icon: old unused case (not bookmarked). |
| 407 GURL url("http://google.com"); |
| 408 EXPECT_CALL(mock_client, IsBookmarked(url)).WillOnce(Return(false)); |
| 409 favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); |
| 410 ASSERT_NE(0, icon); |
| 411 FaviconBitmapID bitmap = |
| 412 db.AddOnDemandFaviconBitmap(icon, favicon, start, gfx::Size()); |
| 413 ASSERT_NE(0, bitmap); |
| 414 ASSERT_NE(0, db.AddIconMapping(url, icon)); |
| 415 |
| 416 base::Time delete_older_than = start + base::TimeDelta::FromDays(7); |
| 417 db.ClearOldOnDemandFavicons(delete_older_than); |
| 418 |
| 419 // The icon gets deleted. |
| 420 EXPECT_FALSE(db.GetIconMappingsForPageURL(url, nullptr)); |
| 421 EXPECT_FALSE(db.GetFaviconHeader(icon, nullptr, nullptr)); |
| 422 EXPECT_FALSE(db.GetFaviconBitmaps(icon, nullptr)); |
| 423 } |
| 424 |
| 425 TEST_F(ThumbnailDatabaseTest, ClearOldOnDemandFaviconsDoesNotDeleteFreshOne) { |
| 426 StrictMock<MockHistoryBackendClient> mock_client; |
| 427 ThumbnailDatabase db(&mock_client); |
| 428 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
| 429 db.BeginTransaction(); |
| 430 |
| 431 base::Time start; |
| 432 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
| 433 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
| 434 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
| 435 |
| 436 // Icon: freshly used case. |
| 437 GURL url("http://google.com"); |
| 438 favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); |
| 439 ASSERT_NE(0, icon); |
| 440 FaviconBitmapID bitmap = |
| 441 db.AddOnDemandFaviconBitmap(icon, favicon, start, gfx::Size()); |
| 442 ASSERT_NE(0, bitmap); |
| 443 ASSERT_NE(0, db.AddIconMapping(url, icon)); |
| 444 |
| 445 // Touch the icon 3 weeks later. |
| 446 base::Time now = start + base::TimeDelta::FromDays(21); |
| 447 EXPECT_TRUE(db.TouchOnDemandFavicon(url, now)); |
| 448 |
| 449 base::Time delete_older_than = start + base::TimeDelta::FromDays(7); |
| 450 db.ClearOldOnDemandFavicons(delete_older_than); |
| 451 |
| 452 // Nothing gets deleted. |
| 453 EXPECT_TRUE(db.GetFaviconHeader(icon, nullptr, nullptr)); |
| 454 std::vector<FaviconBitmap> favicon_bitmaps; |
| 455 EXPECT_TRUE(db.GetFaviconBitmaps(icon, &favicon_bitmaps)); |
| 456 EXPECT_EQ(1u, favicon_bitmaps.size()); |
| 457 std::vector<IconMapping> icon_mapping; |
| 458 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping)); |
| 459 EXPECT_EQ(1u, icon_mapping.size()); |
| 460 EXPECT_EQ(icon, icon_mapping[0].icon_id); |
| 461 } |
| 462 |
| 463 TEST_F(ThumbnailDatabaseTest, ClearOldOnDemandFaviconsDoesNotDeleteBookmarked) { |
| 464 StrictMock<MockHistoryBackendClient> mock_client; |
| 465 ThumbnailDatabase db(&mock_client); |
| 466 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
| 467 db.BeginTransaction(); |
| 468 |
| 469 base::Time start; |
| 470 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
| 471 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
| 472 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
| 473 |
| 474 // Icon: unused but bookmarked case. |
| 475 GURL url("http://google.com"); |
| 476 EXPECT_CALL(mock_client, IsBookmarked(url)).WillOnce(Return(true)); |
| 477 favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); |
| 478 ASSERT_NE(0, icon); |
| 479 FaviconBitmapID bitmap = |
| 480 db.AddOnDemandFaviconBitmap(icon, favicon, start, gfx::Size()); |
| 481 ASSERT_NE(0, bitmap); |
| 482 ASSERT_NE(0, db.AddIconMapping(url, icon)); |
| 483 |
| 484 base::Time delete_older_than = start + base::TimeDelta::FromDays(7); |
| 485 db.ClearOldOnDemandFavicons(delete_older_than); |
| 486 |
| 487 // Nothing gets deleted. |
| 488 EXPECT_TRUE(db.GetFaviconHeader(icon, nullptr, nullptr)); |
| 489 std::vector<FaviconBitmap> favicon_bitmaps; |
| 490 EXPECT_TRUE(db.GetFaviconBitmaps(icon, &favicon_bitmaps)); |
| 491 EXPECT_EQ(1u, favicon_bitmaps.size()); |
| 492 std::vector<IconMapping> icon_mapping; |
| 493 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping)); |
| 494 EXPECT_EQ(1u, icon_mapping.size()); |
| 495 EXPECT_EQ(icon, icon_mapping[0].icon_id); |
| 496 } |
| 497 |
| 498 TEST_F(ThumbnailDatabaseTest, ClearOldOnDemandFaviconsDoesNotDeleteStandard) { |
| 499 StrictMock<MockHistoryBackendClient> mock_client; |
| 500 ThumbnailDatabase db(&mock_client); |
| 501 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
| 502 db.BeginTransaction(); |
| 503 |
| 504 base::Time start; |
| 505 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
| 506 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
| 507 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
| 508 |
| 509 // Icon: standard favicon (not on-demand). |
| 510 GURL url("http://google.com"); |
| 511 favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); |
| 512 ASSERT_NE(0, icon); |
| 513 FaviconBitmapID bitmap = |
| 514 db.AddFaviconBitmap(icon, favicon, start, gfx::Size()); |
| 515 ASSERT_NE(0, bitmap); |
| 516 ASSERT_NE(0, db.AddIconMapping(url, icon)); |
| 517 |
| 518 base::Time delete_older_than = start + base::TimeDelta::FromDays(7); |
| 519 db.ClearOldOnDemandFavicons(delete_older_than); |
| 520 |
| 521 // Nothing gets deleted. |
| 522 EXPECT_TRUE(db.GetFaviconHeader(icon, nullptr, nullptr)); |
| 523 std::vector<FaviconBitmap> favicon_bitmaps; |
| 524 EXPECT_TRUE(db.GetFaviconBitmaps(icon, &favicon_bitmaps)); |
| 525 EXPECT_EQ(1u, favicon_bitmaps.size()); |
| 526 std::vector<IconMapping> icon_mapping; |
| 527 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping)); |
| 528 EXPECT_EQ(1u, icon_mapping.size()); |
| 529 EXPECT_EQ(icon, icon_mapping[0].icon_id); |
| 530 } |
| 531 |
370 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { | 532 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { |
371 ThumbnailDatabase db(NULL); | 533 ThumbnailDatabase db(NULL); |
372 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | 534 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
373 db.BeginTransaction(); | 535 db.BeginTransaction(); |
374 | 536 |
375 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | 537 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
376 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | 538 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
377 | 539 |
378 GURL url("http://google.com"); | 540 GURL url("http://google.com"); |
379 favicon_base::FaviconID id = db.AddFavicon(url, favicon_base::TOUCH_ICON); | 541 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); | 1343 ThumbnailDatabase db(NULL); |
1182 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); | 1344 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); |
1183 | 1345 |
1184 // Verify that the resulting schema is correct, whether it | 1346 // Verify that the resulting schema is correct, whether it |
1185 // involved razing the file or fixing things in place. | 1347 // involved razing the file or fixing things in place. |
1186 VerifyTablesAndColumns(&db.db_); | 1348 VerifyTablesAndColumns(&db.db_); |
1187 } | 1349 } |
1188 } | 1350 } |
1189 | 1351 |
1190 } // namespace history | 1352 } // namespace history |
OLD | NEW |