| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/offline_pages/offline_page_metadata_store_impl.h" | 5 #include "components/offline_pages/offline_page_metadata_store_impl.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| 11 #include "base/files/scoped_temp_dir.h" | 11 #include "base/files/scoped_temp_dir.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/test/test_simple_task_runner.h" | 15 #include "base/test/test_simple_task_runner.h" |
| 15 #include "base/thread_task_runner_handle.h" | 16 #include "base/thread_task_runner_handle.h" |
| 16 #include "components/leveldb_proto/proto_database_impl.h" | 17 #include "components/leveldb_proto/proto_database_impl.h" |
| 17 #include "components/offline_pages/offline_page_item.h" | 18 #include "components/offline_pages/offline_page_item.h" |
| 18 #include "components/offline_pages/offline_page_model.h" | 19 #include "components/offline_pages/offline_page_model.h" |
| 19 #include "components/offline_pages/proto/offline_pages.pb.h" | 20 #include "components/offline_pages/proto/offline_pages.pb.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
| 21 | 22 |
| 22 using leveldb_proto::ProtoDatabaseImpl; | 23 using leveldb_proto::ProtoDatabaseImpl; |
| 23 | 24 |
| 24 namespace offline_pages { | 25 namespace offline_pages { |
| 25 | 26 |
| 26 namespace { | 27 namespace { |
| 27 | 28 |
| 28 const char kTestURL[] = "https://example.com"; | 29 const char kTestURL[] = "https://example.com"; |
| 29 const ClientId kTestBookmarkId(BOOKMARK_NAMESPACE, "1234"); | 30 const ClientId kTestBookmarkId(BOOKMARK_NAMESPACE, "1234"); |
| 30 const ClientId kTestBookmarkId2(BOOKMARK_NAMESPACE, "5678"); | 31 const ClientId kTestBookmarkId2(BOOKMARK_NAMESPACE, "5678"); |
| 31 const base::FilePath::CharType kFilePath[] = | 32 const base::FilePath::CharType kFilePath[] = |
| 32 FILE_PATH_LITERAL("/offline_pages/example_com.mhtml"); | 33 FILE_PATH_LITERAL("/offline_pages/example_com.mhtml"); |
| 33 int64_t kFileSize = 234567; | 34 int64_t kFileSize = 234567; |
| 34 | 35 |
| 36 } // namespace |
| 37 |
| 35 class OfflinePageMetadataStoreImplTest : public testing::Test { | 38 class OfflinePageMetadataStoreImplTest : public testing::Test { |
| 36 public: | 39 public: |
| 37 enum CalledCallback { NONE, LOAD, ADD, REMOVE, DESTROY }; | 40 enum CalledCallback { NONE, LOAD, ADD, REMOVE, DESTROY }; |
| 38 enum Status { STATUS_NONE, STATUS_TRUE, STATUS_FALSE }; | 41 enum Status { STATUS_NONE, STATUS_TRUE, STATUS_FALSE }; |
| 39 | 42 |
| 40 OfflinePageMetadataStoreImplTest(); | 43 OfflinePageMetadataStoreImplTest(); |
| 41 ~OfflinePageMetadataStoreImplTest() override; | 44 ~OfflinePageMetadataStoreImplTest() override; |
| 42 | 45 |
| 43 void TearDown() override { | 46 void TearDown() override { |
| 44 // Wait for all the pieces of the store to delete itself properly. | 47 // Wait for all the pieces of the store to delete itself properly. |
| 45 PumpLoop(); | 48 PumpLoop(); |
| 46 } | 49 } |
| 47 | 50 |
| 48 scoped_ptr<OfflinePageMetadataStoreImpl> BuildStore(); | 51 scoped_ptr<OfflinePageMetadataStoreImpl> BuildStore(); |
| 49 void PumpLoop(); | 52 void PumpLoop(); |
| 50 | 53 |
| 51 void LoadCallback(OfflinePageMetadataStore::LoadStatus load_status, | 54 void LoadCallback(OfflinePageMetadataStore::LoadStatus load_status, |
| 52 const std::vector<OfflinePageItem>& offline_pages); | 55 const std::vector<OfflinePageItem>& offline_pages); |
| 53 void UpdateCallback(CalledCallback called_callback, bool success); | 56 void UpdateCallback(CalledCallback called_callback, bool success); |
| 54 | 57 |
| 55 void ClearResults(); | 58 void ClearResults(); |
| 56 | 59 |
| 60 void UpdateStoreEntries( |
| 61 OfflinePageMetadataStoreImpl* store, |
| 62 scoped_ptr<leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector> |
| 63 entries_to_save); |
| 64 |
| 57 protected: | 65 protected: |
| 58 CalledCallback last_called_callback_; | 66 CalledCallback last_called_callback_; |
| 59 Status last_status_; | 67 Status last_status_; |
| 60 std::vector<OfflinePageItem> offline_pages_; | 68 std::vector<OfflinePageItem> offline_pages_; |
| 61 | 69 |
| 62 base::ScopedTempDir temp_directory_; | 70 base::ScopedTempDir temp_directory_; |
| 63 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; | 71 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
| 64 base::ThreadTaskRunnerHandle task_runner_handle_; | 72 base::ThreadTaskRunnerHandle task_runner_handle_; |
| 65 }; | 73 }; |
| 66 | 74 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 last_called_callback_ = called_callback; | 113 last_called_callback_ = called_callback; |
| 106 last_status_ = status ? STATUS_TRUE : STATUS_FALSE; | 114 last_status_ = status ? STATUS_TRUE : STATUS_FALSE; |
| 107 } | 115 } |
| 108 | 116 |
| 109 void OfflinePageMetadataStoreImplTest::ClearResults() { | 117 void OfflinePageMetadataStoreImplTest::ClearResults() { |
| 110 last_called_callback_ = NONE; | 118 last_called_callback_ = NONE; |
| 111 last_status_ = STATUS_NONE; | 119 last_status_ = STATUS_NONE; |
| 112 offline_pages_.clear(); | 120 offline_pages_.clear(); |
| 113 } | 121 } |
| 114 | 122 |
| 123 void OfflinePageMetadataStoreImplTest::UpdateStoreEntries( |
| 124 OfflinePageMetadataStoreImpl* store, |
| 125 scoped_ptr<leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector> |
| 126 entries_to_save) { |
| 127 scoped_ptr<std::vector<std::string>> keys_to_remove( |
| 128 new std::vector<std::string>()); |
| 129 store->UpdateEntries( |
| 130 std::move(entries_to_save), std::move(keys_to_remove), |
| 131 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback, |
| 132 base::Unretained(this), ADD)); |
| 133 } |
| 134 |
| 115 // Loads empty store and makes sure that there are no offline pages stored in | 135 // Loads empty store and makes sure that there are no offline pages stored in |
| 116 // it. | 136 // it. |
| 117 TEST_F(OfflinePageMetadataStoreImplTest, LoadEmptyStore) { | 137 TEST_F(OfflinePageMetadataStoreImplTest, LoadEmptyStore) { |
| 118 scoped_ptr<OfflinePageMetadataStoreImpl> store(BuildStore()); | 138 scoped_ptr<OfflinePageMetadataStoreImpl> store(BuildStore()); |
| 119 EXPECT_EQ(LOAD, last_called_callback_); | 139 EXPECT_EQ(LOAD, last_called_callback_); |
| 120 EXPECT_EQ(STATUS_TRUE, last_status_); | 140 EXPECT_EQ(STATUS_TRUE, last_status_); |
| 121 EXPECT_EQ(0U, offline_pages_.size()); | 141 EXPECT_EQ(0U, offline_pages_.size()); |
| 122 } | 142 } |
| 123 | 143 |
| 124 // Adds metadata of an offline page into a store and then opens the store | 144 // Adds metadata of an offline page into a store and then opens the store |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 EXPECT_EQ(offline_page.offline_id, offline_pages_[0].offline_id); | 365 EXPECT_EQ(offline_page.offline_id, offline_pages_[0].offline_id); |
| 346 EXPECT_EQ(offline_page.version, offline_pages_[0].version); | 366 EXPECT_EQ(offline_page.version, offline_pages_[0].version); |
| 347 EXPECT_EQ(offline_page.file_path, offline_pages_[0].file_path); | 367 EXPECT_EQ(offline_page.file_path, offline_pages_[0].file_path); |
| 348 EXPECT_EQ(offline_page.file_size, offline_pages_[0].file_size); | 368 EXPECT_EQ(offline_page.file_size, offline_pages_[0].file_size); |
| 349 EXPECT_EQ(offline_page.creation_time, offline_pages_[0].creation_time); | 369 EXPECT_EQ(offline_page.creation_time, offline_pages_[0].creation_time); |
| 350 EXPECT_EQ(offline_page.last_access_time, offline_pages_[0].last_access_time); | 370 EXPECT_EQ(offline_page.last_access_time, offline_pages_[0].last_access_time); |
| 351 EXPECT_EQ(offline_page.access_count, offline_pages_[0].access_count); | 371 EXPECT_EQ(offline_page.access_count, offline_pages_[0].access_count); |
| 352 EXPECT_EQ(offline_page.client_id, offline_pages_[0].client_id); | 372 EXPECT_EQ(offline_page.client_id, offline_pages_[0].client_id); |
| 353 } | 373 } |
| 354 | 374 |
| 355 } // namespace | |
| 356 | |
| 357 // Test that loading a store with a bad value still loads. | 375 // Test that loading a store with a bad value still loads. |
| 358 // Needs to be outside of the anonymous namespace in order for FRIEND_TEST | 376 // Needs to be outside of the anonymous namespace in order for FRIEND_TEST |
| 359 // to work. | 377 // to work. |
| 360 TEST_F(OfflinePageMetadataStoreImplTest, LoadCorruptedStore) { | 378 TEST_F(OfflinePageMetadataStoreImplTest, LoadCorruptedStore) { |
| 361 scoped_ptr<OfflinePageMetadataStoreImpl> store(BuildStore()); | 379 scoped_ptr<OfflinePageMetadataStoreImpl> store(BuildStore()); |
| 362 | 380 |
| 363 // Write one ok page. | 381 // Write one ok page. |
| 364 OfflinePageItem offline_page(GURL(kTestURL), 1234LL, kTestBookmarkId, | 382 OfflinePageItem offline_page(GURL(kTestURL), 1234LL, kTestBookmarkId, |
| 365 base::FilePath(kFilePath), kFileSize); | 383 base::FilePath(kFilePath), kFileSize); |
| 366 store->AddOrUpdateOfflinePage( | 384 store->AddOrUpdateOfflinePage( |
| 367 offline_page, | 385 offline_page, |
| 368 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback, | 386 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback, |
| 369 base::Unretained(this), ADD)); | 387 base::Unretained(this), ADD)); |
| 370 PumpLoop(); | 388 PumpLoop(); |
| 371 EXPECT_EQ(ADD, last_called_callback_); | 389 EXPECT_EQ(ADD, last_called_callback_); |
| 372 EXPECT_EQ(STATUS_TRUE, last_status_); | 390 EXPECT_EQ(STATUS_TRUE, last_status_); |
| 373 | 391 |
| 374 // Manually write one broken page (no id) | 392 // Manually write one broken page (no id) |
| 375 scoped_ptr<leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector> | 393 scoped_ptr<leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector> |
| 376 entries_to_save( | 394 entries_to_save( |
| 377 new leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector()); | 395 new leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector()); |
| 378 scoped_ptr<std::vector<std::string>> keys_to_remove( | |
| 379 new std::vector<std::string>()); | |
| 380 | 396 |
| 381 OfflinePageEntry offline_page_proto; | 397 OfflinePageEntry offline_page_proto; |
| 382 entries_to_save->push_back(std::make_pair("0", offline_page_proto)); | 398 entries_to_save->push_back(std::make_pair("0", offline_page_proto)); |
| 383 | 399 |
| 384 store->UpdateEntries( | 400 UpdateStoreEntries(store.get(), std::move(entries_to_save)); |
| 385 std::move(entries_to_save), std::move(keys_to_remove), | |
| 386 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback, | |
| 387 base::Unretained(this), ADD)); | |
| 388 PumpLoop(); | 401 PumpLoop(); |
| 389 | 402 |
| 390 EXPECT_EQ(ADD, last_called_callback_); | 403 EXPECT_EQ(ADD, last_called_callback_); |
| 391 EXPECT_EQ(STATUS_TRUE, last_status_); | 404 EXPECT_EQ(STATUS_TRUE, last_status_); |
| 392 | 405 |
| 393 ClearResults(); | 406 ClearResults(); |
| 394 | 407 |
| 395 // Close the store first to ensure file lock is removed. | 408 // Close the store first to ensure file lock is removed. |
| 396 store.reset(); | 409 store.reset(); |
| 397 store = BuildStore(); | 410 store = BuildStore(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 414 // Test that loading a store with nothing but bad values errors. | 427 // Test that loading a store with nothing but bad values errors. |
| 415 // Needs to be outside of the anonymous namespace in order for FRIEND_TEST | 428 // Needs to be outside of the anonymous namespace in order for FRIEND_TEST |
| 416 // to work. | 429 // to work. |
| 417 TEST_F(OfflinePageMetadataStoreImplTest, LoadTotallyCorruptedStore) { | 430 TEST_F(OfflinePageMetadataStoreImplTest, LoadTotallyCorruptedStore) { |
| 418 scoped_ptr<OfflinePageMetadataStoreImpl> store(BuildStore()); | 431 scoped_ptr<OfflinePageMetadataStoreImpl> store(BuildStore()); |
| 419 | 432 |
| 420 // Manually write two broken pages (no id) | 433 // Manually write two broken pages (no id) |
| 421 scoped_ptr<leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector> | 434 scoped_ptr<leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector> |
| 422 entries_to_save( | 435 entries_to_save( |
| 423 new leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector()); | 436 new leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector()); |
| 424 scoped_ptr<std::vector<std::string>> keys_to_remove( | |
| 425 new std::vector<std::string>()); | |
| 426 | 437 |
| 427 OfflinePageEntry offline_page_proto; | 438 OfflinePageEntry offline_page_proto; |
| 428 entries_to_save->push_back(std::make_pair("0", offline_page_proto)); | 439 entries_to_save->push_back(std::make_pair("0", offline_page_proto)); |
| 429 entries_to_save->push_back(std::make_pair("1", offline_page_proto)); | 440 entries_to_save->push_back(std::make_pair("1", offline_page_proto)); |
| 430 | 441 |
| 431 store->UpdateEntries( | 442 UpdateStoreEntries(store.get(), std::move(entries_to_save));; |
| 432 std::move(entries_to_save), std::move(keys_to_remove), | |
| 433 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback, | |
| 434 base::Unretained(this), ADD)); | |
| 435 PumpLoop(); | 443 PumpLoop(); |
| 436 | 444 |
| 437 EXPECT_EQ(ADD, last_called_callback_); | 445 EXPECT_EQ(ADD, last_called_callback_); |
| 438 EXPECT_EQ(STATUS_TRUE, last_status_); | 446 EXPECT_EQ(STATUS_TRUE, last_status_); |
| 439 | 447 |
| 440 ClearResults(); | 448 ClearResults(); |
| 441 | 449 |
| 442 // Close the store first to ensure file lock is removed. | 450 // Close the store first to ensure file lock is removed. |
| 443 store.reset(); | 451 store.reset(); |
| 444 store = BuildStore(); | 452 store = BuildStore(); |
| 445 PumpLoop(); | 453 PumpLoop(); |
| 446 | 454 |
| 447 // One of the pages was busted, so only expect one page. | 455 // One of the pages was busted, so only expect one page. |
| 448 EXPECT_EQ(LOAD, last_called_callback_); | 456 EXPECT_EQ(LOAD, last_called_callback_); |
| 449 EXPECT_EQ(STATUS_FALSE, last_status_); | 457 EXPECT_EQ(STATUS_FALSE, last_status_); |
| 450 } | 458 } |
| 451 | 459 |
| 460 TEST_F(OfflinePageMetadataStoreImplTest, UpgradeStoreFromBookmarkIdToClientId) { |
| 461 scoped_ptr<OfflinePageMetadataStoreImpl> store(BuildStore()); |
| 462 |
| 463 // Manually write a page referring to legacy bookmark id. |
| 464 scoped_ptr<leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector> |
| 465 entries_to_save( |
| 466 new leveldb_proto::ProtoDatabase<OfflinePageEntry>::KeyEntryVector()); |
| 467 |
| 468 OfflinePageEntry offline_page_proto; |
| 469 offline_page_proto.set_deprecated_bookmark_id(1LL); |
| 470 offline_page_proto.set_version(1); |
| 471 offline_page_proto.set_url(kTestURL); |
| 472 offline_page_proto.set_file_path("/foo/bar"); |
| 473 entries_to_save->push_back(std::make_pair("1", offline_page_proto)); |
| 474 |
| 475 UpdateStoreEntries(store.get(), std::move(entries_to_save)); |
| 476 PumpLoop(); |
| 477 |
| 478 EXPECT_EQ(ADD, last_called_callback_); |
| 479 EXPECT_EQ(STATUS_TRUE, last_status_); |
| 480 |
| 481 ClearResults(); |
| 482 |
| 483 // Close the store first to ensure file lock is removed. |
| 484 store.reset(); |
| 485 store = BuildStore(); |
| 486 PumpLoop(); |
| 487 |
| 488 // The page should be upgraded with new Client ID format. |
| 489 EXPECT_EQ(LOAD, last_called_callback_); |
| 490 EXPECT_EQ(STATUS_TRUE, last_status_); |
| 491 EXPECT_EQ(1U, offline_pages_.size()); |
| 492 EXPECT_TRUE(offline_pages_[0].offline_id != 0); |
| 493 EXPECT_EQ(offline_pages::BOOKMARK_NAMESPACE, |
| 494 offline_pages_[0].client_id.name_space); |
| 495 EXPECT_EQ(base::Int64ToString(offline_page_proto.deprecated_bookmark_id()), |
| 496 offline_pages_[0].client_id.id); |
| 497 EXPECT_EQ(GURL(kTestURL), offline_pages_[0].url); |
| 498 EXPECT_EQ(offline_page_proto.version(), offline_pages_[0].version); |
| 499 EXPECT_EQ(offline_page_proto.file_path(), |
| 500 offline_pages_[0].file_path.MaybeAsASCII()); |
| 501 } |
| 502 |
| 452 } // namespace offline_pages | 503 } // namespace offline_pages |
| OLD | NEW |