1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/performance_manager/graph/policies/process_priority_policy.h"
#include <memory>
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "components/performance_manager/graph/graph_impl.h"
#include "components/performance_manager/graph/process_node_impl.h"
#include "components/performance_manager/public/features.h"
#include "components/performance_manager/public/performance_manager.h"
#include "components/performance_manager/render_process_user_data.h"
#include "components/performance_manager/test_support/performance_manager_test_harness.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/process_type.h"
#include "content/public/test/navigation_simulator.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace performance_manager {
namespace policies {
namespace {
base::TaskPriority ToTaskPriority(base::Process::Priority priority) {
switch (priority) {
case base::Process::Priority::kBestEffort:
return base::TaskPriority::BEST_EFFORT;
case base::Process::Priority::kUserVisible:
return base::TaskPriority::USER_VISIBLE;
case base::Process::Priority::kUserBlocking:
return base::TaskPriority::USER_BLOCKING;
}
}
void PostProcessNodePriority(content::RenderProcessHost* rph,
base::Process::Priority priority) {
auto* rpud = RenderProcessUserData::GetForRenderProcessHost(rph);
auto* process_node = rpud->process_node();
process_node->set_priority(ToTaskPriority(priority));
}
// Tests ProcessPriorityPolicy in different threading configurations.
class ProcessPriorityPolicyTest : public PerformanceManagerTestHarness,
public testing::WithParamInterface<bool> {
public:
ProcessPriorityPolicyTest() {
base::FieldTrialParams params = {
{features::kNonSpareRendererHighInitialPriority.name,
GetParam() ? "true" : "false"}};
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kPMProcessPriorityPolicy, params);
}
ProcessPriorityPolicyTest(const ProcessPriorityPolicyTest&) = delete;
ProcessPriorityPolicyTest(ProcessPriorityPolicyTest&&) = delete;
ProcessPriorityPolicyTest& operator=(const ProcessPriorityPolicyTest&) =
delete;
ProcessPriorityPolicyTest& operator=(ProcessPriorityPolicyTest&&) = delete;
~ProcessPriorityPolicyTest() override = default;
void SetUp() override {
PerformanceManagerTestHarness::SetUp();
// It's safe to pass unretained as we clear the callback before being
// torn down.
ProcessPriorityPolicy::SetCallbackForTesting(
base::BindRepeating(&ProcessPriorityPolicyTest::OnSetPriorityWrapper,
base::Unretained(this)));
}
void TearDown() override {
ProcessPriorityPolicy::ClearCallbackForTesting();
// Clean up the web contents, which should dispose of the page and frame
// nodes involved.
DeleteContents();
PerformanceManagerTestHarness::TearDown();
}
void OnGraphCreated(GraphImpl* graph) override {
graph->PassToGraph(std::make_unique<ProcessPriorityPolicy>());
}
void RunUntilOnSetPriority() {
task_environment()->RunUntilQuit();
// RunUntilQuit() invalidated the old closure.
quit_closure_ = task_environment()->QuitClosure();
}
// This is eventually invoked by the testing callback when the policy sets a
// process priority.
MOCK_METHOD(void,
OnSetPriority,
(content::RenderProcessHost*, base::Process::Priority));
private:
void OnSetPriorityWrapper(RenderProcessHostProxy rph_proxy,
base::Process::Priority priority) {
OnSetPriority(rph_proxy.Get(), priority);
quit_closure_.Run();
}
base::test::ScopedFeatureList scoped_feature_list_;
base::RepeatingClosure quit_closure_ = task_environment()->QuitClosure();
};
} // namespace
TEST_P(ProcessPriorityPolicyTest, GraphReflectedToRenderProcessHost) {
// Set the active contents in the RenderViewHostTestHarness.
SetContents(CreateTestWebContents());
auto* rvh = web_contents()->GetPrimaryMainFrame()->GetRenderViewHost();
DCHECK(rvh);
auto* rph = rvh->GetProcess();
DCHECK(rph);
const base::Process::Priority kInitialPriority =
features::kNonSpareRendererHighInitialPriority.Get()
? base::Process::Priority::kUserBlocking
: base::Process::Priority::kBestEffort;
const base::Process::Priority kOtherPriority =
features::kNonSpareRendererHighInitialPriority.Get()
? base::Process::Priority::kBestEffort
: base::Process::Priority::kUserBlocking;
// Simulate a navigation so that graph nodes spring into existence.
// Expect a background priority override to be set for process creation.
// NOTE: This is going to change once we have provisional frames and the like,
// and can calculate meaningful process startup priorities.
EXPECT_CALL(*this, OnSetPriority(rph, kInitialPriority));
content::NavigationSimulator::NavigateAndCommitFromBrowser(
web_contents(), GURL("https://www.foo.com/"));
RunUntilOnSetPriority();
// Toggle the priority and expect it to change.
EXPECT_CALL(*this, OnSetPriority(rph, kOtherPriority));
PostProcessNodePriority(rph, kOtherPriority);
RunUntilOnSetPriority();
testing::Mock::VerifyAndClearExpectations(this);
}
INSTANTIATE_TEST_SUITE_P(, ProcessPriorityPolicyTest, testing::Bool());
} // namespace policies
} // namespace performance_manager
|