blob: b3881966cddece946f8663d848a87f707cf6b112 [file] [log] [blame]
// Copyright 2016 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/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl.h"
#include <stdint.h>
#include <list>
#include <memory>
#include <string>
#include "base/command_line.h"
#include "base/metrics/field_trial.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/system/sys_info.h"
#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/data_reduction_proxy/content/browser/data_reduction_proxy_page_load_timing.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
#include "components/data_reduction_proxy/proto/client_config.pb.h"
#include "components/data_reduction_proxy/proto/pageload_metrics.pb.h"
#include "components/previews/core/previews_lite_page_redirect.h"
#include "content/public/common/child_process_host.h"
#include "net/base/net_errors.h"
#include "net/base/network_change_notifier.h"
#include "net/nqe/effective_connection_type.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 "services/network/test/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace data_reduction_proxy {
namespace {
static const char kHistogramSucceeded[] =
"DataReductionProxy.Pingback.Succeeded";
static const char kHistogramAttempted[] =
"DataReductionProxy.Pingback.Attempted";
static const char kSessionKey[] = "fake-session";
static const char kFakeURL[] = "http://www.google.com/";
static const char kChannel[] = "channel";
static const int64_t kBytes = 10000;
static const int64_t kBytesOriginal = 1000000;
static const int64_t kTotalPageSizeBytes = 20000;
static const float kCachedFraction = 0.5;
static const int kCrashProcessId = 1;
static const int64_t kRendererMemory = 1024;
static const int64_t kTouchCount = 10;
static const int64_t kScrollCount = 20;
static const int64_t kRedirectCount = 1;
} // namespace
// Controls whether a pingback is sent or not.
class TestDataReductionProxyPingbackClientImpl
: public DataReductionProxyPingbackClientImpl {
public:
TestDataReductionProxyPingbackClientImpl(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner)
: DataReductionProxyPingbackClientImpl(url_loader_factory,
std::move(thread_task_runner),
kChannel),
should_override_random_(false),
override_value_(0.0f),
current_time_(base::Time::Now()) {}
// Overrides the bahvior of the random float generator in
// DataReductionProxyPingbackClientImpl.
// If |should_override_random| is true, the typically random value that is
// compared with reporting fraction will deterministically be
// |override_value|.
void OverrideRandom(bool should_override_random, float override_value) {
should_override_random_ = should_override_random;
override_value_ = override_value;
}
// Sets the time used for the metrics reporting time.
void set_current_time(base::Time current_time) {
current_time_ = current_time;
}
private:
float GenerateRandomFloat() const override {
if (should_override_random_)
return override_value_;
return DataReductionProxyPingbackClientImpl::GenerateRandomFloat();
}
base::Time CurrentTime() const override { return current_time_; }
bool should_override_random_;
float override_value_;
base::Time current_time_;
};
class DataReductionProxyPingbackClientImplTest : public testing::Test {
public:
DataReductionProxyPingbackClientImplTest()
: scoped_task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
base::test::ScopedTaskEnvironment::ExecutionMode::ASYNC) {}
TestDataReductionProxyPingbackClientImpl* pingback_client() const {
return pingback_client_.get();
}
GURL pingback_url() { return util::AddApiKeyToUrl(params::GetPingbackURL()); }
void Init() {
factory()->AddResponse(pingback_url().spec(), "");
num_network_requests_ = 0;
factory()->SetInterceptor(base::BindLambdaForTesting(
[&](const network::ResourceRequest& request) {
intercepted_url_ = request.url;
intercepted_headers_ = request.headers;
intercepted_body_ = network::GetUploadData(request);
++num_network_requests_;
}));
test_shared_loader_factory_ =
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_);
pingback_client_ =
std::make_unique<TestDataReductionProxyPingbackClientImpl>(
test_shared_loader_factory_,
scoped_task_environment_.GetMainThreadTaskRunner());
page_id_ = 0u;
}
void CreateAndSendPingback(bool lofi_received,
bool client_lofi_requested,
bool lite_page_received,
bool app_background_occurred,
bool opt_out_occurred,
bool crash,
bool black_listed) {
timing_ = std::make_unique<DataReductionProxyPageLoadTiming>(
base::Time::FromJsTime(1500) /* navigation_start */,
base::Optional<base::TimeDelta>(
base::TimeDelta::FromMilliseconds(1600)) /* response_start */,
base::Optional<base::TimeDelta>(
base::TimeDelta::FromMilliseconds(1700)) /* load_event_start */,
base::Optional<base::TimeDelta>(
base::TimeDelta::FromMilliseconds(1800)) /* first_image_paint */,
base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
1900)) /* first_contentful_paint */,
base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
2000)) /* experimental_first_meaningful_paint */,
base::Optional<base::TimeDelta>(
base::TimeDelta::FromMilliseconds(3000)) /* first_input_delay */,
base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
100)) /* parse_blocked_on_script_load_duration */,
base::Optional<base::TimeDelta>(
base::TimeDelta::FromMilliseconds(2000)) /* parse_stop */,
base::Optional<base::TimeDelta>(
base::TimeDelta::FromMilliseconds(5000)) /* page_end_time */,
base::Optional<base::TimeDelta>(base::TimeDelta::FromMilliseconds(
6000)) /* lite_page_redirect_penalty */,
base::Optional<previews::ServerLitePageStatus>(
previews::ServerLitePageStatus::
kSuccess) /* lite_page_redirect_status */,
base::TimeDelta::FromMilliseconds(
100) /* navigation_start_to_main_frame_fetch_start */,
kBytes /* network_bytes */, kBytesOriginal /* original_network_bytes */,
kTotalPageSizeBytes /* total_page_size_bytes */,
kCachedFraction /* cached_fraction */, app_background_occurred,
opt_out_occurred, kRendererMemory,
crash ? kCrashProcessId : content::ChildProcessHost::kInvalidUniqueID,
PageloadMetrics_PageEndReason_END_NONE, kTouchCount /* touch_count */,
kScrollCount /* scroll_count */, kRedirectCount /* redirect_count */);
DataReductionProxyData request_data;
request_data.set_session_key(kSessionKey);
request_data.set_request_url(GURL(kFakeURL));
request_data.set_effective_connection_type(
net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
request_data.set_connection_type(
net::NetworkChangeNotifier::CONNECTION_UNKNOWN);
request_data.set_lofi_received(lofi_received);
request_data.set_black_listed(black_listed);
request_data.set_client_lofi_requested(client_lofi_requested);
request_data.set_lite_page_received(lite_page_received);
request_data.set_page_id(page_id_);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SendPingback(request_data, *timing_);
page_id_++;
}
void WaitForPingbackResponse() {
base::RunLoop run_loop;
run_loop.RunUntilIdle();
}
// Send a fake crash report from crash_reporter.
void ReportCrash(bool oom) {
#if defined(OS_ANDROID)
crash_reporter::ChildExitObserver::TerminationInfo info;
crash_reporter::CrashMetricsReporter::ReportedCrashTypeSet types(
{oom ? crash_reporter::CrashMetricsReporter::ProcessedCrashCounts::
kRendererForegroundVisibleOom
: crash_reporter::CrashMetricsReporter::ProcessedCrashCounts::
kRendererForegroundVisibleCrash});
static_cast<crash_reporter::CrashMetricsReporter::Observer*>(
pingback_client_.get())
->OnCrashDumpProcessed(kCrashProcessId, types);
#endif
}
network::TestURLLoaderFactory* factory() { return &test_url_loader_factory_; }
const DataReductionProxyPageLoadTiming& timing() { return *timing_; }
const base::HistogramTester& histogram_tester() { return histogram_tester_; }
uint64_t page_id() const { return page_id_; }
GURL intercepted_url() { return intercepted_url_; }
std::string upload_content_type() {
std::string content_type;
intercepted_headers_.GetHeader(net::HttpRequestHeaders::kContentType,
&content_type);
return content_type;
}
std::string upload_data() { return intercepted_body_; }
int num_network_requests() { return num_network_requests_; }
protected:
base::test::ScopedTaskEnvironment scoped_task_environment_;
private:
network::TestURLLoaderFactory test_url_loader_factory_;
scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
std::unique_ptr<TestDataReductionProxyPingbackClientImpl> pingback_client_;
std::unique_ptr<DataReductionProxyPageLoadTiming> timing_;
base::HistogramTester histogram_tester_;
uint64_t page_id_;
GURL intercepted_url_;
net::HttpRequestHeaders intercepted_headers_;
std::string intercepted_body_;
int num_network_requests_;
};
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyPingbackContent) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
base::Time current_time = base::Time::UnixEpoch();
pingback_client()->set_current_time(current_time);
uint64_t data_page_id = page_id();
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
EXPECT_EQ(num_network_requests(), 1);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
EXPECT_EQ(current_time, protobuf_parser::TimestampToTime(
batched_request.metrics_sent_time()));
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(
timing().navigation_start,
protobuf_parser::TimestampToTime(pageload_metrics.first_request_time()));
EXPECT_EQ(timing().response_start.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.time_to_first_byte()));
EXPECT_EQ(
timing().load_event_start.value(),
protobuf_parser::DurationToTimeDelta(pageload_metrics.page_load_time()));
EXPECT_EQ(timing().first_image_paint.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.time_to_first_image_paint()));
EXPECT_EQ(timing().first_contentful_paint.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.time_to_first_contentful_paint()));
EXPECT_EQ(
timing().experimental_first_meaningful_paint.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.experimental_time_to_first_meaningful_paint()));
EXPECT_EQ(timing().first_input_delay.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.first_input_delay()));
EXPECT_EQ(timing().parse_blocked_on_script_load_duration.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.parse_blocked_on_script_load_duration()));
EXPECT_EQ(timing().parse_stop.value(), protobuf_parser::DurationToTimeDelta(
pageload_metrics.parse_stop()));
EXPECT_EQ(
timing().page_end_time.value(),
protobuf_parser::DurationToTimeDelta(pageload_metrics.page_end_time()));
EXPECT_EQ(HTTPSLitePagePreviewInfo_Status_SUCCESS,
pageload_metrics.https_litepage_info().status());
EXPECT_EQ(
// base::TimeDelta::FromMilliseconds(6000),
timing().lite_page_redirect_penalty.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.https_litepage_info().navigation_restart_penalty()));
EXPECT_EQ(timing().navigation_start_to_main_frame_fetch_start,
protobuf_parser::DurationToTimeDelta(
pageload_metrics.navigation_start_to_main_frame_fetch_start()));
EXPECT_EQ(kSessionKey, pageload_metrics.session_key());
EXPECT_EQ(kChannel, pageload_metrics.channel());
EXPECT_EQ(kFakeURL, pageload_metrics.first_request_url());
EXPECT_EQ(kBytes, pageload_metrics.compressed_page_size_bytes());
EXPECT_EQ(kBytesOriginal, pageload_metrics.original_page_size_bytes());
EXPECT_EQ(kTotalPageSizeBytes, pageload_metrics.total_page_size_bytes());
EXPECT_EQ(kTouchCount, pageload_metrics.touch_count());
EXPECT_EQ(kScrollCount, pageload_metrics.scroll_count());
EXPECT_EQ(kCachedFraction, pageload_metrics.cached_fraction());
EXPECT_EQ(kRedirectCount, pageload_metrics.redirect_count());
EXPECT_EQ(data_page_id, pageload_metrics.page_id());
EXPECT_EQ(PageloadMetrics_PreviewsType_NONE,
pageload_metrics.previews_type());
EXPECT_EQ(PageloadMetrics_PreviewsOptOut_UNKNOWN,
pageload_metrics.previews_opt_out());
EXPECT_EQ(
PageloadMetrics_EffectiveConnectionType_EFFECTIVE_CONNECTION_TYPE_OFFLINE,
pageload_metrics.effective_connection_type());
EXPECT_EQ(PageloadMetrics_ConnectionType_CONNECTION_UNKNOWN,
pageload_metrics.connection_type());
EXPECT_EQ(PageloadMetrics_PageEndReason_END_NONE,
pageload_metrics.page_end_reason());
EXPECT_EQ(kRendererMemory, pageload_metrics.renderer_memory_usage_kb());
EXPECT_EQ(std::string(), pageload_metrics.holdback_group());
EXPECT_EQ(PageloadMetrics_RendererCrashType_NO_CRASH,
pageload_metrics.renderer_crash_type());
EXPECT_EQ(base::SysInfo::AmountOfPhysicalMemory() / 1024,
batched_request.device_info().total_device_memory_kb());
WaitForPingbackResponse();
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, true, 1);
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyHoldback) {
base::FieldTrialList field_trial_list(nullptr);
ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
"DataCompressionProxyHoldback", "Enabled"));
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
EXPECT_EQ(num_network_requests(), 1);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ("Enabled", pageload_metrics.holdback_group());
WaitForPingbackResponse();
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, true, 1);
}
TEST_F(DataReductionProxyPingbackClientImplTest,
VerifyTwoPingbacksBatchedContent) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
base::Time current_time = base::Time::UnixEpoch();
pingback_client()->set_current_time(current_time);
// First pingback
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
// Two more pingbacks batched together.
std::list<uint64_t> page_ids;
page_ids.push_back(page_id());
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 2);
page_ids.push_back(page_id());
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 3);
EXPECT_EQ(num_network_requests(), 1);
WaitForPingbackResponse();
// Check the state of the second pingback.
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 2);
EXPECT_EQ(current_time, protobuf_parser::TimestampToTime(
batched_request.metrics_sent_time()));
EXPECT_EQ(base::SysInfo::AmountOfPhysicalMemory() / 1024,
batched_request.device_info().total_device_memory_kb());
// Verify the content of both pingbacks.
for (size_t i = 0; i < 2; ++i) {
PageloadMetrics pageload_metrics = batched_request.pageloads(i);
EXPECT_EQ(timing().navigation_start,
protobuf_parser::TimestampToTime(
pageload_metrics.first_request_time()));
EXPECT_EQ(timing().response_start.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.time_to_first_byte()));
EXPECT_EQ(timing().load_event_start.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.page_load_time()));
EXPECT_EQ(timing().first_image_paint.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.time_to_first_image_paint()));
EXPECT_EQ(timing().first_contentful_paint.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.time_to_first_contentful_paint()));
EXPECT_EQ(
timing().experimental_first_meaningful_paint.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.experimental_time_to_first_meaningful_paint()));
EXPECT_EQ(timing().first_input_delay.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.first_input_delay()));
EXPECT_EQ(timing().parse_blocked_on_script_load_duration.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.parse_blocked_on_script_load_duration()));
EXPECT_EQ(timing().parse_stop.value(), protobuf_parser::DurationToTimeDelta(
pageload_metrics.parse_stop()));
EXPECT_EQ(
timing().page_end_time.value(),
protobuf_parser::DurationToTimeDelta(pageload_metrics.page_end_time()));
EXPECT_EQ(HTTPSLitePagePreviewInfo_Status_SUCCESS,
pageload_metrics.https_litepage_info().status());
EXPECT_EQ(timing().lite_page_redirect_penalty.value(),
protobuf_parser::DurationToTimeDelta(
pageload_metrics.https_litepage_info()
.navigation_restart_penalty()));
EXPECT_EQ(
timing().navigation_start_to_main_frame_fetch_start,
protobuf_parser::DurationToTimeDelta(
pageload_metrics.navigation_start_to_main_frame_fetch_start()));
EXPECT_EQ(kSessionKey, pageload_metrics.session_key());
EXPECT_EQ(kChannel, pageload_metrics.channel());
EXPECT_EQ(kFakeURL, pageload_metrics.first_request_url());
EXPECT_EQ(kBytes, pageload_metrics.compressed_page_size_bytes());
EXPECT_EQ(kBytesOriginal, pageload_metrics.original_page_size_bytes());
EXPECT_EQ(kTotalPageSizeBytes, pageload_metrics.total_page_size_bytes());
EXPECT_EQ(kTouchCount, pageload_metrics.touch_count());
EXPECT_EQ(kScrollCount, pageload_metrics.scroll_count());
EXPECT_EQ(kRedirectCount, pageload_metrics.redirect_count());
EXPECT_EQ(kCachedFraction, pageload_metrics.cached_fraction());
EXPECT_EQ(page_ids.front(), pageload_metrics.page_id());
page_ids.pop_front();
EXPECT_EQ(
PageloadMetrics_EffectiveConnectionType_EFFECTIVE_CONNECTION_TYPE_OFFLINE,
pageload_metrics.effective_connection_type());
EXPECT_EQ(PageloadMetrics_ConnectionType_CONNECTION_UNKNOWN,
pageload_metrics.connection_type());
EXPECT_EQ(PageloadMetrics_PageEndReason_END_NONE,
pageload_metrics.page_end_reason());
EXPECT_EQ(kRendererMemory, pageload_metrics.renderer_memory_usage_kb());
}
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, true, 3);
}
TEST_F(DataReductionProxyPingbackClientImplTest, SendTwoPingbacks) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 2);
EXPECT_EQ(num_network_requests(), 1);
WaitForPingbackResponse();
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, true, 2);
histogram_tester().ExpectTotalCount(kHistogramAttempted, 2);
}
TEST_F(DataReductionProxyPingbackClientImplTest, NoPingbackSent) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(0.0f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, false, 1);
histogram_tester().ExpectTotalCount(kHistogramSucceeded, 0);
EXPECT_EQ(num_network_requests(), 0);
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyReportingBehvaior) {
Init();
EXPECT_EQ(num_network_requests(), 0);
// Verify that if the random number is less than the reporting fraction, the
// pingback is created.
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(0.5f);
pingback_client()->OverrideRandom(true, 0.4f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(num_network_requests(), 1);
WaitForPingbackResponse();
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, true, 1);
// Verify that if the random number is greater than the reporting fraction,
// the pingback is not created.
pingback_client()->OverrideRandom(true, 0.6f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectBucketCount(kHistogramAttempted, false, 1);
EXPECT_EQ(num_network_requests(), 1);
// Verify that if the random number is equal to the reporting fraction, the
// pingback is not created. Specifically, if the reporting fraction is zero,
// and the random number is zero, no pingback is sent.
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(0.0f);
pingback_client()->OverrideRandom(true, 0.0f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectBucketCount(kHistogramAttempted, false, 2);
EXPECT_EQ(num_network_requests(), 1);
// Verify that the command line flag forces a pingback.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
data_reduction_proxy::switches::kEnableDataReductionProxyForcePingback);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(0.0f);
pingback_client()->OverrideRandom(true, 1.0f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectBucketCount(kHistogramAttempted, true, 2);
EXPECT_EQ(num_network_requests(), 2);
WaitForPingbackResponse();
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, true, 2);
}
TEST_F(DataReductionProxyPingbackClientImplTest, FailedPingback) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
// Simulate a network error.
factory()->ClearResponses();
factory()->AddResponse(pingback_url().spec(), "", net::HTTP_UNAUTHORIZED);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(num_network_requests(), 1);
WaitForPingbackResponse();
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, false, 1);
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyLoFiContentNoOptOut) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
base::Time current_time = base::Time::UnixEpoch();
pingback_client()->set_current_time(current_time);
CreateAndSendPingback(
true /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
EXPECT_EQ(num_network_requests(), 1);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(PageloadMetrics_PreviewsType_LOFI,
pageload_metrics.previews_type());
EXPECT_EQ(PageloadMetrics_PreviewsOptOut_NON_OPT_OUT,
pageload_metrics.previews_opt_out());
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyLoFiContentOptOut) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
base::Time current_time = base::Time::UnixEpoch();
pingback_client()->set_current_time(current_time);
CreateAndSendPingback(
true /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
true /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
EXPECT_EQ(num_network_requests(), 1);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(PageloadMetrics_PreviewsType_LOFI,
pageload_metrics.previews_type());
EXPECT_EQ(PageloadMetrics_PreviewsOptOut_OPT_OUT,
pageload_metrics.previews_opt_out());
}
TEST_F(DataReductionProxyPingbackClientImplTest,
VerifyClientLoFiContentOptOut) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
base::Time current_time = base::Time::UnixEpoch();
pingback_client()->set_current_time(current_time);
CreateAndSendPingback(
false /* lofi_received */, true /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
true /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
EXPECT_EQ(num_network_requests(), 1);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(PageloadMetrics_PreviewsType_LOFI,
pageload_metrics.previews_type());
EXPECT_EQ(PageloadMetrics_PreviewsOptOut_OPT_OUT,
pageload_metrics.previews_opt_out());
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyLoFiContentBackground) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
base::Time current_time = base::Time::UnixEpoch();
pingback_client()->set_current_time(current_time);
CreateAndSendPingback(
true /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, true /* app_background_occurred */,
true /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
EXPECT_EQ(num_network_requests(), 1);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(PageloadMetrics_PreviewsType_LOFI,
pageload_metrics.previews_type());
EXPECT_EQ(PageloadMetrics_PreviewsOptOut_UNKNOWN,
pageload_metrics.previews_opt_out());
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyBlackListContent) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
base::Time current_time = base::Time::UnixEpoch();
pingback_client()->set_current_time(current_time);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, false /* renderer_crash */,
true /* black_listed */);
EXPECT_EQ(num_network_requests(), 1);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(PageloadMetrics_PreviewsType_CLIENT_BLACKLIST_PREVENTED_PREVIEW,
pageload_metrics.previews_type());
EXPECT_EQ(PageloadMetrics_PreviewsOptOut_UNKNOWN,
pageload_metrics.previews_opt_out());
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyLitePageContent) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
base::Time current_time = base::Time::UnixEpoch();
pingback_client()->set_current_time(current_time);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
true /* lite_page_received */, false /* app_background_occurred */,
true /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
EXPECT_EQ(num_network_requests(), 1);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 1);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(PageloadMetrics_PreviewsType_LITE_PAGE,
pageload_metrics.previews_type());
EXPECT_EQ(PageloadMetrics_PreviewsOptOut_OPT_OUT,
pageload_metrics.previews_opt_out());
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyTwoLitePagePingbacks) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
base::Time current_time = base::Time::UnixEpoch();
pingback_client()->set_current_time(current_time);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
true /* lite_page_received */, false /* app_background_occurred */,
true /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
EXPECT_EQ(num_network_requests(), 1);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(PageloadMetrics_PreviewsType_LITE_PAGE,
pageload_metrics.previews_type());
EXPECT_EQ(PageloadMetrics_PreviewsOptOut_OPT_OUT,
pageload_metrics.previews_opt_out());
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
true /* lite_page_received */, false /* app_background_occurred */,
true /* opt_out_occurred */, false /* renderer_crash */,
false /* black_listed */);
histogram_tester().ExpectUniqueSample(kHistogramAttempted, true, 2);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(PageloadMetrics_PreviewsType_LITE_PAGE,
pageload_metrics.previews_type());
EXPECT_EQ(PageloadMetrics_PreviewsOptOut_OPT_OUT,
pageload_metrics.previews_opt_out());
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyCrashOomBehavior) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, true /* renderer_crash */,
false /* black_listed */);
ReportCrash(true /* oom */);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
#if defined(OS_ANDROID)
EXPECT_EQ(PageloadMetrics_RendererCrashType_ANDROID_FOREGROUND_OOM,
pageload_metrics.renderer_crash_type());
#else
EXPECT_EQ(PageloadMetrics_RendererCrashType_NOT_ANALYZED,
pageload_metrics.renderer_crash_type());
#endif
WaitForPingbackResponse();
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, true, 1);
}
TEST_F(DataReductionProxyPingbackClientImplTest, VerifyCrashNotOomBehavior) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, true /* renderer_crash */,
false /* black_listed */);
ReportCrash(false /* oom */);
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
#if defined(OS_ANDROID)
EXPECT_EQ(PageloadMetrics_RendererCrashType_OTHER_CRASH,
pageload_metrics.renderer_crash_type());
#else
EXPECT_EQ(PageloadMetrics_RendererCrashType_NOT_ANALYZED,
pageload_metrics.renderer_crash_type());
#endif
WaitForPingbackResponse();
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, true, 1);
}
TEST_F(DataReductionProxyPingbackClientImplTest,
VerifyCrashNotAnalyzedBehavior) {
Init();
EXPECT_EQ(num_network_requests(), 0);
pingback_client()->OverrideRandom(true, 0.5f);
static_cast<DataReductionProxyPingbackClient*>(pingback_client())
->SetPingbackReportingFraction(1.0f);
CreateAndSendPingback(
false /* lofi_received */, false /* client_lofi_requested */,
false /* lite_page_received */, false /* app_background_occurred */,
false /* opt_out_occurred */, true /* renderer_crash */,
false /* black_listed */);
// Don't report the crash dump details.
scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
EXPECT_EQ(upload_content_type(), "application/x-protobuf");
RecordPageloadMetricsRequest batched_request;
batched_request.ParseFromString(upload_data());
EXPECT_EQ(batched_request.pageloads_size(), 1);
PageloadMetrics pageload_metrics = batched_request.pageloads(0);
EXPECT_EQ(PageloadMetrics_RendererCrashType_NOT_ANALYZED,
pageload_metrics.renderer_crash_type());
WaitForPingbackResponse();
histogram_tester().ExpectUniqueSample(kHistogramSucceeded, true, 1);
}
} // namespace data_reduction_proxy