blob: 60d27b4b6fd1e62fcee96fce43424e0f5d838609 [file] [log] [blame]
// Copyright 2015 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 "cc/scheduler/compositor_frame_reporting_controller.h"
#include "base/macros.h"
#include "base/test/metrics/histogram_tester.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
namespace {
class CompositorFrameReportingControllerTest;
class TestCompositorFrameReportingController
: public CompositorFrameReportingController {
public:
TestCompositorFrameReportingController(
CompositorFrameReportingControllerTest* test)
: CompositorFrameReportingController(), test_(test) {}
TestCompositorFrameReportingController(
const TestCompositorFrameReportingController& controller) = delete;
TestCompositorFrameReportingController& operator=(
const TestCompositorFrameReportingController& controller) = delete;
std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; }
int ActiveReporters() {
int count = 0;
for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) {
if (reporters_[i])
++count;
}
return count;
}
protected:
CompositorFrameReportingControllerTest* test_;
};
class CompositorFrameReportingControllerTest : public testing::Test {
public:
CompositorFrameReportingControllerTest() : reporting_controller_(this) {}
// The following functions simulate the actions that would
// occur for each phase of the reporting controller.
void SimulateBeginImplFrame() { reporting_controller_.WillBeginImplFrame(); }
void SimulateBeginMainFrame() {
if (!reporting_controller_.reporters()[CompositorFrameReportingController::
PipelineStage::kBeginImplFrame])
SimulateBeginImplFrame();
CHECK(
reporting_controller_.reporters()[CompositorFrameReportingController::
PipelineStage::kBeginImplFrame]);
reporting_controller_.WillBeginMainFrame();
}
void SimulateCommit() {
if (!reporting_controller_.reporters()[CompositorFrameReportingController::
PipelineStage::kBeginMainFrame])
SimulateBeginMainFrame();
CHECK(
reporting_controller_.reporters()[CompositorFrameReportingController::
PipelineStage::kBeginMainFrame]);
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
}
void SimulateActivate() {
if (!reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kCommit])
SimulateCommit();
CHECK(reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kCommit]);
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
}
void SimulateSubmitCompositorFrame() {
if (!reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kActivate])
SimulateActivate();
CHECK(reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kActivate]);
reporting_controller_.DidSubmitCompositorFrame();
}
protected:
TestCompositorFrameReportingController reporting_controller_;
};
TEST_F(CompositorFrameReportingControllerTest, ActiveReporterCounts) {
// Check that there are no leaks with the CompositorFrameReporter
// objects no matter what the sequence of scheduled actions is
// Note that due to DCHECKs in WillCommit(), WillActivate(), etc., it
// is impossible to have 2 reporters both in BMF or Commit
// Tests Cases:
// - 2 Reporters at Activate phase
// - 2 back-to-back BeginImplFrames
// - 4 Simultaneous Reporters
// BF
reporting_controller_.WillBeginImplFrame();
EXPECT_EQ(1, reporting_controller_.ActiveReporters());
// BF -> BF
// Should replace previous reporter.
reporting_controller_.WillBeginImplFrame();
EXPECT_EQ(1, reporting_controller_.ActiveReporters());
// BF -> BMF -> BF
// Should add new reporter.
reporting_controller_.WillBeginMainFrame();
reporting_controller_.WillBeginImplFrame();
EXPECT_EQ(2, reporting_controller_.ActiveReporters());
// BF -> BMF -> BF -> Commit
// Should stay same.
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
EXPECT_EQ(2, reporting_controller_.ActiveReporters());
// BF -> BMF -> BF -> Commit -> BMF -> Activate -> Commit -> Activation
// Having two reporters at Activate phase should delete the older one.
reporting_controller_.WillBeginMainFrame();
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
EXPECT_EQ(1, reporting_controller_.ActiveReporters());
reporting_controller_.DidSubmitCompositorFrame();
EXPECT_EQ(0, reporting_controller_.ActiveReporters());
// 4 simultaneous reporters active.
SimulateActivate();
SimulateCommit();
SimulateBeginMainFrame();
SimulateBeginImplFrame();
EXPECT_EQ(4, reporting_controller_.ActiveReporters());
// Any additional BeginImplFrame's would be ignored.
SimulateBeginImplFrame();
EXPECT_EQ(4, reporting_controller_.ActiveReporters());
}
TEST_F(CompositorFrameReportingControllerTest,
SubmittedFrameHistogramReporting) {
base::HistogramTester histogram_tester;
// 2 reporters active.
SimulateActivate();
SimulateBeginImplFrame();
// Submitting the next reporter should be missed.
SimulateSubmitCompositorFrame();
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedFrame.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedFrame.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Commit", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedFrame.EndCommitToActivation", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Activation",
1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedFrame.EndActivateToSubmitCompositorFrame", 1);
// Other histograms should not be reported.
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
0);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 0);
// Submitting the next reporter will not be counted as missed.
// In practice this submitted frame should be considered as missed because a
// new BeginFrame would have been issued, which is the cause for this frame
// submission.
SimulateSubmitCompositorFrame();
// Other histograms should not be reported.
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
// Missed frame histogram counts should not change.
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedFrame.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedFrame.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Commit", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedFrame.EndCommitToActivation", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.MissedFrame.Activation",
1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedFrame.EndActivateToSubmitCompositorFrame", 1);
}
} // namespace
} // namespace cc