Commit fd2cb104 authored by Xida Chen's avatar Xida Chen Committed by Commit Bot

[throughput] Track last frame

It could happen that after a BeginImpl(Main)Frame is reported, a tracker
is scheduled to terminate. In this case, any subsequent handling of
that impl(main)-frame will be lost. In other words, we completely lost
track of the last frame.

This CL fixes the impl frame, the fix for main frame comes later because
this CL is already big.

Bug: 1055844
Change-Id: I1cc65e9a5d973ecb67c83105be03f7bc08139dae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2079134
Commit-Queue: Xida Chen <xidachen@chromium.org>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#752529}
parent adfc6824
......@@ -334,6 +334,7 @@ void FrameSequenceTrackerCollection::StopSequence(
frame_trackers_.erase(type);
tracker->ScheduleTerminate();
removal_trackers_.push_back(std::move(tracker));
DestroyTrackers();
}
void FrameSequenceTrackerCollection::ClearAll() {
......@@ -362,16 +363,19 @@ void FrameSequenceTrackerCollection::NotifyMainFrameProcessed(
void FrameSequenceTrackerCollection::NotifyImplFrameCausedNoDamage(
const viz::BeginFrameAck& ack) {
for (auto& tracker : frame_trackers_) {
for (auto& tracker : frame_trackers_)
tracker.second->ReportImplFrameCausedNoDamage(ack);
}
// Removal trackers continue to process any frames which they started
// observing.
for (auto& tracker : removal_trackers_)
tracker->ReportImplFrameCausedNoDamage(ack);
}
void FrameSequenceTrackerCollection::NotifyMainFrameCausedNoDamage(
const viz::BeginFrameArgs& args) {
for (auto& tracker : frame_trackers_) {
for (auto& tracker : frame_trackers_)
tracker.second->ReportMainFrameCausedNoDamage(args);
}
}
void FrameSequenceTrackerCollection::NotifyPauseFrameProduction() {
......@@ -388,14 +392,27 @@ void FrameSequenceTrackerCollection::NotifySubmitFrame(
tracker.second->ReportSubmitFrame(frame_token, has_missing_content, ack,
origin_args);
}
// Removal trackers continue to process any frames which they started
// observing.
for (auto& tracker : removal_trackers_) {
tracker->ReportSubmitFrame(frame_token, has_missing_content, ack,
origin_args);
}
}
void FrameSequenceTrackerCollection::NotifyFrameEnd(
const viz::BeginFrameArgs& args,
const viz::BeginFrameArgs& main_args) {
for (auto& tracker : frame_trackers_) {
for (auto& tracker : frame_trackers_)
tracker.second->ReportFrameEnd(args, main_args);
}
// Removal trackers continue to process any frames which they started
// observing.
for (auto& tracker : removal_trackers_)
tracker->ReportFrameEnd(args, main_args);
DestroyTrackers();
}
void FrameSequenceTrackerCollection::NotifyFramePresented(
......@@ -421,24 +438,6 @@ void FrameSequenceTrackerCollection::NotifyFramePresented(
accumulated_metrics_.erase(tracker->type());
}
#if DCHECK_IS_ON()
// Handling the case like b(100)s(150)e(100)b(200)n(200), and then
// StopSequence() is called which put this tracker in removal_trackers_.
// Then P(150). In this case, frame 200 isn't processed yet, because this
// no damage impl frame is considered 'processed' at e(200).
const bool incomplete_frame_had_no_damage =
!tracker->compositor_frame_submitted_ &&
tracker->frame_had_no_compositor_damage_;
if (tracker->is_inside_frame_ && incomplete_frame_had_no_damage)
--metrics->impl_throughput().frames_received;
if (metrics->impl_throughput().frames_received !=
metrics->impl_throughput().frames_processed) {
std::string output = tracker->frame_sequence_trace_.str().substr(
tracker->ignored_trace_char_count_);
NOTREACHED() << output;
}
#endif
if (metrics->HasEnoughDataForReporting())
metrics->ReportMetrics();
if (metrics->HasDataLeftForReporting())
......@@ -446,7 +445,10 @@ void FrameSequenceTrackerCollection::NotifyFramePresented(
}
}
// Destroy the trackers that are ready to be terminated.
DestroyTrackers();
}
void FrameSequenceTrackerCollection::DestroyTrackers() {
base::EraseIf(
removal_trackers_,
[](const std::unique_ptr<FrameSequenceTracker>& tracker) {
......@@ -490,6 +492,15 @@ FrameSequenceTracker* FrameSequenceTrackerCollection::GetTrackerForTesting(
return frame_trackers_[type].get();
}
FrameSequenceTracker*
FrameSequenceTrackerCollection::GetRemovalTrackerForTesting(
FrameSequenceTrackerType type) {
for (const auto& tracker : removal_trackers_)
if (tracker->type_ == type)
return tracker.get();
return nullptr;
}
void FrameSequenceTrackerCollection::SetUkmManager(UkmManager* manager) {
DCHECK(frame_trackers_.empty());
if (manager)
......@@ -515,19 +526,12 @@ FrameSequenceTracker::~FrameSequenceTracker() {
}
void FrameSequenceTracker::ScheduleTerminate() {
// If the last frame has ended and there is no frame awaiting presentation,
// then it is ready to terminate.
if (!is_inside_frame_ && last_submitted_frame_ == 0)
termination_status_ = TerminationStatus::kReadyForTermination;
else
termination_status_ = TerminationStatus::kScheduledForTermination;
// It could happen that a main/impl frame is generated, but never processed
// (didn't report no damage and didn't submit) when this happens.
if (last_processed_impl_sequence_ < last_started_impl_sequence_) {
DCHECK_GE(impl_throughput().frames_expected,
begin_impl_frame_data_.previous_sequence_delta)
<< TRACKER_DCHECK_MSG;
impl_throughput().frames_expected -=
begin_impl_frame_data_.previous_sequence_delta;
#if DCHECK_IS_ON()
--impl_throughput().frames_received;
#endif
}
}
void FrameSequenceTracker::ReportMetricsForTesting() {
......@@ -544,10 +548,9 @@ void FrameSequenceTracker::ReportBeginImplFrame(
TRACKER_TRACE_STREAM << "b(" << args.frame_id.sequence_number << ")";
#if DCHECK_IS_ON()
DCHECK(!is_inside_frame_) << TRACKER_DCHECK_MSG;
is_inside_frame_ = true;
#if DCHECK_IS_ON()
if (args.type == viz::BeginFrameArgs::NORMAL)
impl_frames_.insert(args.frame_id);
#endif
......@@ -664,8 +667,8 @@ void FrameSequenceTracker::ReportSubmitFrame(
bool has_missing_content,
const viz::BeginFrameAck& ack,
const viz::BeginFrameArgs& origin_args) {
if (termination_status_ != TerminationStatus::kActive ||
ShouldIgnoreBeginFrameSource(ack.frame_id.source_id) ||
DCHECK_NE(termination_status_, TerminationStatus::kReadyForTermination);
if (ShouldIgnoreBeginFrameSource(ack.frame_id.source_id) ||
ShouldIgnoreSequence(ack.frame_id.sequence_number)) {
ignored_frame_tokens_.insert(frame_token);
return;
......@@ -697,10 +700,12 @@ void FrameSequenceTracker::ReportSubmitFrame(
const bool main_change_had_no_damage =
last_no_main_damage_sequence_ != 0 &&
origin_args.frame_id.sequence_number == last_no_main_damage_sequence_;
const bool origin_args_is_valid = origin_args.frame_id.sequence_number <=
begin_main_frame_data_.previous_sequence;
if (!ShouldIgnoreBeginFrameSource(origin_args.frame_id.source_id) &&
main_changes_after_sequence_started && main_changes_include_new_changes &&
!main_change_had_no_damage) {
!main_change_had_no_damage && origin_args_is_valid) {
submitted_frame_had_new_main_content_ = true;
TRACKER_TRACE_STREAM << "S(" << origin_args.frame_id.sequence_number << ")";
......@@ -718,8 +723,7 @@ void FrameSequenceTracker::ReportSubmitFrame(
void FrameSequenceTracker::ReportFrameEnd(
const viz::BeginFrameArgs& args,
const viz::BeginFrameArgs& main_args) {
if (termination_status_ != TerminationStatus::kActive)
return;
DCHECK_NE(termination_status_, TerminationStatus::kReadyForTermination);
if (ShouldIgnoreBeginFrameSource(args.frame_id.source_id))
return;
......@@ -736,9 +740,7 @@ void FrameSequenceTracker::ReportFrameEnd(
}
if (should_ignore_sequence) {
#if DCHECK_IS_ON()
is_inside_frame_ = false;
#endif
return;
}
......@@ -771,16 +773,19 @@ void FrameSequenceTracker::ReportFrameEnd(
NOTREACHED() << TRACKER_DCHECK_MSG;
#endif
begin_impl_frame_data_.previous_sequence = 0;
// last_submitted_frame_ == 0 means the last impl frame has been presented.
if (termination_status_ == TerminationStatus::kScheduledForTermination &&
last_submitted_frame_ == 0)
termination_status_ = TerminationStatus::kReadyForTermination;
}
frame_had_no_compositor_damage_ = false;
compositor_frame_submitted_ = false;
submitted_frame_had_new_main_content_ = false;
last_processed_main_sequence_latency_ = 0;
#if DCHECK_IS_ON()
DCHECK(is_inside_frame_) << TRACKER_DCHECK_MSG;
is_inside_frame_ = false;
#endif
DCHECK_EQ(last_started_impl_sequence_, last_processed_impl_sequence_)
<< TRACKER_DCHECK_MSG;
......@@ -790,15 +795,18 @@ void FrameSequenceTracker::ReportFrameEnd(
void FrameSequenceTracker::ReportFramePresented(
uint32_t frame_token,
const gfx::PresentationFeedback& feedback) {
// !viz::FrameTokenGT(a, b) is equivalent to b >= a.
const bool frame_token_acks_last_frame =
frame_token == last_submitted_frame_ ||
viz::FrameTokenGT(frame_token, last_submitted_frame_);
!viz::FrameTokenGT(last_submitted_frame_, frame_token);
// Update termination status if this is scheduled for termination, and it is
// not waiting for any frames, or it has received the presentation-feedback
// for the latest frame it is tracking.
//
// We should always wait for an impl frame to end, that is, ReportFrameEnd.
if (termination_status_ == TerminationStatus::kScheduledForTermination &&
(last_submitted_frame_ == 0 || frame_token_acks_last_frame)) {
(last_submitted_frame_ == 0 || frame_token_acks_last_frame) &&
!is_inside_frame_) {
termination_status_ = TerminationStatus::kReadyForTermination;
}
......@@ -878,16 +886,15 @@ void FrameSequenceTracker::ReportFramePresented(
void FrameSequenceTracker::ReportImplFrameCausedNoDamage(
const viz::BeginFrameAck& ack) {
if (termination_status_ != TerminationStatus::kActive)
return;
DCHECK_NE(termination_status_, TerminationStatus::kReadyForTermination);
if (ShouldIgnoreBeginFrameSource(ack.frame_id.source_id))
return;
TRACKER_TRACE_STREAM << "n(" << ack.frame_id.sequence_number << ")";
// It is possible that this is called before a begin-impl-frame has been
// dispatched for this frame-sequence. In such cases, ignore this call.
// This tracker would be scheduled to terminate, and this frame doesn't belong
// to that tracker.
if (ShouldIgnoreSequence(ack.frame_id.sequence_number))
return;
......@@ -981,13 +988,18 @@ bool FrameSequenceTracker::ShouldIgnoreBeginFrameSource(
return source_id != begin_impl_frame_data_.previous_source;
}
// This check ensures that when ReportBeginMainFrame, or ReportSubmitFrame, or
// ReportFramePresented is called for a particular arg, the ReportBeginImplFrame
// is been called already.
// This check handles two cases:
// 1. When there is a call to ReportBeginMainFrame, or ReportSubmitFrame, or
// ReportFramePresented, there must be a ReportBeginImplFrame for that sequence.
// Otherwise, the begin_impl_frame_data_.previous_sequence would be 0.
// 2. A tracker is scheduled to terminate, then any new request to handle a new
// impl frame whose sequence_number > begin_impl_frame_data_.previous_sequence
// should be ignored.
// Note that sequence_number < begin_impl_frame_data_.previous_sequence cannot
// happen.
bool FrameSequenceTracker::ShouldIgnoreSequence(
uint64_t sequence_number) const {
return begin_impl_frame_data_.previous_sequence == 0 ||
sequence_number < begin_impl_frame_data_.previous_sequence;
return sequence_number != begin_impl_frame_data_.previous_sequence;
}
std::unique_ptr<base::trace_event::TracedValue>
......@@ -1010,6 +1022,11 @@ bool FrameSequenceTracker::ShouldReportMetricsNow(
}
std::unique_ptr<FrameSequenceMetrics> FrameSequenceTracker::TakeMetrics() {
#if DCHECK_IS_ON()
DCHECK_EQ(impl_throughput().frames_received,
impl_throughput().frames_processed)
<< frame_sequence_trace_.str().substr(ignored_trace_char_count_);
#endif
return std::move(metrics_);
}
......
......@@ -192,6 +192,8 @@ class CC_EXPORT FrameSequenceTrackerCollection {
ActiveFrameSequenceTrackers FrameSequenceTrackerActiveTypes();
FrameSequenceTracker* GetTrackerForTesting(FrameSequenceTrackerType type);
FrameSequenceTracker* GetRemovalTrackerForTesting(
FrameSequenceTrackerType type);
void SetUkmManager(UkmManager* manager);
......@@ -199,6 +201,8 @@ class CC_EXPORT FrameSequenceTrackerCollection {
friend class FrameSequenceTrackerTest;
void RecreateTrackers(const viz::BeginFrameArgs& args);
// Destroy the trackers that are ready to be terminated.
void DestroyTrackers();
const bool is_single_threaded_;
// The callsite can use the type to manipulate the tracker.
......@@ -227,9 +231,9 @@ class CC_EXPORT FrameSequenceTrackerCollection {
class CC_EXPORT FrameSequenceTracker {
public:
enum class TerminationStatus {
kActive,
kScheduledForTermination,
kReadyForTermination,
kActive = 0,
kScheduledForTermination = 1,
kReadyForTermination = 2,
};
static const char* GetFrameSequenceTrackerTypeName(
......@@ -435,9 +439,11 @@ class CC_EXPORT FrameSequenceTracker {
void Advance(base::TimeTicks new_timestamp);
} trace_data_;
#if DCHECK_IS_ON()
// True when an impl-impl is not ended. A tracker is ready for termination
// only when the last impl-frame is ended (ReportFrameEnd).
bool is_inside_frame_ = false;
#if DCHECK_IS_ON()
// This stringstream represents a sequence of frame reporting activities on
// the current tracker. Each letter can be one of the following:
// {'B', 'N', 'b', 'n', 'S', 'P'}, where
......
......@@ -119,17 +119,9 @@ class FrameSequenceTrackerTest : public testing::Test {
FrameSequenceTrackerType::kMainThreadAnimation));
EXPECT_TRUE(collection_.frame_trackers_.contains(
FrameSequenceTrackerType::kTouchScroll));
ASSERT_EQ(collection_.removal_trackers_.size(), 1u);
EXPECT_EQ(collection_.removal_trackers_[0]->type_,
FrameSequenceTrackerType::kCompositorAnimation);
gfx::PresentationFeedback feedback;
collection_.NotifyFramePresented(1u, feedback);
// NotifyFramePresented should call ReportFramePresented on all the
// |removal_trackers_|, which changes their termination_status_ to
// kReadyForTermination. So at this point, the |removal_trackers_| should be
// empty.
EXPECT_TRUE(collection_.removal_trackers_.empty());
// StopSequence should have destroyed all trackers because there is no frame
// awaiting presentation.
ASSERT_EQ(collection_.removal_trackers_.size(), 0u);
}
void ReportMetricsTest() {
......@@ -263,6 +255,8 @@ class FrameSequenceTrackerTest : public testing::Test {
case 's': {
auto frame_token = sequence;
if (current_frame == 0)
current_frame = 1;
auto args = CreateBeginFrameArgs(source_id, current_frame);
auto main_args = args;
if (*str == 'S') {
......@@ -344,6 +338,15 @@ class FrameSequenceTrackerTest : public testing::Test {
tracker_->termination_status_ = status;
}
FrameSequenceTracker::TerminationStatus GetTerminationStatus() {
return tracker_->termination_status_;
}
FrameSequenceTracker::TerminationStatus GetTerminationStatusForTracker(
FrameSequenceTracker* tracker) {
return tracker->termination_status_;
}
protected:
uint32_t number_of_frames_checkerboarded() const {
return tracker_->metrics_->frames_checkerboarded();
......@@ -536,7 +539,8 @@ TEST_F(FrameSequenceTrackerTest, ReportMetricsAtFixedInterval) {
collection_.NotifyImplFrameCausedNoDamage(viz::BeginFrameAck(args, false));
collection_.NotifyFrameEnd(args, args);
EXPECT_EQ(NumberOfTrackers(), 1u);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
// At NotifyFrameEnd, the tracker is removed from removal_tracker_ list.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
}
TEST_F(FrameSequenceTrackerTest, ReportWithoutBeginImplFrame) {
......@@ -775,16 +779,6 @@ TEST_F(FrameSequenceTrackerTest, SequenceStateResetsDuringFrame) {
EXPECT_EQ(MainThroughput().frames_produced, 0u);
}
TEST_F(FrameSequenceTrackerTest, BeginImplFrameBeforeTerminate) {
const char sequence[] = "b(1)s(1)e(1,0)b(4)P(1)";
GenerateSequence(sequence);
EXPECT_EQ(ImplThroughput().frames_expected, 4u);
EXPECT_EQ(ImplThroughput().frames_produced, 1u);
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(ImplThroughput().frames_expected, 1u);
EXPECT_EQ(ImplThroughput().frames_produced, 1u);
}
// b(2417)B(0,2417)E(2417)n(2417)N(2417,2417)
TEST_F(FrameSequenceTrackerTest, SequenceNumberReset) {
const char sequence[] =
......@@ -803,28 +797,589 @@ TEST_F(FrameSequenceTrackerTest, MainThroughputWithHighLatency) {
EXPECT_EQ(MainThroughput().frames_produced, 1u);
}
#if DCHECK_IS_ON()
// These two tests ensures that when present a frame, the frames_received is
// the same as frames_processed. As long as there is no crash, the condition is
// true.
TEST_F(FrameSequenceTrackerTest, FramesProcessedMatch1) {
const char sequence[] = "b(1)n(1)e(1,0)b(2)s(2)e(2,0)b(3)n(3)";
GenerateSequence(sequence);
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch1) {
GenerateSequence("b(1)s(1)e(1,0)b(4)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
SetTerminationStatus(
FrameSequenceTracker::TerminationStatus::kReadyForTermination);
GenerateSequence("P(2)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
// There is still one impl-frame not processed not, so the tracker is not yet
// ready for termination.
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
TEST_F(FrameSequenceTrackerTest, FramesProcessedMatch2) {
const char sequence[] = "b(1)n(1)e(1,0)b(2)s(2)e(2,0)b(3)s(3)";
GenerateSequence(sequence);
// Following 3 cases are for: b(1)s(1)e(1,0)P(1), and StopSequence can happen
// anywhere after b and before P.
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch2) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("s(1)e(1,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch3) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(1,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch4) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)e(1,0)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
// Following 2 cases are for: b(1)s(1)P(1), and StopSequence can happen
// anywhere after b and before P. Because there is no e when P happens, the
// tracker is not ready for termination.
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch5) {
GenerateSequence("b(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("s(1)P(1)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch6) {
GenerateSequence("b(1)s(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
SetTerminationStatus(
FrameSequenceTracker::TerminationStatus::kReadyForTermination);
GenerateSequence("P(2)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
// All the following cases are for one complete impl + one incomplete:
// b(1)s(1)e(1,0)xxxxxxxxP(1)
// The 'xxxxx' is an incomplete impl frame that has no damage, it could be
// 1. b(2)n(2)e(2,0)P(1), and StopSequence can happen anywhere after b and
// before P.
// 2. b(2)n(2)P(1), and StopSequence can happen anywhere after b and before P.
// In this case, the tracker is not ready for termination yet because e never
// happens.
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch7) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)e(1,0)b(2)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("n(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch8) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)e(1,0)b(2)n(2)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch9) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)e(1,0)b(2)n(2)e(2,0)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch10) {
GenerateSequence("b(1)s(1)e(1,0)b(2)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("n(2)P(1)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch11) {
GenerateSequence("b(1)s(1)e(1,0)b(2)n(2)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("P(1)");
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
}
// Following tests are for the case where the last impl-frame has no damage.
// Basically b(1)s(1)e(1)P(1)b(2)n(2)e(2). And StopSequence can happen any time
// after b(2).
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch12) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)e(1,0)P(1)b(2)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("n(2)e(2,0)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch13) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)e(1,0)P(1)b(2)n(2)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(2,0)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch14) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)e(1,0)P(1)b(2)n(2)e(2,0)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
// The tracker should have been removed from the removal_tracker_ list.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
// Following tests are for the case where the presentation of the first impl
// frame arrives late, and a second impl frame has started, and the tracker is
// scheduled to terminate before the second impl frame starts. Basically:
// 1. b(1)s(1)e(1,0)b(2)s(2)e(2,0)P(1), and StopSequence happens anywhere after
// b(1) and before b(2)
// 2. b(1)s(1)e(1,0)b(2)n(2)e(2,0)P(1), and StopSequence happens anywhere after
// b(1) and before b(2)
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch15) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("s(1)e(1,0)b(2)s(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch16) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(1,0)b(2)s(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch17) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)e(1,0)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("b(2)s(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
// The second impl-frame has no damage.
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch18) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("s(1)e(1,0)b(2)n(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch19) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(1,0)b(2)n(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch20) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)s(1)e(1,0)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("b(2)n(2)e(2,0)P(1)");
// Now the |removal_tracker| should have been destroyed.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
// Both impl and slower threads reports 101 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
// The main thread reports 0 frames expected.
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
// Following cases test that no frame needs to be presented, basically:
// b(1)n(1)e(1,0), and StopSequence can happen anytime after b(1).
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch21) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("n(1)e(1,0)");
// Ensure that this tracker is actually removed from the |removal_trackers_|
// before the test terminates.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
// If the tracker is terminated successfully, we should see this UMA.
std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch22) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)n(1)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
FrameSequenceTracker* removal_tracker =
collection_.GetRemovalTrackerForTesting(
FrameSequenceTrackerType::kTouchScroll);
EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
GenerateSequence("e(1,0)");
// Ensure that this tracker is actually removed from the |removal_trackers_|
// before the test terminates.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
// If the tracker is terminated successfully, we should see this UMA.
std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
TEST_F(FrameSequenceTrackerTest, ImplFramesProcessedMatch23) {
base::HistogramTester histogram_tester;
// Ensure we have enough data to report.
ImplThroughput().frames_expected = 100u;
ImplThroughput().frames_produced = 100u;
GenerateSequence("b(1)n(1)e(1,0)");
collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
// Ensure that this tracker is actually removed from the |removal_trackers_|
// before the test terminates.
EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
// If the tracker is terminated successfully, we should see this UMA.
std::string metric =
"Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
}
#endif
TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage1) {
const char sequence[] =
......@@ -858,8 +1413,7 @@ TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage3) {
TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage4) {
const char sequence[] =
"b(9)B(0,9)n(9)Re(9,0)E(9)b(11)B(0,11)n(11)e(11,9)b(12)E(11)B(11,12)s(1)"
"S(11)"
"e(12,11)b(13)E(12)s(2)S(12)";
"S(11)e(12,11)b(13)E(12)s(2)S(12)";
GenerateSequence(sequence);
EXPECT_EQ(ImplThroughput().frames_expected, 2u);
EXPECT_EQ(MainThroughput().frames_expected, 2u);
......
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