blob: 7104293473a5086015bfa61a49e9fd1ce2d15a6b [file] [log] [blame]
// Copyright 2019 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/previews/content/hints_fetcher.h"
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "components/previews/content/hint_cache.h"
#include "components/previews/core/previews_experiments.h"
#include "components/previews/core/previews_features.h"
#include "net/base/url_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace previews {
constexpr char optimization_guide_service_url[] = "https://hintsserver.com/";
class HintsFetcherTest : public testing::Test {
public:
explicit HintsFetcherTest()
: shared_url_loader_factory_(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_)) {
base::test::ScopedFeatureList scoped_list;
scoped_list.InitAndEnableFeatureWithParameters(
features::kOptimizationHintsFetching, {});
hints_fetcher_ = std::make_unique<HintsFetcher>(
shared_url_loader_factory_, GURL(optimization_guide_service_url));
}
~HintsFetcherTest() override {}
void OnHintsFetched(
base::Optional<
std::unique_ptr<optimization_guide::proto::GetHintsResponse>>
get_hints_response) {
if (get_hints_response)
hints_fetched_ = true;
}
bool hints_fetched() { return hints_fetched_; }
protected:
bool FetchHints(const std::vector<std::string>& hosts) {
bool status = hints_fetcher_->FetchOptimizationGuideServiceHints(
hosts, base::BindOnce(&HintsFetcherTest::OnHintsFetched,
base::Unretained(this)));
RunUntilIdle();
return status;
}
// Return a 200 response with provided content to any pending requests.
bool SimulateResponse(const std::string& content,
net::HttpStatusCode http_status) {
return test_url_loader_factory_.SimulateResponseForPendingRequest(
optimization_guide_service_url, content, http_status,
network::TestURLLoaderFactory::kUrlMatchPrefix);
}
void VerifyHasPendingFetchRequests() {
EXPECT_GE(test_url_loader_factory_.NumPending(), 1);
std::string key_value;
for (const auto& pending_request :
*test_url_loader_factory_.pending_requests()) {
EXPECT_EQ(pending_request.request.method, "POST");
EXPECT_TRUE(net::GetValueForKeyInQuery(pending_request.request.url, "key",
&key_value));
}
}
private:
void RunUntilIdle() {
scoped_task_environment_.RunUntilIdle();
base::RunLoop().RunUntilIdle();
}
bool hints_fetched_ = false;
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<HintsFetcher> hints_fetcher_;
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
network::TestURLLoaderFactory test_url_loader_factory_;
DISALLOW_COPY_AND_ASSIGN(HintsFetcherTest);
};
TEST_F(HintsFetcherTest, FetchOptimizationGuideServiceHints) {
std::string response_content;
EXPECT_TRUE(FetchHints(std::vector<std::string>()));
VerifyHasPendingFetchRequests();
EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
EXPECT_TRUE(hints_fetched());
}
// Tests to ensure that multiple hint fetches by the same object cannot be in
// progress simultaneously.
TEST_F(HintsFetcherTest, FetchInProcess) {
std::string response_content;
// Fetch back to back without waiting for Fetch to complete,
// |fetch_in_progress_| should cause early exit.
EXPECT_TRUE(FetchHints(std::vector<std::string>()));
EXPECT_FALSE(FetchHints(std::vector<std::string>()));
// Once response arrives, check to make sure a new fetch can start.
SimulateResponse(response_content, net::HTTP_OK);
EXPECT_TRUE(FetchHints(std::vector<std::string>()));
}
// Tests 404 response from request.
TEST_F(HintsFetcherTest, FetchReturned404) {
std::string response_content;
EXPECT_TRUE(FetchHints(std::vector<std::string>()));
// Send a 404 to HintsFetcher.
SimulateResponse(response_content, net::HTTP_NOT_FOUND);
EXPECT_FALSE(hints_fetched());
}
TEST_F(HintsFetcherTest, FetchReturnBadResponse) {
std::string response_content = "not proto";
EXPECT_TRUE(FetchHints(std::vector<std::string>()));
VerifyHasPendingFetchRequests();
EXPECT_TRUE(SimulateResponse(response_content, net::HTTP_OK));
EXPECT_FALSE(hints_fetched());
}
} // namespace previews