Commit 61fc3569 authored by Dan Harrington's avatar Dan Harrington Committed by Commit Bot

Add PrefetchItemFlow unittest

This helps test the integration of tasks that make up the prefetch
pipeline. I found that this coverage was lacking when making a change
to a task.

This CL also improves output of PrefetchItem and prefetch enums for tests.

Change-Id: I719d815da3a6473c120f077f723c3c67a30e29cc
Reviewed-on: https://chromium-review.googlesource.com/1058169
Commit-Queue: Dan H <harringtond@chromium.org>
Reviewed-by: default avatarJustin DeWitt <dewittj@chromium.org>
Cr-Commit-Position: refs/heads/master@{#559294}
parent cc46beb5
......@@ -130,6 +130,10 @@ static_library("test_support") {
"prefetch_task_test_base.h",
"store/prefetch_store_test_util.cc",
"store/prefetch_store_test_util.h",
"test_download_client.cc",
"test_download_client.h",
"test_download_service.cc",
"test_download_service.h",
"test_offline_metrics_collector.h",
"test_prefetch_dispatcher.cc",
"test_prefetch_dispatcher.h",
......@@ -141,12 +145,14 @@ static_library("test_support") {
"test_prefetch_importer.h",
"test_prefetch_network_request_factory.cc",
"test_prefetch_network_request_factory.h",
"test_util.cc",
]
deps = [
":prefetch",
"//base",
"//components/download/public/background_service:public",
"//components/download/public/background_service/test:test_support",
"//components/gcm_driver/instance_id",
"//components/keyed_service/core",
"//components/offline_pages/core",
......@@ -206,8 +212,6 @@ source_set("unit_tests") {
"store/prefetch_store_schema_unittest.cc",
"store/prefetch_store_unittest.cc",
"suggested_articles_observer_unittest.cc",
"test_download_client.cc",
"test_download_client.h",
]
deps = [
......
......@@ -68,4 +68,4 @@ void GeneratePageBundleRequest::OnCompleted(PrefetchRequestStatus status,
callback_.Run(PrefetchRequestStatus::SUCCESS, operation_name, pages);
}
} // offline_pages
} // namespace offline_pages
......@@ -4,8 +4,10 @@
#include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/offline_pages/core/client_namespace_constants.h"
#include "components/offline_pages/core/offline_event_logger.h"
......@@ -16,6 +18,8 @@
#include "components/offline_pages/core/prefetch/prefetch_background_task.h"
#include "components/offline_pages/core/prefetch/prefetch_configuration.h"
#include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h"
#include "components/offline_pages/core/prefetch/prefetch_importer_impl.h"
#include "components/offline_pages/core/prefetch/prefetch_item.h"
#include "components/offline_pages/core/prefetch/prefetch_network_request_factory.h"
#include "components/offline_pages/core/prefetch/prefetch_request_test_base.h"
#include "components/offline_pages/core/prefetch/prefetch_service.h"
......@@ -23,6 +27,7 @@
#include "components/offline_pages/core/prefetch/store/prefetch_store.h"
#include "components/offline_pages/core/prefetch/store/prefetch_store_test_util.h"
#include "components/offline_pages/core/prefetch/suggested_articles_observer.h"
#include "components/offline_pages/core/prefetch/test_download_service.h"
#include "components/offline_pages/core/prefetch/test_prefetch_network_request_factory.h"
#include "components/offline_pages/core/stub_offline_page_model.h"
#include "components/version_info/channel.h"
......@@ -47,15 +52,36 @@ const GURL kTestURL("https://www.chromium.org");
const GURL kTestURL2("https://www.chromium.org/2");
const int64_t kTestOfflineID = 1111;
const char kClientID[] = "client-id-1";
const char kOperationName[] = "operation-1";
const char kBodyName[] = "body-1";
const int64_t kBodyLength = 10;
const char kBodyContent[] = "abcde12345";
const base::Time kRenderTime = base::Time::Now();
RenderPageInfo RenderInfo(const std::string& url) {
RenderPageInfo info;
info.url = url;
info.redirect_url = "";
info.status = RenderStatus::RENDERED;
info.body_name = kBodyName;
info.body_length = kBodyLength;
info.render_time = kRenderTime;
return info;
}
class MockOfflinePageModel : public StubOfflinePageModel {
public:
MockOfflinePageModel() = default;
MockOfflinePageModel(const base::FilePath& archive_directory) {
SetArchiveDirectory(archive_directory);
}
~MockOfflinePageModel() override = default;
MOCK_METHOD1(StoreThumbnail, void(const OfflinePageThumbnail& thumb));
MOCK_METHOD2(HasThumbnailForOfflineId_,
void(int64_t offline_id,
base::OnceCallback<void(bool)>* callback));
MOCK_METHOD2(AddPage,
void(const OfflinePageItem& page,
const AddPageCallback& callback));
void HasThumbnailForOfflineId(
int64_t offline_id,
base::OnceCallback<void(bool)> callback) override {
......@@ -92,6 +118,33 @@ class TestPrefetchConfiguration : public PrefetchConfiguration {
bool enabled_ = true;
};
class FakePrefetchNetworkRequestFactory
: public TestPrefetchNetworkRequestFactory {
public:
void MakeGeneratePageBundleRequest(
const std::vector<std::string>& prefetch_urls,
const std::string& gcm_registration_id,
const PrefetchRequestFinishedCallback& callback) override {
TestPrefetchNetworkRequestFactory::MakeGeneratePageBundleRequest(
prefetch_urls, gcm_registration_id, callback);
if (!respond_to_generate_page_bundle_)
return;
std::vector<RenderPageInfo> pages;
for (const std::string& url : prefetch_urls) {
pages.push_back(RenderInfo(url));
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindRepeating(callback, PrefetchRequestStatus::SUCCESS,
kOperationName, pages));
}
void set_respond_to_generate_page_bundle(bool value) {
respond_to_generate_page_bundle_ = value;
}
private:
bool respond_to_generate_page_bundle_ = false;
};
} // namespace
class PrefetchDispatcherTest : public PrefetchRequestTestBase {
......@@ -126,7 +179,7 @@ class PrefetchDispatcherTest : public PrefetchRequestTestBase {
bool dispatcher_suspended() const { return dispatcher_->suspended_; }
TaskQueue* dispatcher_task_queue() { return &dispatcher_->task_queue_; }
PrefetchDispatcher* prefetch_dispatcher() { return dispatcher_; }
TestPrefetchNetworkRequestFactory* network_request_factory() {
FakePrefetchNetworkRequestFactory* network_request_factory() {
return network_request_factory_;
}
......@@ -168,6 +221,10 @@ class PrefetchDispatcherTest : public PrefetchRequestTestBase {
to_return, task_runner()))));
}
PrefetchDispatcherImpl* dispatcher() { return dispatcher_; }
PrefetchService* prefetch_service() { return taco_->prefetch_service(); }
TestDownloadService* download_service() { return taco_->download_service(); }
protected:
// Owned by |taco_|.
MockOfflinePageModel* offline_model_;
......@@ -177,6 +234,9 @@ class PrefetchDispatcherTest : public PrefetchRequestTestBase {
// Owned by |taco_|.
MockThumbnailFetcher* thumbnail_fetcher_;
PrefetchStoreTestUtil store_util_{task_runner()};
base::ScopedTempDir archive_directory_;
private:
std::unique_ptr<PrefetchServiceTestTaco> taco_;
......@@ -185,7 +245,7 @@ class PrefetchDispatcherTest : public PrefetchRequestTestBase {
// Owned by |taco_|.
PrefetchDispatcherImpl* dispatcher_;
// Owned by |taco_|.
TestPrefetchNetworkRequestFactory* network_request_factory_;
FakePrefetchNetworkRequestFactory* network_request_factory_;
bool reschedule_called_ = false;
PrefetchBackgroundTaskRescheduleType reschedule_type_ =
......@@ -197,9 +257,13 @@ PrefetchDispatcherTest::PrefetchDispatcherTest() {
}
void PrefetchDispatcherTest::SetUp() {
ASSERT_TRUE(archive_directory_.CreateUniqueTempDir());
dispatcher_ = new PrefetchDispatcherImpl();
network_request_factory_ = new TestPrefetchNetworkRequestFactory();
network_request_factory_ = new FakePrefetchNetworkRequestFactory();
taco_.reset(new PrefetchServiceTestTaco);
store_util_.BuildStore();
taco_->SetPrefetchStore(store_util_.ReleaseStore());
taco_->SetPrefetchDispatcher(base::WrapUnique(dispatcher_));
taco_->SetPrefetchNetworkRequestFactory(
base::WrapUnique(network_request_factory_));
......@@ -208,9 +272,14 @@ void PrefetchDispatcherTest::SetUp() {
auto thumbnail_fetcher = std::make_unique<MockThumbnailFetcher>();
thumbnail_fetcher_ = thumbnail_fetcher.get();
taco_->SetThumbnailFetcher(std::move(thumbnail_fetcher));
auto model = std::make_unique<MockOfflinePageModel>();
auto model =
std::make_unique<MockOfflinePageModel>(archive_directory_.GetPath());
offline_model_ = model.get();
taco_->SetOfflinePageModel(std::move(model));
taco_->SetPrefetchImporter(std::make_unique<PrefetchImporterImpl>(
dispatcher_, offline_model_, task_runner()));
taco_->CreatePrefetchService();
ASSERT_TRUE(test_urls_.empty());
......@@ -543,4 +612,67 @@ TEST_F(PrefetchDispatcherTest,
std::move(prefetch_item_ids));
}
// Runs through the entire lifecycle of a successful prefetch item,
// from GeneratePageBundle, GetOperation, download, import, and completion.
TEST_F(PrefetchDispatcherTest, PrefetchItemFlow) {
auto get_item = [&]() {
std::set<PrefetchItem> items;
EXPECT_EQ(1ul, store_util_.GetAllItems(&items));
return *items.begin();
};
// The page should be added to the offline model. Return success through the
// callback, and store the page to added_page.
OfflinePageItem added_page;
EXPECT_CALL(*offline_model_, AddPage(_, _))
.WillOnce(testing::Invoke([&](const OfflinePageItem& page,
const AddPageCallback& callback) {
added_page = page;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(callback, AddPageResult::SUCCESS, page.offline_id));
}));
network_request_factory()->set_respond_to_generate_page_bundle(true);
download_service()->SetTestFileData(kBodyContent);
std::vector<PrefetchURL> prefetch_urls;
prefetch_urls.push_back(PrefetchURL("url-1", GURL("http://www.url1.com"),
base::ASCIIToUTF16("URL 1")));
// Kick off the request.
dispatcher()->AddCandidatePrefetchURLs(kSuggestedArticlesNamespace,
prefetch_urls);
// Run the pipeline to completion.
RunUntilIdle();
PrefetchItem state1 = get_item();
BeginBackgroundTask();
RunUntilIdle();
PrefetchItem state2 = get_item();
BeginBackgroundTask();
RunUntilIdle();
PrefetchItem state3 = get_item();
// Check progression of item state. Log the states to help explain any failed
// expectations.
SCOPED_TRACE(testing::Message() << "\nstate1: " << state1 << "\nstate2: "
<< state2 << "\nstate3: " << state3);
// State 1.
EXPECT_EQ(PrefetchItemState::NEW_REQUEST, state1.state);
// State 2.
EXPECT_EQ(PrefetchItemState::FINISHED, state2.state);
EXPECT_FALSE(state2.file_path.empty());
EXPECT_FALSE(added_page.file_path.empty());
std::string imported_file_contents;
EXPECT_TRUE(
base::ReadFileToString(added_page.file_path, &imported_file_contents));
EXPECT_EQ(kBodyContent, imported_file_contents);
EXPECT_EQ(kBodyLength, state2.file_size);
// State 3.
EXPECT_EQ(PrefetchItemState::ZOMBIE, state3.state);
EXPECT_EQ(PrefetchItemErrorCode::SUCCESS, state3.error_code);
}
} // namespace offline_pages
......@@ -43,9 +43,6 @@ PrefetchDownloaderImpl::PrefetchDownloaderImpl(
DCHECK(download_service);
}
PrefetchDownloaderImpl::PrefetchDownloaderImpl(version_info::Channel channel)
: download_service_(nullptr), channel_(channel), weak_ptr_factory_(this) {}
PrefetchDownloaderImpl::~PrefetchDownloaderImpl() = default;
void PrefetchDownloaderImpl::SetPrefetchService(PrefetchService* service) {
......
......@@ -26,7 +26,6 @@ class DownloadService;
namespace offline_pages {
class PrefetchService;
class PrefetchServiceTestTaco;
// Asynchronously downloads the archive.
class PrefetchDownloaderImpl : public PrefetchDownloader {
......@@ -54,8 +53,6 @@ class PrefetchDownloaderImpl : public PrefetchDownloader {
void SetClockForTesting(base::Clock* clock);
private:
friend class PrefetchServiceTestTaco;
enum class DownloadServiceStatus {
// The download service is booting up.
INITIALIZING,
......@@ -66,9 +63,6 @@ class PrefetchDownloaderImpl : public PrefetchDownloader {
UNAVAILABLE,
};
// For test only.
explicit PrefetchDownloaderImpl(version_info::Channel channel);
// Callback for StartDownload.
void OnStartDownload(const std::string& download_id,
download::DownloadParams::StartResult result);
......
......@@ -14,67 +14,8 @@ namespace offline_pages {
PrefetchItem::PrefetchItem() = default;
PrefetchItem::PrefetchItem(const PrefetchItem& other) = default;
PrefetchItem::PrefetchItem(PrefetchItem&& other) = default;
PrefetchItem::~PrefetchItem() = default;
PrefetchItem& PrefetchItem::operator=(const PrefetchItem& other) = default;
PrefetchItem& PrefetchItem::operator=(PrefetchItem&& other) = default;
bool PrefetchItem::operator==(const PrefetchItem& other) const {
return offline_id == other.offline_id && guid == other.guid &&
client_id == other.client_id && state == other.state &&
url == other.url && final_archived_url == other.final_archived_url &&
generate_bundle_attempts == other.generate_bundle_attempts &&
get_operation_attempts == other.get_operation_attempts &&
download_initiation_attempts == other.download_initiation_attempts &&
operation_name == other.operation_name &&
archive_body_name == other.archive_body_name &&
archive_body_length == other.archive_body_length &&
creation_time == other.creation_time &&
freshness_time == other.freshness_time &&
error_code == other.error_code && title == other.title &&
file_path == other.file_path && file_size == other.file_size;
}
bool PrefetchItem::operator!=(const PrefetchItem& other) const {
return !(*this == other);
}
bool PrefetchItem::operator<(const PrefetchItem& other) const {
return offline_id < other.offline_id;
}
std::string PrefetchItem::ToString() const {
std::string s("PrefetchItem(");
s.append(base::Int64ToString(offline_id)).append(", ");
s.append(guid).append(", ");
s.append(client_id.ToString()).append(", ");
s.append(base::IntToString(static_cast<int>(state))).append(", ");
s.append(url.possibly_invalid_spec()).append(", ");
s.append(final_archived_url.possibly_invalid_spec()).append(", ");
s.append(base::IntToString(generate_bundle_attempts)).append(", ");
s.append(base::IntToString(get_operation_attempts)).append(", ");
s.append(base::IntToString(download_initiation_attempts)).append(", ");
s.append(operation_name).append(", ");
s.append(archive_body_name).append(", ");
s.append(base::IntToString(archive_body_length)).append(", ");
s.append(base::Int64ToString(store_utils::ToDatabaseTime(creation_time)))
.append(", ");
s.append(base::Int64ToString(store_utils::ToDatabaseTime(freshness_time)))
.append(", ");
s.append(base::IntToString(static_cast<int>(error_code))).append(", ");
s.append(base::UTF16ToUTF8(title)).append(", ");
s.append(file_path.AsUTF8Unsafe()).append(", ");
s.append(base::IntToString(static_cast<int>(file_size))).append(")");
return s;
}
std::ostream& operator<<(std::ostream& out, const PrefetchItem& pi) {
return out << pi.ToString();
}
} // namespace offline_pages
......@@ -24,18 +24,17 @@ namespace offline_pages {
// inserted into) the persistent prefetching data store.
struct PrefetchItem {
PrefetchItem();
PrefetchItem(const PrefetchItem& other);
PrefetchItem(PrefetchItem&& other);
~PrefetchItem();
// These methods are implemented in test_util.cc, for testing only.
PrefetchItem(const PrefetchItem& other);
PrefetchItem& operator=(const PrefetchItem& other);
PrefetchItem& operator=(PrefetchItem&& other);
bool operator==(const PrefetchItem& other) const;
bool operator!=(const PrefetchItem& other) const;
bool operator<(const PrefetchItem& other) const;
std::string ToString() const;
// Primary key that stays consistent between prefetch item, request and
......@@ -116,6 +115,7 @@ struct PrefetchItem {
int64_t file_size = -1;
};
// Provided for test only. Implemented in test_util.cc.
std::ostream& operator<<(std::ostream& out, const PrefetchItem& pi);
} // namespace offline_pages
......
......@@ -22,6 +22,8 @@
#include "components/offline_pages/core/prefetch/prefetch_service_impl.h"
#include "components/offline_pages/core/prefetch/store/prefetch_store.h"
#include "components/offline_pages/core/prefetch/suggested_articles_observer.h"
#include "components/offline_pages/core/prefetch/test_download_client.h"
#include "components/offline_pages/core/prefetch/test_download_service.h"
#include "components/offline_pages/core/prefetch/test_offline_metrics_collector.h"
#include "components/offline_pages/core/prefetch/test_prefetch_dispatcher.h"
#include "components/offline_pages/core/prefetch/test_prefetch_gcm_handler.h"
......@@ -74,8 +76,12 @@ PrefetchServiceTestTaco::PrefetchServiceTestTaco() {
prefetch_store_ =
std::make_unique<PrefetchStore>(base::ThreadTaskRunnerHandle::Get());
suggested_articles_observer_ = std::make_unique<SuggestedArticlesObserver>();
prefetch_downloader_ =
base::WrapUnique(new PrefetchDownloaderImpl(kTestChannel));
download_service_ = std::make_unique<TestDownloadService>();
prefetch_downloader_ = base::WrapUnique(
new PrefetchDownloaderImpl(download_service_.get(), kTestChannel));
download_client_ =
std::make_unique<TestDownloadClient>(prefetch_downloader_.get());
download_service_->SetClient(download_client_.get());
prefetch_importer_ = std::make_unique<TestPrefetchImporter>();
// This sets up the testing articles as an empty vector, we can ignore the
// result here. This allows us to not create a ContentSuggestionsService.
......@@ -92,30 +98,35 @@ PrefetchServiceTestTaco::~PrefetchServiceTestTaco() = default;
void PrefetchServiceTestTaco::SetOfflineMetricsCollector(
std::unique_ptr<OfflineMetricsCollector> metrics_collector) {
CHECK(!prefetch_service_);
CHECK(metrics_collector);
metrics_collector_ = std::move(metrics_collector);
}
void PrefetchServiceTestTaco::SetPrefetchDispatcher(
std::unique_ptr<PrefetchDispatcher> dispatcher) {
CHECK(!prefetch_service_);
CHECK(dispatcher);
dispatcher_ = std::move(dispatcher);
}
void PrefetchServiceTestTaco::SetPrefetchGCMHandler(
std::unique_ptr<PrefetchGCMHandler> gcm_handler) {
CHECK(!prefetch_service_);
CHECK(gcm_handler);
gcm_handler_ = std::move(gcm_handler);
}
void PrefetchServiceTestTaco::SetPrefetchNetworkRequestFactory(
std::unique_ptr<PrefetchNetworkRequestFactory> network_request_factory) {
CHECK(!prefetch_service_);
CHECK(network_request_factory);
network_request_factory_ = std::move(network_request_factory);
}
void PrefetchServiceTestTaco::SetPrefetchStore(
std::unique_ptr<PrefetchStore> prefetch_store) {
CHECK(!prefetch_service_);
CHECK(prefetch_store);
prefetch_store_ = std::move(prefetch_store);
}
......@@ -128,6 +139,7 @@ void PrefetchServiceTestTaco::SetSuggestedArticlesObserver(
void PrefetchServiceTestTaco::SetPrefetchDownloader(
std::unique_ptr<PrefetchDownloader> prefetch_downloader) {
CHECK(!prefetch_service_);
CHECK(prefetch_downloader);
prefetch_downloader_ = std::move(prefetch_downloader);
}
......@@ -164,10 +176,7 @@ void PrefetchServiceTestTaco::SetOfflinePageModel(
}
void PrefetchServiceTestTaco::CreatePrefetchService() {
CHECK(metrics_collector_ && dispatcher_ && gcm_handler_ &&
network_request_factory_ && prefetch_store_ &&
suggested_articles_observer_ && prefetch_downloader_);
CHECK(!prefetch_service_);
prefetch_service_ = std::make_unique<PrefetchServiceImpl>(
std::move(metrics_collector_), std::move(dispatcher_),
std::move(gcm_handler_), std::move(network_request_factory_),
......
......@@ -24,6 +24,8 @@ class PrefetchNetworkRequestFactory;
class PrefetchService;
class PrefetchStore;
class SuggestedArticlesObserver;
class TestDownloadClient;
class TestDownloadService;
class ThumbnailFetcher;
// The taco class acts as a wrapper around the prefetch service making
......@@ -78,6 +80,8 @@ class PrefetchServiceTestTaco {
return prefetch_service_.get();
}
TestDownloadService* download_service() { return download_service_.get(); }
// Creates and returns the ownership of the created PrefetchService instance.
// Leaves the taco empty, not usable.
std::unique_ptr<PrefetchService> CreateAndReturnPrefetchService();
......@@ -97,6 +101,8 @@ class PrefetchServiceTestTaco {
std::unique_ptr<PrefetchService> prefetch_service_;
std::unique_ptr<ThumbnailFetcher> thumbnail_fetcher_;
std::unique_ptr<OfflinePageModel> offline_page_model_;
std::unique_ptr<TestDownloadService> download_service_;
std::unique_ptr<TestDownloadClient> download_client_;
};
} // namespace offline_pages
......
......@@ -6,6 +6,127 @@
namespace offline_pages {
namespace {
std::string PrefetchEnumToString(PrefetchBackgroundTaskRescheduleType value) {
switch (value) {
case PrefetchBackgroundTaskRescheduleType::NO_RESCHEDULE:
return "NO_RESCHEDULE";
case PrefetchBackgroundTaskRescheduleType::RESCHEDULE_WITHOUT_BACKOFF:
return "RESCHEDULE_WITHOUT_BACKOFF";
case PrefetchBackgroundTaskRescheduleType::RESCHEDULE_WITH_BACKOFF:
return "RESCHEDULE_WITH_BACKOFF";
case PrefetchBackgroundTaskRescheduleType::RESCHEDULE_DUE_TO_SYSTEM:
return "RESCHEDULE_DUE_TO_SYSTEM";
case PrefetchBackgroundTaskRescheduleType::SUSPEND:
return "SUSPEND";
}
CHECK(false) << static_cast<int>(value) << " not valid enum value";
}
std::string PrefetchEnumToString(PrefetchRequestStatus value) {
switch (value) {
case PrefetchRequestStatus::SUCCESS:
return "SUCCESS";
case PrefetchRequestStatus::SHOULD_RETRY_WITHOUT_BACKOFF:
return "SHOULD_RETRY_WITHOUT_BACKOFF";
case PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF:
return "SHOULD_RETRY_WITH_BACKOFF";
case PrefetchRequestStatus::SHOULD_SUSPEND:
return "SHOULD_SUSPEND";
case PrefetchRequestStatus::COUNT:
return "COUNT";
}
CHECK(false) << static_cast<int>(value) << " not valid enum value";
}
std::string PrefetchEnumToString(RenderStatus value) {
switch (value) {
case RenderStatus::RENDERED:
return "RENDERED";
case RenderStatus::PENDING:
return "PENDING";
case RenderStatus::FAILED:
return "FAILED";
case RenderStatus::EXCEEDED_LIMIT:
return "EXCEEDED_LIMIT";
}
CHECK(false) << static_cast<int>(value) << " not valid enum value";
}
std::string PrefetchEnumToString(PrefetchItemState value) {
switch (value) {
case PrefetchItemState::NEW_REQUEST:
return "NEW_REQUEST";
case PrefetchItemState::SENT_GENERATE_PAGE_BUNDLE:
return "SENT_GENERATE_PAGE_BUNDLE";
case PrefetchItemState::AWAITING_GCM:
return "AWAITING_GCM";
case PrefetchItemState::RECEIVED_GCM:
return "RECEIVED_GCM";
case PrefetchItemState::SENT_GET_OPERATION:
return "SENT_GET_OPERATION";
case PrefetchItemState::RECEIVED_BUNDLE:
return "RECEIVED_BUNDLE";
case PrefetchItemState::DOWNLOADING:
return "DOWNLOADING";
case PrefetchItemState::DOWNLOADED:
return "DOWNLOADED";
case PrefetchItemState::IMPORTING:
return "IMPORTING";
case PrefetchItemState::FINISHED:
return "FINISHED";
case PrefetchItemState::ZOMBIE:
return "ZOMBIE";
}
CHECK(false) << static_cast<int>(value) << " not valid enum value";
}
std::string PrefetchEnumToString(PrefetchItemErrorCode value) {
switch (value) {
case PrefetchItemErrorCode::SUCCESS:
return "SUCCESS";
case PrefetchItemErrorCode::TOO_MANY_NEW_URLS:
return "TOO_MANY_NEW_URLS";
case PrefetchItemErrorCode::DOWNLOAD_ERROR:
return "DOWNLOAD_ERROR";
case PrefetchItemErrorCode::IMPORT_ERROR:
return "IMPORT_ERROR";
case PrefetchItemErrorCode::ARCHIVING_FAILED:
return "ARCHIVING_FAILED";
case PrefetchItemErrorCode::ARCHIVING_LIMIT_EXCEEDED:
return "ARCHIVING_LIMIT_EXCEEDED";
case PrefetchItemErrorCode::STALE_AT_NEW_REQUEST:
return "STALE_AT_NEW_REQUEST";
case PrefetchItemErrorCode::STALE_AT_AWAITING_GCM:
return "STALE_AT_AWAITING_GCM";
case PrefetchItemErrorCode::STALE_AT_RECEIVED_GCM:
return "STALE_AT_RECEIVED_GCM";
case PrefetchItemErrorCode::STALE_AT_RECEIVED_BUNDLE:
return "STALE_AT_RECEIVED_BUNDLE";
case PrefetchItemErrorCode::STALE_AT_DOWNLOADING:
return "STALE_AT_DOWNLOADING";
case PrefetchItemErrorCode::STALE_AT_IMPORTING:
return "STALE_AT_IMPORTING";
case PrefetchItemErrorCode::STALE_AT_UNKNOWN:
return "STALE_AT_UNKNOWN";
case PrefetchItemErrorCode::GET_OPERATION_MAX_ATTEMPTS_REACHED:
return "GET_OPERATION_MAX_ATTEMPTS_REACHED";
case PrefetchItemErrorCode::
GENERATE_PAGE_BUNDLE_REQUEST_MAX_ATTEMPTS_REACHED:
return "GENERATE_PAGE_BUNDLE_REQUEST_MAX_ATTEMPTS_REACHED";
case PrefetchItemErrorCode::DOWNLOAD_MAX_ATTEMPTS_REACHED:
return "DOWNLOAD_MAX_ATTEMPTS_REACHED";
case PrefetchItemErrorCode::MAXIMUM_CLOCK_BACKWARD_SKEW_EXCEEDED:
return "MAXIMUM_CLOCK_BACKWARD_SKEW_EXCEEDED";
case PrefetchItemErrorCode::IMPORT_LOST:
return "IMPORT_LOST";
case PrefetchItemErrorCode::SUGGESTION_INVALIDATED:
return "SUGGESTION_INVALIDATED";
}
CHECK(false) << static_cast<int>(value) << " not valid enum value";
}
} // namespace
RenderPageInfo::RenderPageInfo() = default;
RenderPageInfo::RenderPageInfo(const RenderPageInfo& other) = default;
......@@ -40,4 +161,21 @@ bool PrefetchArchiveInfo::empty() const {
return offline_id == 0;
}
std::ostream& operator<<(std::ostream& out,
PrefetchBackgroundTaskRescheduleType value) {
return out << PrefetchEnumToString(value);
}
std::ostream& operator<<(std::ostream& out, PrefetchRequestStatus value) {
return out << PrefetchEnumToString(value);
}
std::ostream& operator<<(std::ostream& out, RenderStatus value) {
return out << PrefetchEnumToString(value);
}
std::ostream& operator<<(std::ostream& out, const PrefetchItemState& value) {
return out << PrefetchEnumToString(value);
}
std::ostream& operator<<(std::ostream& out, PrefetchItemErrorCode value) {
return out << PrefetchEnumToString(value);
}
} // namespace offline_pages
......@@ -255,6 +255,15 @@ struct PrefetchArchiveInfo {
int64_t file_size = 0;
};
// These operators are implemented for testing only, see test_util.cc.
// They are provided here to avoid ODR problems.
std::ostream& operator<<(std::ostream& out,
PrefetchBackgroundTaskRescheduleType value);
std::ostream& operator<<(std::ostream& out, PrefetchRequestStatus value);
std::ostream& operator<<(std::ostream& out, RenderStatus value);
std::ostream& operator<<(std::ostream& out, const PrefetchItemState& value);
std::ostream& operator<<(std::ostream& out, PrefetchItemErrorCode value);
} // namespace offline_pages
#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_TYPES_H_
......@@ -256,6 +256,18 @@ std::size_t PrefetchStoreTestUtil::GetAllItems(
return items_count;
}
std::string PrefetchStoreTestUtil::ToString() {
std::string result = "PrefetchItems: [";
std::set<PrefetchItem> items;
GetAllItems(&items);
for (const auto& item : items) {
result += "\n";
result += item.ToString();
}
result += "\n]";
return result;
}
int PrefetchStoreTestUtil::ZombifyPrefetchItems(const std::string& name_space,
const GURL& url) {
int count = -1;
......
......@@ -61,6 +61,9 @@ class PrefetchStoreTestUtil {
// Returns the number of items found.
std::size_t GetAllItems(std::set<PrefetchItem>* all_items);
// Prints a representation of the prefetch store contents.
std::string ToString();
// Sets to the ZOMBIE state entries identified by |name_space| and
// |url|, returning the number of entries found.
int ZombifyPrefetchItems(const std::string& name_space, const GURL& url);
......
// Copyright 2018 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/prefetch/test_download_service.h"
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/bind_test_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/download/public/background_service/download_metadata.h"
#include "components/download/public/background_service/service_config.h"
#include "components/offline_pages/core/prefetch/test_download_client.h"
namespace offline_pages {
namespace {
// Implementation of ServiceConfig used for testing. This is never actually
// constructed.
class TestServiceConfig : public download::ServiceConfig {
public:
TestServiceConfig() = default;
~TestServiceConfig() override = default;
// ServiceConfig implementation.
uint32_t GetMaxScheduledDownloadsPerClient() const override { return 0; }
uint32_t GetMaxConcurrentDownloads() const override { return 0; }
const base::TimeDelta& GetFileKeepAliveTime() const override {
return time_delta_;
}
private:
base::TimeDelta time_delta_;
DISALLOW_COPY_AND_ASSIGN(TestServiceConfig);
};
} // namespace
TestDownloadService::TestDownloadService() = default;
TestDownloadService::~TestDownloadService() = default;
const download::ServiceConfig& TestDownloadService::GetConfig() {
NOTIMPLEMENTED();
static TestServiceConfig config;
return config;
}
void TestDownloadService::StartDownload(
const download::DownloadParams& download_params) {
if (!download_dir_.IsValid())
DCHECK(download_dir_.CreateUniqueTempDir());
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindRepeating(download_params.callback, download_params.guid,
download::DownloadParams::ACCEPTED));
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&TestDownloadService::FinishDownload,
base::Unretained(this), download_params.guid));
}
void TestDownloadService::FinishDownload(const std::string& guid) {
base::FilePath path = download_dir_.GetPath().AppendASCII(
base::StrCat({"dl_", base::NumberToString(next_file_id_++)}));
const int file_size = static_cast<int>(test_file_data_.size());
CHECK_EQ(file_size, base::WriteFile(path, test_file_data_.data(), file_size));
client_->OnDownloadSucceeded(
guid, download::CompletionInfo(path, test_file_data_.size()));
}
void TestDownloadService::SetTestFileData(const std::string& data) {
test_file_data_ = data;
}
void TestDownloadService::OnStartScheduledTask(
download::DownloadTaskType task_type,
const download::TaskFinishedCallback& callback) {
NOTIMPLEMENTED();
}
bool TestDownloadService::OnStopScheduledTask(
download::DownloadTaskType task_type) {
NOTIMPLEMENTED();
return false;
}
download::DownloadService::ServiceStatus TestDownloadService::GetStatus() {
NOTIMPLEMENTED();
return DownloadService::ServiceStatus();
}
void TestDownloadService::PauseDownload(const std::string& guid) {
NOTIMPLEMENTED();
}
void TestDownloadService::ResumeDownload(const std::string& guid) {
NOTIMPLEMENTED();
}
void TestDownloadService::CancelDownload(const std::string& guid) {
NOTIMPLEMENTED();
}
void TestDownloadService::ChangeDownloadCriteria(
const std::string& guid,
const download::SchedulingParams& params) {
NOTIMPLEMENTED();
}
download::Logger* TestDownloadService::GetLogger() {
NOTIMPLEMENTED();
return nullptr;
}
} // namespace offline_pages
// Copyright 2018 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.
#ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TEST_DOWNLOAD_SERVICE_H_
#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TEST_DOWNLOAD_SERVICE_H_
#include <list>
#include "base/files/scoped_temp_dir.h"
#include "base/optional.h"
#include "components/download/public/background_service/client.h"
#include "components/download/public/background_service/download_params.h"
#include "components/download/public/background_service/download_service.h"
#include "components/offline_pages/core/prefetch/test_download_client.h"
namespace offline_pages {
// Implementation of DownloadService used for testing.
class TestDownloadService : public download::DownloadService {
public:
explicit TestDownloadService();
~TestDownloadService() override;
// DownloadService implementation.
const download::ServiceConfig& GetConfig() override;
void OnStartScheduledTask(
download::DownloadTaskType task_type,
const download::TaskFinishedCallback& callback) override;
bool OnStopScheduledTask(download::DownloadTaskType task_type) override;
DownloadService::ServiceStatus GetStatus() override;
void StartDownload(const download::DownloadParams& download_params) override;
void PauseDownload(const std::string& guid) override;
void ResumeDownload(const std::string& guid) override;
void CancelDownload(const std::string& guid) override;
void ChangeDownloadCriteria(
const std::string& guid,
const download::SchedulingParams& params) override;
download::Logger* GetLogger() override;
void SetClient(TestDownloadClient* client) { client_ = client; }
// Sets the content saved for downloads requested through StartDownload.
void SetTestFileData(const std::string& data);
private:
void FinishDownload(const std::string& guid);
base::ScopedTempDir download_dir_;
TestDownloadClient* client_ = nullptr;
int next_file_id_ = 0;
std::string test_file_data_;
DISALLOW_COPY_AND_ASSIGN(TestDownloadService);
};
} // namespace offline_pages
#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_TEST_DOWNLOAD_SERVICE_H_
// Copyright 2018 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 <sstream>
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/offline_pages/core/offline_store_utils.h"
#include "components/offline_pages/core/prefetch/prefetch_item.h"
namespace offline_pages {
std::string PrefetchItem::ToString() const {
std::stringstream s;
s << "PrefetchItem(id=" << offline_id << ", guid=" << guid << ", "
<< client_id << ", state=" << state
<< ", url=" << url.possibly_invalid_spec()
<< ", final_url=" << final_archived_url.possibly_invalid_spec()
<< ", gb_attempts=" << generate_bundle_attempts
<< ", get_attempts=" << get_operation_attempts
<< ", dl_attempts=" << download_initiation_attempts
<< ", operation=" << operation_name << ", body_name=" << archive_body_name
<< ", body_len=" << archive_body_length
<< ", creation_time=" << store_utils::ToDatabaseTime(creation_time)
<< ", freshness_time=" << store_utils::ToDatabaseTime(freshness_time)
<< ", error=" << error_code << ", title=" << base::UTF16ToUTF8(title)
<< ", file_path=" << file_path.AsUTF8Unsafe() << ", file_size=" << file_size
<< ")";
return s.str();
}
std::ostream& operator<<(std::ostream& out, const PrefetchItem& pi) {
return out << pi.ToString();
}
PrefetchItem::PrefetchItem(const PrefetchItem& other) = default;
PrefetchItem& PrefetchItem::operator=(const PrefetchItem& other) = default;
PrefetchItem& PrefetchItem::operator=(PrefetchItem&& other) = default;
bool PrefetchItem::operator==(const PrefetchItem& other) const {
return offline_id == other.offline_id && guid == other.guid &&
client_id == other.client_id && state == other.state &&
url == other.url && final_archived_url == other.final_archived_url &&
generate_bundle_attempts == other.generate_bundle_attempts &&
get_operation_attempts == other.get_operation_attempts &&
download_initiation_attempts == other.download_initiation_attempts &&
operation_name == other.operation_name &&
archive_body_name == other.archive_body_name &&
archive_body_length == other.archive_body_length &&
creation_time == other.creation_time &&
freshness_time == other.freshness_time &&
error_code == other.error_code && title == other.title &&
file_path == other.file_path && file_size == other.file_size;
}
bool PrefetchItem::operator!=(const PrefetchItem& other) const {
return !(*this == other);
}
bool PrefetchItem::operator<(const PrefetchItem& other) const {
return offline_id < other.offline_id;
}
} // namespace offline_pages
......@@ -12,6 +12,10 @@ StubOfflinePageModel::StubOfflinePageModel()
: archive_directory_(base::FilePath(FILE_PATH_LITERAL("/archive_dir/"))) {}
StubOfflinePageModel::~StubOfflinePageModel() {}
void StubOfflinePageModel::SetArchiveDirectory(const base::FilePath& path) {
archive_directory_ = path;
}
void StubOfflinePageModel::AddObserver(Observer* observer) {}
void StubOfflinePageModel::RemoveObserver(Observer* observer) {}
void StubOfflinePageModel::SavePage(
......
......@@ -22,6 +22,8 @@ class StubOfflinePageModel : public OfflinePageModel {
StubOfflinePageModel();
~StubOfflinePageModel() override;
void SetArchiveDirectory(const base::FilePath& path);
void AddObserver(Observer* observer) override;
void RemoveObserver(Observer* observer) override;
void SavePage(const SavePageParams& save_page_params,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment