Commit 3697464e authored by Steve Kobes's avatar Steve Kobes Committed by Commit Bot

Refactor MetricIntegrationTest.

Move the LayoutInstability test case and CLS-specific stuff into a
separate file, add comments to document MetricIntegrationTest APIs,
and create UKM/UMA tester objects automatically.

Bug: 1045064
Change-Id: I905975afc97fa7ebd3b3d5382b7c77429628c07a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2064780Reviewed-by: default avatarAnnie Sullivan <sullivan@chromium.org>
Commit-Queue: Steve Kobes <skobes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#743099}
parent 4f41b4c7
// Copyright 2019 The Chromium Authors. All rights reserved.
// Copyright 2020 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 "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/page_load_metrics/integration_tests/metric_integration_test.h"
#include "base/test/trace_event_analyzer.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/tracing_controller.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "services/metrics/public/cpp/ukm_builders.h"
using base::Bucket;
using base::CommandLine;
using base::HistogramTester;
using base::JSONReader;
using base::JSONWriter;
using base::OnceClosure;
using base::RunLoop;
using base::StringPiece;
using base::Value;
using base::trace_event::TraceConfig;
using content::TracingController;
using content::WebContents;
using net::test_server::BasicHttpResponse;
using net::test_server::HttpRequest;
using net::test_server::HttpResponse;
using trace_analyzer::Query;
using trace_analyzer::TraceAnalyzer;
using trace_analyzer::TraceEventVector;
using ukm::TestAutoSetUkmRecorder;
using ukm::TestUkmRecorder;
using ukm::builders::PageLoad;
using ukm::mojom::UkmEntry;
namespace {
......@@ -65,103 +39,8 @@ std::vector<double> LayoutShiftScores(TraceAnalyzer& analyzer) {
return scores;
}
void ExpectPageLoadMetric(const TestUkmRecorder& ukm_recorder,
StringPiece metric_name,
int64_t expected_value) {
std::vector<const UkmEntry*> entries =
ukm_recorder.GetEntriesByName(PageLoad::kEntryName);
auto name_filter = [&metric_name](const UkmEntry* entry) {
return !TestUkmRecorder::EntryHasMetric(entry, metric_name);
};
entries.erase(std::remove_if(entries.begin(), entries.end(), name_filter),
entries.end());
EXPECT_EQ(1ul, entries.size());
TestUkmRecorder::ExpectEntryMetric(entries[0], metric_name, expected_value);
}
} // namespace
class MetricIntegrationTest : public InProcessBrowserTest {
public:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
embedded_test_server()->ServeFilesFromSourceDirectory(
"third_party/blink/web_tests/external/wpt");
content::SetupCrossSiteRedirector(embedded_test_server());
}
protected:
void Serve(const std::string& url, const std::string& content) {
embedded_test_server()->RegisterRequestHandler(
base::BindRepeating(&HandleRequest, url, content));
}
void Start() { ASSERT_TRUE(embedded_test_server()->Start()); }
void Load(const std::string& relative_url) {
GURL url = embedded_test_server()->GetURL("example.com", relative_url);
ui_test_utils::NavigateToURL(browser(), url);
}
void LoadHTML(const std::string& content) {
Serve("/test.html", content);
Start();
Load("/test.html");
}
void StartTracing(const std::vector<std::string>& categories) {
RunLoop wait_for_tracing;
TracingController::GetInstance()->StartTracing(
TraceConfig(
base::StringPrintf("{\"included_categories\": [\"%s\"]}",
base::JoinString(categories, "\", \"").c_str())),
wait_for_tracing.QuitClosure());
wait_for_tracing.Run();
}
void StopTracing(std::string& trace_output) {
RunLoop wait_for_tracing;
TracingController::GetInstance()->StopTracing(
TracingController::CreateStringEndpoint(base::BindOnce(
[](OnceClosure quit_closure, std::string* output,
std::unique_ptr<std::string> trace_str) {
*output = *trace_str;
std::move(quit_closure).Run();
},
wait_for_tracing.QuitClosure(), &trace_output)));
wait_for_tracing.Run();
}
std::unique_ptr<TraceAnalyzer> StopTracingAndAnalyze() {
std::string trace_str;
StopTracing(trace_str);
return std::unique_ptr<TraceAnalyzer>(TraceAnalyzer::Create(trace_str));
}
WebContents* web_contents() const {
return browser()->tab_strip_model()->GetActiveWebContents();
}
void SetUpCommandLine(CommandLine* command_line) override {
// Set a default window size for consistency.
command_line->AppendSwitchASCII(switches::kWindowSize, "800,600");
}
private:
static std::unique_ptr<HttpResponse> HandleRequest(
const std::string& relative_url,
const std::string& content,
const HttpRequest& request) {
if (request.relative_url != relative_url)
return nullptr;
auto response = std::make_unique<BasicHttpResponse>();
response->set_code(net::HTTP_OK);
response->set_content(content);
response->set_content_type("text/html; charset=utf-8");
return std::move(response);
}
};
IN_PROC_BROWSER_TEST_F(MetricIntegrationTest, LayoutInstability) {
LoadHTML(R"HTML(
<script src="/layout-instability/resources/util.js"></script>
......@@ -202,8 +81,6 @@ IN_PROC_BROWSER_TEST_F(MetricIntegrationTest, LayoutInstability) {
)HTML");
StartTracing({"loading"});
TestAutoSetUkmRecorder ukm_recorder;
HistogramTester histogram_tester;
// Check web perf API.
double expected_score = EvalJs(web_contents(), "runtest()").ExtractDouble();
......@@ -216,12 +93,11 @@ IN_PROC_BROWSER_TEST_F(MetricIntegrationTest, LayoutInstability) {
ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
// Check UKM.
ExpectPageLoadMetric(ukm_recorder,
PageLoad::kLayoutInstability_CumulativeShiftScoreName,
LayoutShiftUkmValue(expected_score));
ExpectUKMPageLoadMetric(PageLoad::kLayoutInstability_CumulativeShiftScoreName,
LayoutShiftUkmValue(expected_score));
// Check UMA.
auto samples = histogram_tester.GetAllSamples(
auto samples = histogram_tester().GetAllSamples(
"PageLoad.LayoutInstability.CumulativeShiftScore");
EXPECT_EQ(1ul, samples.size());
EXPECT_EQ(samples[0], Bucket(LayoutShiftUmaValue(expected_score), 1));
......
// 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 "chrome/browser/page_load_metrics/integration_tests/metric_integration_test.h"
#include "base/strings/stringprintf.h"
#include "base/test/trace_event_analyzer.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/tracing_controller.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "services/metrics/public/cpp/ukm_builders.h"
using base::CommandLine;
using base::OnceClosure;
using base::RunLoop;
using base::StringPiece;
using base::trace_event::TraceConfig;
using content::TracingController;
using content::WebContents;
using net::test_server::BasicHttpResponse;
using net::test_server::HttpRequest;
using net::test_server::HttpResponse;
using trace_analyzer::TraceAnalyzer;
using ukm::TestUkmRecorder;
using ukm::builders::PageLoad;
using ukm::mojom::UkmEntry;
MetricIntegrationTest::MetricIntegrationTest() = default;
MetricIntegrationTest::~MetricIntegrationTest() = default;
void MetricIntegrationTest::SetUpOnMainThread() {
host_resolver()->AddRule("*", "127.0.0.1");
embedded_test_server()->ServeFilesFromSourceDirectory(
"third_party/blink/web_tests/external/wpt");
content::SetupCrossSiteRedirector(embedded_test_server());
ukm_recorder_.emplace();
histogram_tester_.emplace();
}
void MetricIntegrationTest::Serve(const std::string& url,
const std::string& content) {
embedded_test_server()->RegisterRequestHandler(
base::BindRepeating(&HandleRequest, url, content));
}
void MetricIntegrationTest::Start() {
ASSERT_TRUE(embedded_test_server()->Start());
}
void MetricIntegrationTest::Load(const std::string& relative_url) {
GURL url = embedded_test_server()->GetURL("example.com", relative_url);
ui_test_utils::NavigateToURL(browser(), url);
}
void MetricIntegrationTest::LoadHTML(const std::string& content) {
Serve("/test.html", content);
Start();
Load("/test.html");
}
void MetricIntegrationTest::StartTracing(
const std::vector<std::string>& categories) {
RunLoop wait_for_tracing;
TracingController::GetInstance()->StartTracing(
TraceConfig(
base::StringPrintf("{\"included_categories\": [\"%s\"]}",
base::JoinString(categories, "\", \"").c_str())),
wait_for_tracing.QuitClosure());
wait_for_tracing.Run();
}
void MetricIntegrationTest::StopTracing(std::string& trace_output) {
RunLoop wait_for_tracing;
TracingController::GetInstance()->StopTracing(
TracingController::CreateStringEndpoint(base::BindOnce(
[](OnceClosure quit_closure, std::string* output,
std::unique_ptr<std::string> trace_str) {
*output = *trace_str;
std::move(quit_closure).Run();
},
wait_for_tracing.QuitClosure(), &trace_output)));
wait_for_tracing.Run();
}
std::unique_ptr<TraceAnalyzer> MetricIntegrationTest::StopTracingAndAnalyze() {
std::string trace_str;
StopTracing(trace_str);
return std::unique_ptr<TraceAnalyzer>(TraceAnalyzer::Create(trace_str));
}
WebContents* MetricIntegrationTest::web_contents() const {
return browser()->tab_strip_model()->GetActiveWebContents();
}
void MetricIntegrationTest::SetUpCommandLine(CommandLine* command_line) {
// Set a default window size for consistency.
command_line->AppendSwitchASCII(switches::kWindowSize, "800,600");
}
std::unique_ptr<HttpResponse> MetricIntegrationTest::HandleRequest(
const std::string& relative_url,
const std::string& content,
const HttpRequest& request) {
if (request.relative_url != relative_url)
return nullptr;
auto response = std::make_unique<BasicHttpResponse>();
response->set_code(net::HTTP_OK);
response->set_content(content);
response->set_content_type("text/html; charset=utf-8");
return std::move(response);
}
void MetricIntegrationTest::ExpectUKMPageLoadMetric(StringPiece metric_name,
int64_t expected_value) {
std::vector<const UkmEntry*> entries =
ukm_recorder().GetEntriesByName(PageLoad::kEntryName);
auto name_filter = [&metric_name](const UkmEntry* entry) {
return !TestUkmRecorder::EntryHasMetric(entry, metric_name);
};
entries.erase(std::remove_if(entries.begin(), entries.end(), name_filter),
entries.end());
EXPECT_EQ(1ul, entries.size());
TestUkmRecorder::ExpectEntryMetric(entries[0], metric_name, expected_value);
}
// Copyright 2020 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 CHROME_BROWSER_PAGE_LOAD_METRICS_INTEGRATION_TESTS_METRIC_INTEGRATION_TEST_H_
#define CHROME_BROWSER_PAGE_LOAD_METRICS_INTEGRATION_TESTS_METRIC_INTEGRATION_TEST_H_
#include "chrome/test/base/in_process_browser_test.h"
#include "base/test/metrics/histogram_tester.h"
#include "components/ukm/test_ukm_recorder.h"
namespace base {
class CommandLine;
}
namespace content {
class WebContents;
}
namespace net {
namespace test_server {
struct HttpRequest;
class HttpResponse;
} // namespace test_server
} // namespace net
namespace trace_analyzer {
class TraceAnalyzer;
}
// Base class for end to end integration tests of speed metrics.
// See README.md for more information.
class MetricIntegrationTest : public InProcessBrowserTest {
public:
MetricIntegrationTest();
~MetricIntegrationTest() override;
// Override of BrowserTestBase::SetUpOnMainThread.
void SetUpOnMainThread() override;
protected:
// Configures a request handler for the specified URL, which supplies
// the specified response content. Example:
//
// Serve("/foo.html", "<html> Hello, World! </html>");
//
// The response is served with an HTTP 200 status code and a content
// type of "text/html; charset=utf-8".
void Serve(const std::string& url, const std::string& content);
// Starts the test server. Call this after configuring request
// handlers, and before loading any pages.
void Start();
// Navigates Chrome to the specified URL in the current tab.
void Load(const std::string& relative_url);
// Convenience helper for Serve + Start + Load of a single HTML
// resource at the URL "/test.html".
void LoadHTML(const std::string& content);
// Begin trace collection for the specified trace categories. The
// trace includes events from all processes (browser and renderer).
void StartTracing(const std::vector<std::string>& categories);
// End trace collection and write trace output as JSON into the
// specified string.
void StopTracing(std::string& trace_output);
// End trace collection and return a TraceAnalyzer which can run
// queries on the trace output.
std::unique_ptr<trace_analyzer::TraceAnalyzer> StopTracingAndAnalyze();
// Returns the WebContents object for the current Chrome tab.
content::WebContents* web_contents() const;
// Override for command-line flags.
void SetUpCommandLine(base::CommandLine* command_line) override;
ukm::TestAutoSetUkmRecorder& ukm_recorder() { return *ukm_recorder_; }
base::HistogramTester& histogram_tester() { return *histogram_tester_; }
// Checks for a single UKM entry under the PageLoad event with the specified
// metric name and value.
void ExpectUKMPageLoadMetric(base::StringPiece metric_name,
int64_t expected_value);
private:
static std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
const std::string& relative_url,
const std::string& content,
const net::test_server::HttpRequest& request);
base::Optional<ukm::TestAutoSetUkmRecorder> ukm_recorder_;
base::Optional<base::HistogramTester> histogram_tester_;
};
#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_INTEGRATION_TESTS_METRIC_INTEGRATION_TEST_H_
# Copyright 2020 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.
metric_integration_sources = [
"//chrome/browser/page_load_metrics/integration_tests/layout_instability_browsertest.cc",
"//chrome/browser/page_load_metrics/integration_tests/metric_integration_test.cc",
"//chrome/browser/page_load_metrics/integration_tests/metric_integration_test.h",
]
......@@ -15,6 +15,7 @@ import("//build/util/version.gni")
import("//chrome/browser/buildflags.gni")
import("//chrome/browser/downgrade/buildflags.gni")
import("//chrome/browser/page_load_metrics/integration_tests/jsdeps.gni")
import("//chrome/browser/page_load_metrics/integration_tests/sources.gni")
import("//chrome/common/features.gni")
import("//chrome/test/base/js2gtest.gni")
import("//chrome/test/include_js_tests.gni")
......@@ -1055,7 +1056,6 @@ if (!is_android) {
"../browser/optimization_guide/hints_fetcher_browsertest.cc",
"../browser/optimization_guide/optimization_guide_keyed_service_browsertest.cc",
"../browser/optimization_guide/prediction/prediction_manager_browsertest.cc",
"../browser/page_load_metrics/integration_tests/metric_browsertest.cc",
"../browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc",
"../browser/page_load_metrics/observers/amp_page_load_metrics_observer_browsertest.cc",
"../browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc",
......@@ -2847,6 +2847,8 @@ if (!is_android) {
sources +=
[ "../browser/site_isolation/spellcheck_per_process_browsertest.cc" ]
}
sources += metric_integration_sources
}
}
......
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