blob: b71806bce9929df8a81dce62b3dffa7699a37f97 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/offline_pages/core/model/startup_maintenance_task.h"
#include <memory>
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "build/build_config.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/model/model_task_test_base.h"
#include "components/offline_pages/core/model/offline_page_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace offline_pages {
namespace {
const int64_t kTestFileSize = 512 * (1 << 10); // Default file size is 512KB.
// Used for checking if the page is still present in database and/or filesystem.
enum class PagePresence {
BOTH_DB_AND_FILESYSTEM,
DB_ONLY,
FILESYSTEM_ONLY,
NONE,
};
} // namespace
class StartupMaintenanceTaskTest : public ModelTaskTestBase {
public:
StartupMaintenanceTaskTest();
~StartupMaintenanceTaskTest() override;
void SetUp() override;
PagePresence CheckPagePresence(const OfflinePageItem& page);
base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }
private:
std::unique_ptr<base::HistogramTester> histogram_tester_;
};
StartupMaintenanceTaskTest::StartupMaintenanceTaskTest() {}
StartupMaintenanceTaskTest::~StartupMaintenanceTaskTest() {}
void StartupMaintenanceTaskTest::SetUp() {
ModelTaskTestBase::SetUp();
histogram_tester_ = std::make_unique<base::HistogramTester>();
}
PagePresence StartupMaintenanceTaskTest::CheckPagePresence(
const OfflinePageItem& page) {
if (base::PathExists(page.file_path)) {
if (store_test_util()->GetPageByOfflineId(page.offline_id))
return PagePresence::BOTH_DB_AND_FILESYSTEM;
else
return PagePresence::FILESYSTEM_ONLY;
} else {
if (store_test_util()->GetPageByOfflineId(page.offline_id))
return PagePresence::DB_ONLY;
else
return PagePresence::NONE;
}
}
// This test is affected by https://crbug.com/725685, which only affects windows
// platform.
#if defined(OS_WIN)
#define MAYBE_TestDeletePageInLegacyArchivesDir \
DISABLED_TestDeletePageInLegacyArchivesDir
#else
#define MAYBE_TestDeletePageInLegacyArchivesDir \
TestDeletePageInLegacyArchivesDir
#endif
TEST_F(StartupMaintenanceTaskTest, MAYBE_TestDeletePageInLegacyArchivesDir) {
// |temporary_page| will be removed since it's temporary and its archive file
// is in private directory.
// |persistent_page| will not be affected by the maintenance task.
generator()->SetArchiveDirectory(PrivateDir());
generator()->SetNamespace(kLastNNamespace);
OfflinePageItem temporary_page1 = AddPage();
OfflinePageItem temporary_page2 = AddPageWithoutDBEntry();
generator()->SetNamespace(kDownloadNamespace);
OfflinePageItem persistent_page1 = AddPage();
OfflinePageItem persistent_page2 = AddPageWithoutDBEntry();
EXPECT_EQ(2LL, store_test_util()->GetPageCount());
EXPECT_EQ(4UL, test_utils::GetFileCountInDirectory(PrivateDir()));
auto task = std::make_unique<StartupMaintenanceTask>(
store(), archive_manager(), policy_controller());
RunTask(std::move(task));
EXPECT_EQ(1LL, store_test_util()->GetPageCount());
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(PrivateDir()));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(temporary_page1));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(temporary_page2));
EXPECT_EQ(PagePresence::BOTH_DB_AND_FILESYSTEM,
CheckPagePresence(persistent_page1));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(persistent_page2));
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Legacy.DeletedHeadlessFileCount", 2, 1);
}
// This test is affected by https://crbug.com/725685, which only affects windows
// platform.
#if defined(OS_WIN)
#define MAYBE_TestDeleteFileWithoutDbEntry DISABLED_TestDeleteFileWithoutDbEntry
#else
#define MAYBE_TestDeleteFileWithoutDbEntry TestDeleteFileWithoutDbEntry
#endif
TEST_F(StartupMaintenanceTaskTest, MAYBE_TestDeleteFileWithoutDbEntry) {
// |temporary_page1| will not be affected.
// |temporary_page2| will have the file deleted since the file doesn't have a
// DB entry.
// |persistent_page1| will not be affected.
// |persistent_page2| will have its file deleted, since the file is in private
// directory and has no associated DB entry.
generator()->SetNamespace(kLastNNamespace);
generator()->SetArchiveDirectory(TemporaryDir());
OfflinePageItem temporary_page1 = AddPage();
OfflinePageItem temporary_page2 = AddPageWithoutDBEntry();
generator()->SetNamespace(kDownloadNamespace);
generator()->SetArchiveDirectory(PrivateDir());
OfflinePageItem persistent_page1 = AddPage();
OfflinePageItem persistent_page2 = AddPageWithoutDBEntry();
EXPECT_EQ(2LL, store_test_util()->GetPageCount());
EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(TemporaryDir()));
EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(PrivateDir()));
EXPECT_EQ(PagePresence::FILESYSTEM_ONLY, CheckPagePresence(temporary_page2));
EXPECT_EQ(PagePresence::FILESYSTEM_ONLY, CheckPagePresence(persistent_page2));
auto task = std::make_unique<StartupMaintenanceTask>(
store(), archive_manager(), policy_controller());
RunTask(std::move(task));
EXPECT_EQ(2LL, store_test_util()->GetPageCount());
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(TemporaryDir()));
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(PrivateDir()));
EXPECT_EQ(PagePresence::BOTH_DB_AND_FILESYSTEM,
CheckPagePresence(temporary_page1));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(temporary_page2));
EXPECT_EQ(PagePresence::BOTH_DB_AND_FILESYSTEM,
CheckPagePresence(persistent_page1));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(persistent_page2));
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Legacy.DeletedHeadlessFileCount", 1, 1);
histogram_tester()->ExpectTotalCount(
"OfflinePages.ConsistencyCheck.Temporary.PagesMissingArchiveFileCount",
0);
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Temporary.PagesMissingDbEntryCount", 1, 1);
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Temporary.Result",
static_cast<int>(SyncOperationResult::SUCCESS), 1);
}
// This test is affected by https://crbug.com/725685, which only affects windows
// platform.
#if defined(OS_WIN)
#define MAYBE_TestDeleteDbEntryWithoutFile DISABLED_TestDeleteDbEntryWithoutFile
#else
#define MAYBE_TestDeleteDbEntryWithoutFile TestDeleteDbEntryWithoutFile
#endif
TEST_F(StartupMaintenanceTaskTest, MAYBE_TestDeleteDbEntryWithoutFile) {
// |temporary_page1| will not be affected.
// |temporary_page2| will be deleted from DB since it has no file associated.
// |persistent_page1| will not be affected.
// |persistent_page2| will be marked as file_missing.
generator()->SetNamespace(kLastNNamespace);
generator()->SetArchiveDirectory(TemporaryDir());
OfflinePageItem temporary_page1 = AddPage();
OfflinePageItem temporary_page2 = AddPageWithoutFile();
generator()->SetNamespace(kDownloadNamespace);
generator()->SetArchiveDirectory(PrivateDir());
OfflinePageItem persistent_page1 = AddPage();
OfflinePageItem persistent_page2 = AddPageWithoutFile();
EXPECT_EQ(4LL, store_test_util()->GetPageCount());
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(TemporaryDir()));
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(PrivateDir()));
EXPECT_EQ(PagePresence::DB_ONLY, CheckPagePresence(temporary_page2));
EXPECT_EQ(PagePresence::DB_ONLY, CheckPagePresence(persistent_page2));
auto task = std::make_unique<StartupMaintenanceTask>(
store(), archive_manager(), policy_controller());
RunTask(std::move(task));
EXPECT_EQ(3LL, store_test_util()->GetPageCount());
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(TemporaryDir()));
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(PrivateDir()));
EXPECT_EQ(PagePresence::BOTH_DB_AND_FILESYSTEM,
CheckPagePresence(temporary_page1));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(temporary_page2));
EXPECT_EQ(PagePresence::BOTH_DB_AND_FILESYSTEM,
CheckPagePresence(persistent_page1));
EXPECT_EQ(PagePresence::DB_ONLY, CheckPagePresence(persistent_page2));
histogram_tester()->ExpectTotalCount(
"OfflinePages.ConsistencyCheck.Temporary.PagesMissingDbEntryCount", 0);
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Temporary.PagesMissingArchiveFileCount", 1,
1);
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Temporary.Result",
static_cast<int>(SyncOperationResult::SUCCESS), 1);
}
// This test is affected by https://crbug.com/725685, which only affects windows
// platform.
#if defined(OS_WIN)
#define MAYBE_CombinedTest DISABLED_CombinedTest
#else
#define MAYBE_CombinedTest CombinedTest
#endif
TEST_F(StartupMaintenanceTaskTest, MAYBE_CombinedTest) {
// Adding a bunch of pages with different setups for temporary pages.
// |temporary_page1| will not be affected.
// |temporary_page{2,3,4,5,6}| will be deleted.
generator()->SetNamespace(kLastNNamespace);
generator()->SetArchiveDirectory(TemporaryDir());
OfflinePageItem temporary_page1 = AddPage();
OfflinePageItem temporary_page2 = AddPageWithoutDBEntry();
OfflinePageItem temporary_page3 = AddPageWithoutFile();
generator()->SetArchiveDirectory(PrivateDir());
OfflinePageItem temporary_page4 = AddPage();
OfflinePageItem temporary_page5 = AddPageWithoutDBEntry();
OfflinePageItem temporary_page6 = AddPageWithoutFile();
// Adding a bunch of pages with different setups for persistent pages.
// |persistent_page1| will not be affected.
// |persistent_page2| will be deleted from Filesystem, since it's in private
// directory.
generator()->SetNamespace(kDownloadNamespace);
OfflinePageItem persistent_page1 = AddPage();
OfflinePageItem persistent_page2 = AddPageWithoutDBEntry();
EXPECT_EQ(5LL, store_test_util()->GetPageCount());
EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(TemporaryDir()));
EXPECT_EQ(4UL, test_utils::GetFileCountInDirectory(PrivateDir()));
auto task = std::make_unique<StartupMaintenanceTask>(
store(), archive_manager(), policy_controller());
RunTask(std::move(task));
EXPECT_EQ(2LL, store_test_util()->GetPageCount());
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(TemporaryDir()));
EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(PrivateDir()));
EXPECT_EQ(PagePresence::BOTH_DB_AND_FILESYSTEM,
CheckPagePresence(temporary_page1));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(temporary_page2));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(temporary_page3));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(temporary_page4));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(temporary_page5));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(temporary_page6));
EXPECT_EQ(PagePresence::BOTH_DB_AND_FILESYSTEM,
CheckPagePresence(persistent_page1));
EXPECT_EQ(PagePresence::NONE, CheckPagePresence(persistent_page2));
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Legacy.DeletedHeadlessFileCount", 2, 1);
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Temporary.PagesMissingArchiveFileCount", 2,
1);
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Temporary.PagesMissingDbEntryCount", 1, 1);
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ConsistencyCheck.Temporary.Result",
static_cast<int>(SyncOperationResult::SUCCESS), 1);
}
TEST_F(StartupMaintenanceTaskTest, TestKeepingNonMhtmlFile) {
// Create a persistent offline page with mhtml extension but has no DB entry.
// It will not be deleted since it's in public directory.
generator()->SetNamespace(kDownloadNamespace);
generator()->SetArchiveDirectory(PublicDir());
OfflinePageItem page1 = AddPageWithoutDBEntry();
// Create a file with non-mhtml extension. It should not be affected.
base::FilePath path;
base::CreateTemporaryFileInDir(PublicDir(), &path);
base::FilePath mp3_path = path.AddExtension(FILE_PATH_LITERAL("mp3"));
EXPECT_TRUE(base::Move(path, mp3_path));
EXPECT_EQ(0LL, store_test_util()->GetPageCount());
EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(PublicDir()));
auto task = std::make_unique<StartupMaintenanceTask>(
store(), archive_manager(), policy_controller());
RunTask(std::move(task));
EXPECT_EQ(0LL, store_test_util()->GetPageCount());
EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(PublicDir()));
EXPECT_EQ(PagePresence::FILESYSTEM_ONLY, CheckPagePresence(page1));
}
TEST_F(StartupMaintenanceTaskTest, TestReportStorageUsage) {
generator()->SetFileSize(kTestFileSize);
std::vector<std::string> namespaces = policy_controller()->GetAllNamespaces();
// Adding pages into each namespace.
for (const auto& name_space : namespaces) {
// Set the correct namespace for generated pages, also put them into the
// correct directories, otherwise they might be cleaned based on consistency
// check.
generator()->SetNamespace(name_space);
if (policy_controller()->IsRemovedOnCacheReset(name_space))
generator()->SetArchiveDirectory(TemporaryDir());
else
generator()->SetArchiveDirectory(PrivateDir());
// For each namespace, insert pages based on the length of the namespace, so
// that we don't need to have const values here.
for (size_t count = 0; count < name_space.length(); ++count)
AddPage();
}
auto task = std::make_unique<StartupMaintenanceTask>(
store(), archive_manager(), policy_controller());
RunTask(std::move(task));
// For each namespace, check if the storage usage was correctly reported,
// since the value is reported with KiB as unit, divide it by 1024 here.
for (const auto& name_space : namespaces) {
histogram_tester()->ExpectUniqueSample(
"OfflinePages.ClearStoragePreRunUsage2." + name_space,
name_space.length() * kTestFileSize / 1024, 1);
}
}
} // namespace offline_pages