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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 } | 166 } |
162 | 167 |
163 bool CompareIconMappingIconUrl(const IconMapping& a, const IconMapping& b) { | 168 bool CompareIconMappingIconUrl(const IconMapping& a, const IconMapping& b) { |
164 return a.icon_url < b.icon_url; | 169 return a.icon_url < b.icon_url; |
165 } | 170 } |
166 | 171 |
167 void SortMappingsByIconUrl(std::vector<IconMapping>* mappings) { | 172 void SortMappingsByIconUrl(std::vector<IconMapping>* mappings) { |
168 std::sort(mappings->begin(), mappings->end(), &CompareIconMappingIconUrl); | 173 std::sort(mappings->begin(), mappings->end(), &CompareIconMappingIconUrl); |
169 } | 174 } |
170 | 175 |
| 176 class MockHistoryBackendClient : public HistoryBackendClient { |
| 177 public: |
| 178 // MOCK_METHOD0(~HistoryBackendClient, void()); |
| 179 MOCK_METHOD1(IsBookmarked, bool(const GURL& url)); |
| 180 MOCK_METHOD1(GetBookmarks, void(std::vector<URLAndTitle>* bookmarks)); |
| 181 MOCK_METHOD0(ShouldReportDatabaseError, bool()); |
| 182 MOCK_METHOD1(IsWebSafe, bool(const GURL& url)); |
| 183 |
| 184 #if defined(OS_ANDROID) |
| 185 MOCK_METHOD4(OnHistoryBackendInitialized, |
| 186 void(HistoryBackend* history_backend, |
| 187 HistoryDatabase* history_database, |
| 188 ThumbnailDatabase* thumbnail_database, |
| 189 const base::FilePath& history_dir)); |
| 190 MOCK_METHOD2(OnHistoryBackendDestroyed, |
| 191 void(HistoryBackend* history_backend, |
| 192 const base::FilePath& history_dir)); |
| 193 #endif // defined(OS_ANDROID) |
| 194 }; |
| 195 |
171 } // namespace | 196 } // namespace |
172 | 197 |
173 class ThumbnailDatabaseTest : public testing::Test { | 198 class ThumbnailDatabaseTest : public testing::Test { |
174 public: | 199 public: |
175 ThumbnailDatabaseTest() {} | 200 ThumbnailDatabaseTest() {} |
176 ~ThumbnailDatabaseTest() override {} | 201 ~ThumbnailDatabaseTest() override {} |
177 | 202 |
178 // Initialize a thumbnail database instance from the SQL file at | 203 // Initialize a thumbnail database instance from the SQL file at |
179 // |golden_path| in the "History/" subdirectory of test data. | 204 // |golden_path| in the "History/" subdirectory of test data. |
180 std::unique_ptr<ThumbnailDatabase> LoadFromGolden(const char* golden_path) { | 205 std::unique_ptr<ThumbnailDatabase> LoadFromGolden(const char* golden_path) { |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 db.TouchOnDemandFavicon(url, end); | 379 db.TouchOnDemandFavicon(url, end); |
355 | 380 |
356 base::Time last_updated; | 381 base::Time last_updated; |
357 base::Time last_requested; | 382 base::Time last_requested; |
358 EXPECT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, | 383 EXPECT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, |
359 nullptr, nullptr)); | 384 nullptr, nullptr)); |
360 EXPECT_EQ(start, last_updated); // Does not mess up with last_updates. | 385 EXPECT_EQ(start, last_updated); // Does not mess up with last_updates. |
361 EXPECT_EQ(base::Time(), last_requested); // No update. | 386 EXPECT_EQ(base::Time(), last_requested); // No update. |
362 } | 387 } |
363 | 388 |
| 389 TEST_F(ThumbnailDatabaseTest, ClearOldOnDemandFaviconsSuccess) { |
| 390 StrictMock<MockHistoryBackendClient> mock_client; |
| 391 ThumbnailDatabase db(&mock_client); |
| 392 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
| 393 db.BeginTransaction(); |
| 394 |
| 395 base::Time start; |
| 396 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
| 397 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
| 398 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
| 399 |
| 400 // Icon: old unused case (not bookmarked). |
| 401 GURL url("http://google.com"); |
| 402 EXPECT_CALL(mock_client, IsBookmarked(url)).WillOnce(Return(false)); |
| 403 favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); |
| 404 ASSERT_NE(0, icon); |
| 405 FaviconBitmapID bitmap = |
| 406 db.AddOnDemandFaviconBitmap(icon, favicon, start, gfx::Size()); |
| 407 ASSERT_NE(0, bitmap); |
| 408 ASSERT_NE(0, db.AddIconMapping(url, icon)); |
| 409 |
| 410 base::Time delete_older_than = start + base::TimeDelta::FromDays(7); |
| 411 db.ClearOldOnDemandFavicons(delete_older_than); |
| 412 |
| 413 // The icon gets deleted. |
| 414 EXPECT_FALSE(db.GetIconMappingsForPageURL(url, nullptr)); |
| 415 EXPECT_FALSE(db.GetFaviconHeader(icon, nullptr, nullptr)); |
| 416 EXPECT_FALSE(db.GetFaviconBitmaps(icon, nullptr)); |
| 417 } |
| 418 |
| 419 TEST_F(ThumbnailDatabaseTest, ClearOldOnDemandFaviconsDoesNotDeleteFreshOne) { |
| 420 StrictMock<MockHistoryBackendClient> mock_client; |
| 421 ThumbnailDatabase db(&mock_client); |
| 422 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
| 423 db.BeginTransaction(); |
| 424 |
| 425 base::Time start; |
| 426 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
| 427 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
| 428 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
| 429 |
| 430 // Icon: freshly used case. |
| 431 GURL url("http://google.com"); |
| 432 favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); |
| 433 ASSERT_NE(0, icon); |
| 434 FaviconBitmapID bitmap = |
| 435 db.AddOnDemandFaviconBitmap(icon, favicon, start, gfx::Size()); |
| 436 ASSERT_NE(0, bitmap); |
| 437 ASSERT_NE(0, db.AddIconMapping(url, icon)); |
| 438 |
| 439 // Touch the icon 3 weeks later. |
| 440 base::Time now = start + base::TimeDelta::FromDays(21); |
| 441 EXPECT_TRUE(db.TouchOnDemandFavicon(url, now)); |
| 442 |
| 443 base::Time delete_older_than = start + base::TimeDelta::FromDays(7); |
| 444 db.ClearOldOnDemandFavicons(delete_older_than); |
| 445 |
| 446 // Nothing gets deleted. |
| 447 EXPECT_TRUE(db.GetFaviconHeader(icon, nullptr, nullptr)); |
| 448 std::vector<FaviconBitmap> favicon_bitmaps; |
| 449 EXPECT_TRUE(db.GetFaviconBitmaps(icon, &favicon_bitmaps)); |
| 450 EXPECT_EQ(1u, favicon_bitmaps.size()); |
| 451 std::vector<IconMapping> icon_mapping; |
| 452 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping)); |
| 453 EXPECT_EQ(1u, icon_mapping.size()); |
| 454 EXPECT_EQ(icon, icon_mapping[0].icon_id); |
| 455 } |
| 456 |
| 457 TEST_F(ThumbnailDatabaseTest, ClearOldOnDemandFaviconsDoesNotDeleteBookmarked) { |
| 458 StrictMock<MockHistoryBackendClient> mock_client; |
| 459 ThumbnailDatabase db(&mock_client); |
| 460 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
| 461 db.BeginTransaction(); |
| 462 |
| 463 base::Time start; |
| 464 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
| 465 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
| 466 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
| 467 |
| 468 // Icon: unused but bookmarked case. |
| 469 GURL url("http://google.com"); |
| 470 EXPECT_CALL(mock_client, IsBookmarked(url)).WillOnce(Return(true)); |
| 471 favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); |
| 472 ASSERT_NE(0, icon); |
| 473 FaviconBitmapID bitmap = |
| 474 db.AddOnDemandFaviconBitmap(icon, favicon, start, gfx::Size()); |
| 475 ASSERT_NE(0, bitmap); |
| 476 ASSERT_NE(0, db.AddIconMapping(url, icon)); |
| 477 |
| 478 base::Time delete_older_than = start + base::TimeDelta::FromDays(7); |
| 479 db.ClearOldOnDemandFavicons(delete_older_than); |
| 480 |
| 481 // Nothing gets deleted. |
| 482 EXPECT_TRUE(db.GetFaviconHeader(icon, nullptr, nullptr)); |
| 483 std::vector<FaviconBitmap> favicon_bitmaps; |
| 484 EXPECT_TRUE(db.GetFaviconBitmaps(icon, &favicon_bitmaps)); |
| 485 EXPECT_EQ(1u, favicon_bitmaps.size()); |
| 486 std::vector<IconMapping> icon_mapping; |
| 487 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping)); |
| 488 EXPECT_EQ(1u, icon_mapping.size()); |
| 489 EXPECT_EQ(icon, icon_mapping[0].icon_id); |
| 490 } |
| 491 |
| 492 TEST_F(ThumbnailDatabaseTest, ClearOldOnDemandFaviconsDoesNotDeleteStandard) { |
| 493 StrictMock<MockHistoryBackendClient> mock_client; |
| 494 ThumbnailDatabase db(&mock_client); |
| 495 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
| 496 db.BeginTransaction(); |
| 497 |
| 498 base::Time start; |
| 499 ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); |
| 500 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
| 501 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
| 502 |
| 503 // Icon: standard favicon (not on-demand). |
| 504 GURL url("http://google.com"); |
| 505 favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); |
| 506 ASSERT_NE(0, icon); |
| 507 FaviconBitmapID bitmap = |
| 508 db.AddFaviconBitmap(icon, favicon, start, gfx::Size()); |
| 509 ASSERT_NE(0, bitmap); |
| 510 ASSERT_NE(0, db.AddIconMapping(url, icon)); |
| 511 |
| 512 base::Time delete_older_than = start + base::TimeDelta::FromDays(7); |
| 513 db.ClearOldOnDemandFavicons(delete_older_than); |
| 514 |
| 515 // Nothing gets deleted. |
| 516 EXPECT_TRUE(db.GetFaviconHeader(icon, nullptr, nullptr)); |
| 517 std::vector<FaviconBitmap> favicon_bitmaps; |
| 518 EXPECT_TRUE(db.GetFaviconBitmaps(icon, &favicon_bitmaps)); |
| 519 EXPECT_EQ(1u, favicon_bitmaps.size()); |
| 520 std::vector<IconMapping> icon_mapping; |
| 521 EXPECT_TRUE(db.GetIconMappingsForPageURL(url, &icon_mapping)); |
| 522 EXPECT_EQ(1u, icon_mapping.size()); |
| 523 EXPECT_EQ(icon, icon_mapping[0].icon_id); |
| 524 } |
| 525 |
364 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { | 526 TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { |
365 ThumbnailDatabase db(NULL); | 527 ThumbnailDatabase db(NULL); |
366 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); | 528 ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); |
367 db.BeginTransaction(); | 529 db.BeginTransaction(); |
368 | 530 |
369 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); | 531 std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); |
370 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); | 532 scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); |
371 | 533 |
372 GURL url("http://google.com"); | 534 GURL url("http://google.com"); |
373 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... |
1175 ThumbnailDatabase db(NULL); | 1337 ThumbnailDatabase db(NULL); |
1176 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); | 1338 ASSERT_EQ(sql::INIT_OK, db.Init(db_path)); |
1177 | 1339 |
1178 // Verify that the resulting schema is correct, whether it | 1340 // Verify that the resulting schema is correct, whether it |
1179 // involved razing the file or fixing things in place. | 1341 // involved razing the file or fixing things in place. |
1180 VerifyTablesAndColumns(&db.db_); | 1342 VerifyTablesAndColumns(&db.db_); |
1181 } | 1343 } |
1182 } | 1344 } |
1183 | 1345 |
1184 } // namespace history | 1346 } // namespace history |
OLD | NEW |