| Index: components/offline_pages/offline_page_metadata_store_impl_unittest.cc
|
| diff --git a/components/offline_pages/offline_page_metadata_store_impl_unittest.cc b/components/offline_pages/offline_page_metadata_store_impl_unittest.cc
|
| index 2ed53a23477395f3b7bbe4c459249fde93e00c2d..6684482ef4af960fc77f467b191cc083ab6bb823 100644
|
| --- a/components/offline_pages/offline_page_metadata_store_impl_unittest.cc
|
| +++ b/components/offline_pages/offline_page_metadata_store_impl_unittest.cc
|
| @@ -18,23 +18,76 @@
|
| #include "components/offline_pages/offline_page_item.h"
|
| #include "components/offline_pages/offline_page_metadata_store_sql.h"
|
| #include "components/offline_pages/offline_page_model.h"
|
| +#include "sql/connection.h"
|
| +#include "sql/statement.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| namespace offline_pages {
|
|
|
| namespace {
|
|
|
| +#define OFFLINE_PAGES_TABLE_V1 "offlinepages_v1"
|
| +
|
| const char kTestClientNamespace[] = "CLIENT_NAMESPACE";
|
| const char kTestURL[] = "https://example.com";
|
| const ClientId kTestClientId1(kTestClientNamespace, "1234");
|
| const ClientId kTestClientId2(kTestClientNamespace, "5678");
|
| const base::FilePath::CharType kFilePath[] =
|
| FILE_PATH_LITERAL("/offline_pages/example_com.mhtml");
|
| -int64_t kFileSize = 234567;
|
| +int64_t kFileSize = 234567LL;
|
| +int64_t kOfflineId = 12345LL;
|
| +
|
| +// Build a store with outdated schema to simulate the upgrading process.
|
| +// TODO(romax): move it to sql_unittests.
|
| +void BuildTestStoreWithOutdatedSchema(const base::FilePath& file) {
|
| + sql::Connection connection;
|
| + ASSERT_TRUE(
|
| + connection.Open(file.Append(FILE_PATH_LITERAL("OfflinePages.db"))));
|
| + ASSERT_TRUE(connection.is_open());
|
| + ASSERT_TRUE(connection.BeginTransaction());
|
| + ASSERT_TRUE(connection.Execute("CREATE TABLE " OFFLINE_PAGES_TABLE_V1
|
| + "(offline_id INTEGER PRIMARY KEY NOT NULL, "
|
| + "creation_time INTEGER NOT NULL, "
|
| + "file_size INTEGER NOT NULL, "
|
| + "version INTEGER NOT NULL, "
|
| + "last_access_time INTEGER NOT NULL, "
|
| + "access_count INTEGER NOT NULL, "
|
| + "status INTEGER NOT NULL DEFAULT 0, "
|
| + "user_initiated INTEGER, "
|
| + "client_namespace VARCHAR NOT NULL, "
|
| + "client_id VARCHAR NOT NULL, "
|
| + "online_url VARCHAR NOT NULL, "
|
| + "offline_url VARCHAR NOT NULL DEFAULT '', "
|
| + "file_path VARCHAR NOT NULL "
|
| + ")"));
|
| + ASSERT_TRUE(connection.CommitTransaction());
|
| + sql::Statement statement(connection.GetUniqueStatement(
|
| + "INSERT INTO " OFFLINE_PAGES_TABLE_V1
|
| + "(offline_id, creation_time, file_size, version, "
|
| + "last_access_time, access_count, client_namespace, "
|
| + "client_id, online_url, file_path) "
|
| + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
|
| + statement.BindInt64(0, kOfflineId);
|
| + statement.BindInt(1, 0);
|
| + statement.BindInt64(2, kFileSize);
|
| + statement.BindInt(3, 0);
|
| + statement.BindInt(4, 0);
|
| + statement.BindInt(5, 1);
|
| + statement.BindCString(6, kTestClientNamespace);
|
| + statement.BindString(7, kTestClientId2.id);
|
| + statement.BindCString(8, kTestURL);
|
| + statement.BindString(9, base::FilePath(kFilePath).MaybeAsASCII());
|
| + ASSERT_TRUE(statement.Run());
|
| + ASSERT_TRUE(connection.DoesTableExist(OFFLINE_PAGES_TABLE_V1));
|
| + ASSERT_FALSE(
|
| + connection.DoesColumnExist(OFFLINE_PAGES_TABLE_V1, "expiration_time"));
|
| +}
|
|
|
| class OfflinePageMetadataStoreFactory {
|
| public:
|
| virtual OfflinePageMetadataStore* BuildStore(const base::FilePath& file) = 0;
|
| + virtual OfflinePageMetadataStore* BuildStoreV1(
|
| + const base::FilePath& file) = 0;
|
| };
|
|
|
| class OfflinePageMetadataStoreSQLFactory
|
| @@ -45,6 +98,13 @@ class OfflinePageMetadataStoreSQLFactory
|
| base::ThreadTaskRunnerHandle::Get(), file);
|
| return store;
|
| }
|
| +
|
| + OfflinePageMetadataStore* BuildStoreV1(const base::FilePath& file) override {
|
| + BuildTestStoreWithOutdatedSchema(file);
|
| + OfflinePageMetadataStoreSQL* store = new OfflinePageMetadataStoreSQL(
|
| + base::ThreadTaskRunnerHandle::Get(), file);
|
| + return store;
|
| + }
|
| };
|
|
|
| enum CalledCallback { NONE, LOAD, ADD, REMOVE, DESTROY };
|
| @@ -119,6 +179,8 @@ template <typename T>
|
| class OfflinePageMetadataStoreTest : public OfflinePageMetadataStoreTestBase {
|
| public:
|
| std::unique_ptr<OfflinePageMetadataStore> BuildStore();
|
| + std::unique_ptr<OfflinePageMetadataStore>
|
| + BuildStoreWithUpgradeFromOutdatedSchema();
|
|
|
| protected:
|
| T factory_;
|
| @@ -135,6 +197,17 @@ OfflinePageMetadataStoreTest<T>::BuildStore() {
|
| return store;
|
| }
|
|
|
| +template <typename T>
|
| +std::unique_ptr<OfflinePageMetadataStore>
|
| +OfflinePageMetadataStoreTest<T>::BuildStoreWithUpgradeFromOutdatedSchema() {
|
| + std::unique_ptr<OfflinePageMetadataStore> store(
|
| + factory_.BuildStoreV1(temp_directory_.path()));
|
| + store->Load(base::Bind(&OfflinePageMetadataStoreTestBase::LoadCallback,
|
| + base::Unretained(this)));
|
| + PumpLoop();
|
| + return store;
|
| +}
|
| +
|
| typedef testing::Types<OfflinePageMetadataStoreSQLFactory> MyTypes;
|
| TYPED_TEST_CASE(OfflinePageMetadataStoreTest, MyTypes);
|
|
|
| @@ -147,6 +220,53 @@ TYPED_TEST(OfflinePageMetadataStoreTest, LoadEmptyStore) {
|
| EXPECT_EQ(0U, this->offline_pages_.size());
|
| }
|
|
|
| +// Loads a store which has an outdated schema.
|
| +// This test case would crash if it's not handling correctly when we're loading
|
| +// old version stores.
|
| +// TODO(romax): Move this to sql_unittest.
|
| +TYPED_TEST(OfflinePageMetadataStoreTest, LoadPreviousVersionStore) {
|
| + std::unique_ptr<OfflinePageMetadataStore> store(
|
| + this->BuildStoreWithUpgradeFromOutdatedSchema());
|
| + EXPECT_EQ(LOAD, this->last_called_callback_);
|
| + EXPECT_EQ(STATUS_TRUE, this->last_status_);
|
| + EXPECT_EQ(1U, this->offline_pages_.size());
|
| + OfflinePageItem offline_page(GURL(kTestURL), 1234LL, kTestClientId1,
|
| + base::FilePath(kFilePath), kFileSize);
|
| + base::Time expiration_time = base::Time::Now();
|
| + offline_page.expiration_time = expiration_time;
|
| + store->AddOrUpdateOfflinePage(
|
| + offline_page,
|
| + base::Bind(&OfflinePageMetadataStoreTestBase::UpdateCallback,
|
| + base::Unretained(this), ADD));
|
| + this->PumpLoop();
|
| + EXPECT_EQ(ADD, this->last_called_callback_);
|
| + EXPECT_EQ(STATUS_TRUE, this->last_status_);
|
| + this->ClearResults();
|
| +
|
| + // Close the store first to ensure file lock is removed.
|
| + store.reset();
|
| + store = this->BuildStore();
|
| + this->PumpLoop();
|
| +
|
| + EXPECT_EQ(LOAD, this->last_called_callback_);
|
| + EXPECT_EQ(STATUS_TRUE, this->last_status_);
|
| + ASSERT_EQ(2U, this->offline_pages_.size());
|
| + if (this->offline_pages_[0].offline_id != offline_page.offline_id) {
|
| + std::swap(this->offline_pages_[0], this->offline_pages_[1]);
|
| + }
|
| + EXPECT_EQ(offline_page.url, this->offline_pages_[0].url);
|
| + EXPECT_EQ(offline_page.offline_id, this->offline_pages_[0].offline_id);
|
| + EXPECT_EQ(offline_page.file_path, this->offline_pages_[0].file_path);
|
| + EXPECT_EQ(offline_page.last_access_time,
|
| + this->offline_pages_[0].last_access_time);
|
| + EXPECT_EQ(offline_page.expiration_time,
|
| + this->offline_pages_[0].expiration_time);
|
| + EXPECT_EQ(offline_page.client_id, this->offline_pages_[0].client_id);
|
| + EXPECT_EQ(kOfflineId, this->offline_pages_[1].offline_id);
|
| + EXPECT_EQ(kFileSize, this->offline_pages_[1].file_size);
|
| + EXPECT_EQ(kTestClientId2, this->offline_pages_[1].client_id);
|
| +}
|
| +
|
| // Adds metadata of an offline page into a store and then opens the store
|
| // again to make sure that stored metadata survives store restarts.
|
| TYPED_TEST(OfflinePageMetadataStoreTest, AddOfflinePage) {
|
| @@ -170,7 +290,7 @@ TYPED_TEST(OfflinePageMetadataStoreTest, AddOfflinePage) {
|
|
|
| EXPECT_EQ(LOAD, this->last_called_callback_);
|
| EXPECT_EQ(STATUS_TRUE, this->last_status_);
|
| - EXPECT_EQ(1U, this->offline_pages_.size());
|
| + ASSERT_EQ(1U, this->offline_pages_.size());
|
| EXPECT_EQ(offline_page.url, this->offline_pages_[0].url);
|
| EXPECT_EQ(offline_page.offline_id, this->offline_pages_[0].offline_id);
|
| EXPECT_EQ(offline_page.version, this->offline_pages_[0].version);
|
| @@ -305,7 +425,7 @@ TYPED_TEST(OfflinePageMetadataStoreTest, AddRemoveMultipleOfflinePages) {
|
|
|
| EXPECT_EQ(LOAD, this->last_called_callback_);
|
| EXPECT_EQ(STATUS_TRUE, this->last_status_);
|
| - EXPECT_EQ(1U, this->offline_pages_.size());
|
| + ASSERT_EQ(1U, this->offline_pages_.size());
|
| EXPECT_EQ(offline_page_2.url, this->offline_pages_[0].url);
|
| EXPECT_EQ(offline_page_2.offline_id, this->offline_pages_[0].offline_id);
|
| EXPECT_EQ(offline_page_2.version, this->offline_pages_[0].version);
|
| @@ -343,7 +463,7 @@ TYPED_TEST(OfflinePageMetadataStoreTest, UpdateOfflinePage) {
|
|
|
| EXPECT_EQ(LOAD, this->last_called_callback_);
|
| EXPECT_EQ(STATUS_TRUE, this->last_status_);
|
| - EXPECT_EQ(1U, this->offline_pages_.size());
|
| + ASSERT_EQ(1U, this->offline_pages_.size());
|
| EXPECT_EQ(offline_page.url, this->offline_pages_[0].url);
|
| EXPECT_EQ(offline_page.offline_id, this->offline_pages_[0].offline_id);
|
| EXPECT_EQ(offline_page.version, this->offline_pages_[0].version);
|
| @@ -376,7 +496,7 @@ TYPED_TEST(OfflinePageMetadataStoreTest, UpdateOfflinePage) {
|
|
|
| EXPECT_EQ(LOAD, this->last_called_callback_);
|
| EXPECT_EQ(STATUS_TRUE, this->last_status_);
|
| - EXPECT_EQ(1U, this->offline_pages_.size());
|
| + ASSERT_EQ(1U, this->offline_pages_.size());
|
| EXPECT_EQ(offline_page.url, this->offline_pages_[0].url);
|
| EXPECT_EQ(offline_page.offline_id, this->offline_pages_[0].offline_id);
|
| EXPECT_EQ(offline_page.version, this->offline_pages_[0].version);
|
|
|