1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/metrics/frame_sequence_tracker.h"
6
7 #include <vector>
8
9 #include "base/macros.h"
10 #include "base/test/metrics/histogram_tester.h"
11 #include "cc/metrics/compositor_frame_reporting_controller.h"
12 #include "components/viz/common/frame_sinks/begin_frame_args.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/gfx/presentation_feedback.h"
16
17 namespace cc {
18
19 namespace {
20
ParseNumber(const char * str,uint64_t * retvalue)21 const char* ParseNumber(const char* str, uint64_t* retvalue) {
22 uint64_t number = 0;
23 for (; *str >= '0' && *str <= '9'; ++str) {
24 number *= 10;
25 number += *str - '0';
26 }
27 *retvalue = number;
28 return str;
29 }
30
31 } // namespace
32
33 class FrameSequenceTrackerTest : public testing::Test {
34 public:
35 const uint32_t kImplDamage = 0x1;
36 const uint32_t kMainDamage = 0x2;
37
FrameSequenceTrackerTest()38 FrameSequenceTrackerTest()
39 : compositor_frame_reporting_controller_(
40 std::make_unique<CompositorFrameReportingController>(
41 /*should_report_metrics=*/true)),
42 collection_(/*is_single_threaded=*/false,
43 compositor_frame_reporting_controller_.get()) {
44 collection_.StartSequence(FrameSequenceTrackerType::kTouchScroll);
45 tracker_ = collection_.GetTrackerForTesting(
46 FrameSequenceTrackerType::kTouchScroll);
47 }
48 ~FrameSequenceTrackerTest() override = default;
49
CreateNewTracker()50 void CreateNewTracker() {
51 collection_.StartSequence(FrameSequenceTrackerType::kTouchScroll);
52 tracker_ = collection_.GetTrackerForTesting(
53 FrameSequenceTrackerType::kTouchScroll);
54 }
55
CreateBeginFrameArgs(uint64_t source_id,uint64_t sequence_number,base::TimeTicks now=base::TimeTicks::Now ())56 viz::BeginFrameArgs CreateBeginFrameArgs(
57 uint64_t source_id,
58 uint64_t sequence_number,
59 base::TimeTicks now = base::TimeTicks::Now()) {
60 auto interval = base::TimeDelta::FromMilliseconds(16);
61 auto deadline = now + interval;
62 return viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, source_id,
63 sequence_number, now, deadline, interval,
64 viz::BeginFrameArgs::NORMAL);
65 }
66
StartImplAndMainFrames(const viz::BeginFrameArgs & args)67 void StartImplAndMainFrames(const viz::BeginFrameArgs& args) {
68 collection_.NotifyBeginImplFrame(args);
69 collection_.NotifyBeginMainFrame(args);
70 }
71
DispatchCompleteFrame(const viz::BeginFrameArgs & args,uint32_t damage_type,bool has_missing_content=false)72 uint32_t DispatchCompleteFrame(const viz::BeginFrameArgs& args,
73 uint32_t damage_type,
74 bool has_missing_content = false) {
75 StartImplAndMainFrames(args);
76
77 if (damage_type & kImplDamage) {
78 if (!(damage_type & kMainDamage)) {
79 collection_.NotifyMainFrameCausedNoDamage(args);
80 } else {
81 collection_.NotifyMainFrameProcessed(args);
82 }
83 uint32_t frame_token = NextFrameToken();
84 collection_.NotifySubmitFrame(frame_token, has_missing_content,
85 viz::BeginFrameAck(args, true), args);
86 collection_.NotifyFrameEnd(args, args);
87 return frame_token;
88 } else {
89 collection_.NotifyImplFrameCausedNoDamage(
90 viz::BeginFrameAck(args, false));
91 collection_.NotifyMainFrameCausedNoDamage(args);
92 collection_.NotifyFrameEnd(args, args);
93 }
94 return 0;
95 }
96
NextFrameToken()97 uint32_t NextFrameToken() {
98 static uint32_t frame_token = 0;
99 return ++frame_token;
100 }
101
102 // Check whether a type of tracker exists in |frame_trackers_| or not.
TrackerExists(FrameSequenceTrackerType type) const103 bool TrackerExists(FrameSequenceTrackerType type) const {
104 return collection_.frame_trackers_.contains(type);
105 }
106
RemovalTrackerExists(unsigned index,FrameSequenceTrackerType type) const107 bool RemovalTrackerExists(unsigned index,
108 FrameSequenceTrackerType type) const {
109 DCHECK_GT(collection_.removal_trackers_.size(), index);
110 return collection_.removal_trackers_[index]->type_ == type;
111 }
112
GenerateSequence(const char * str)113 void GenerateSequence(const char* str) {
114 const uint64_t source_id = 1;
115 uint64_t current_frame = 0;
116 viz::BeginFrameArgs last_activated_main_args;
117 while (*str) {
118 const char command = *str++;
119 uint64_t sequence = 0, dummy = 0, last_activated_main = 0;
120 switch (command) {
121 case 'b':
122 case 'P':
123 case 'n':
124 case 's':
125 case 'E':
126 ASSERT_EQ(*str, '(') << command;
127 str = ParseNumber(++str, &sequence);
128 ASSERT_EQ(*str, ')');
129 ++str;
130 break;
131
132 case 'B':
133 case 'N':
134 ASSERT_EQ(*str, '(');
135 str = ParseNumber(++str, &dummy);
136 ASSERT_EQ(*str, ',');
137 str = ParseNumber(++str, &sequence);
138 ASSERT_EQ(*str, ')');
139 ++str;
140 break;
141
142 case 'e':
143 ASSERT_EQ(*str, '(');
144 str = ParseNumber(++str, &sequence);
145 ASSERT_EQ(*str, ',');
146 str = ParseNumber(++str, &last_activated_main);
147 ASSERT_EQ(*str, ')');
148 ++str;
149 break;
150
151 case 'R':
152 break;
153
154 default:
155 NOTREACHED() << command << str;
156 }
157
158 switch (command) {
159 case 'b':
160 current_frame = sequence;
161 collection_.NotifyBeginImplFrame(
162 CreateBeginFrameArgs(source_id, sequence));
163 break;
164
165 case 'P':
166 collection_.NotifyFramePresented(
167 sequence, {base::TimeTicks::Now(),
168 viz::BeginFrameArgs::DefaultInterval(), 0});
169 break;
170
171 case 'R':
172 collection_.NotifyPauseFrameProduction();
173 break;
174
175 case 'n':
176 collection_.NotifyImplFrameCausedNoDamage(
177 viz::BeginFrameAck(source_id, sequence, false, 0));
178 break;
179
180 case 's': {
181 auto frame_token = sequence;
182 if (current_frame == 0)
183 current_frame = 1;
184 auto args = CreateBeginFrameArgs(source_id, current_frame);
185 auto main_args = args;
186 if (*str == 'S') {
187 ++str;
188 ASSERT_EQ(*str, '(');
189 str = ParseNumber(++str, &sequence);
190 ASSERT_EQ(*str, ')');
191 ++str;
192 main_args = CreateBeginFrameArgs(source_id, sequence);
193 }
194 collection_.NotifySubmitFrame(
195 frame_token, /*has_missing_content=*/false,
196 viz::BeginFrameAck(args, true), main_args);
197 break;
198 }
199
200 case 'e': {
201 auto args = CreateBeginFrameArgs(source_id, sequence);
202 if (last_activated_main != 0)
203 DCHECK_EQ(last_activated_main_args.frame_id.sequence_number,
204 last_activated_main);
205 collection_.NotifyFrameEnd(args, last_activated_main_args);
206 break;
207 }
208
209 case 'E':
210 last_activated_main_args = CreateBeginFrameArgs(source_id, sequence);
211 collection_.NotifyMainFrameProcessed(last_activated_main_args);
212 break;
213
214 case 'B':
215 collection_.NotifyBeginMainFrame(
216 CreateBeginFrameArgs(source_id, sequence));
217 break;
218
219 case 'N':
220 collection_.NotifyMainFrameCausedNoDamage(
221 CreateBeginFrameArgs(source_id, sequence));
222 break;
223
224 default:
225 NOTREACHED();
226 }
227 }
228 }
229
ReportMetrics()230 void ReportMetrics() { tracker_->metrics_->ReportMetrics(); }
231
TimeDeltaToReort() const232 base::TimeDelta TimeDeltaToReort() const {
233 return tracker_->time_delta_to_report_;
234 }
235
NumberOfTrackers() const236 unsigned NumberOfTrackers() const {
237 return collection_.frame_trackers_.size();
238 }
NumberOfCustomTrackers() const239 unsigned NumberOfCustomTrackers() const {
240 return collection_.custom_frame_trackers_.size();
241 }
NumberOfRemovalTrackers() const242 unsigned NumberOfRemovalTrackers() const {
243 return collection_.removal_trackers_.size();
244 }
245
BeginImplFrameDataPreviousSequence() const246 uint64_t BeginImplFrameDataPreviousSequence() const {
247 return tracker_->begin_impl_frame_data_.previous_sequence;
248 }
BeginMainFrameDataPreviousSequence() const249 uint64_t BeginMainFrameDataPreviousSequence() const {
250 return tracker_->begin_main_frame_data_.previous_sequence;
251 }
252
IgnoredFrameTokens() const253 base::flat_set<uint32_t> IgnoredFrameTokens() const {
254 return tracker_->ignored_frame_tokens_;
255 }
256
ImplThroughput() const257 FrameSequenceMetrics::ThroughputData& ImplThroughput() const {
258 return tracker_->impl_throughput();
259 }
MainThroughput() const260 FrameSequenceMetrics::ThroughputData& MainThroughput() const {
261 return tracker_->main_throughput();
262 }
AggregatedThroughput() const263 FrameSequenceMetrics::ThroughputData& AggregatedThroughput() const {
264 return tracker_->aggregated_throughput();
265 }
266
SetTerminationStatus(FrameSequenceTracker::TerminationStatus status)267 void SetTerminationStatus(FrameSequenceTracker::TerminationStatus status) {
268 tracker_->termination_status_ = status;
269 }
270
GetTerminationStatus()271 FrameSequenceTracker::TerminationStatus GetTerminationStatus() {
272 return tracker_->termination_status_;
273 }
274
GetTerminationStatusForTracker(FrameSequenceTracker * tracker)275 FrameSequenceTracker::TerminationStatus GetTerminationStatusForTracker(
276 FrameSequenceTracker* tracker) {
277 return tracker->termination_status_;
278 }
279
280 protected:
number_of_frames_checkerboarded() const281 uint32_t number_of_frames_checkerboarded() const {
282 return tracker_->metrics_->frames_checkerboarded();
283 }
284
285 std::unique_ptr<CompositorFrameReportingController>
286 compositor_frame_reporting_controller_;
287 FrameSequenceTrackerCollection collection_;
288 FrameSequenceTracker* tracker_;
289 };
290
291 // Tests that the tracker works correctly when the source-id for the
292 // begin-frames change.
TEST_F(FrameSequenceTrackerTest,SourceIdChangeDuringSequence)293 TEST_F(FrameSequenceTrackerTest, SourceIdChangeDuringSequence) {
294 const uint64_t source_1 = 1;
295 uint64_t sequence_1 = 0;
296
297 // Dispatch some frames, both causing damage to impl/main, and both impl and
298 // main providing damage to the frame.
299 auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
300 DispatchCompleteFrame(args_1, kImplDamage | kMainDamage);
301 args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
302 DispatchCompleteFrame(args_1, kImplDamage | kMainDamage);
303
304 // Start a new tracker.
305 CreateNewTracker();
306
307 // Change the source-id, and start an impl frame. This time, the main-frame
308 // does not provide any damage.
309 const uint64_t source_2 = 2;
310 uint64_t sequence_2 = 0;
311 auto args_2 = CreateBeginFrameArgs(source_2, ++sequence_2);
312 collection_.NotifyBeginImplFrame(args_2);
313 collection_.NotifyBeginMainFrame(args_2);
314 collection_.NotifyMainFrameCausedNoDamage(args_2);
315 // Since the main-frame did not have any new damage from the latest
316 // BeginFrameArgs, the submit-frame will carry the previous BeginFrameArgs
317 // (from source_1);
318 collection_.NotifySubmitFrame(NextFrameToken(), /*has_missing_content=*/false,
319 viz::BeginFrameAck(args_2, true), args_1);
320 }
321
TEST_F(FrameSequenceTrackerTest,UniversalTrackerCreation)322 TEST_F(FrameSequenceTrackerTest, UniversalTrackerCreation) {
323 // The universal tracker should be explicitly created by the object that
324 // manages the |collection_|
325 EXPECT_FALSE(TrackerExists(FrameSequenceTrackerType::kUniversal));
326 }
327
TEST_F(FrameSequenceTrackerTest,UniversalTrackerRestartableAfterClearAll)328 TEST_F(FrameSequenceTrackerTest, UniversalTrackerRestartableAfterClearAll) {
329 collection_.StartSequence(FrameSequenceTrackerType::kUniversal);
330 EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kUniversal));
331
332 collection_.ClearAll();
333 EXPECT_FALSE(TrackerExists(FrameSequenceTrackerType::kUniversal));
334
335 collection_.StartSequence(FrameSequenceTrackerType::kUniversal);
336 EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kUniversal));
337 }
338
TEST_F(FrameSequenceTrackerTest,TestNotifyFramePresented)339 TEST_F(FrameSequenceTrackerTest, TestNotifyFramePresented) {
340 collection_.StartSequence(FrameSequenceTrackerType::kCompositorAnimation);
341 collection_.StartSequence(FrameSequenceTrackerType::kMainThreadAnimation);
342 // The kTouchScroll tracker is created in the test constructor, and the
343 // kUniversal tracker is created in the FrameSequenceTrackerCollection
344 // constructor.
345 EXPECT_EQ(NumberOfTrackers(), 3u);
346 collection_.StartSequence(FrameSequenceTrackerType::kUniversal);
347 EXPECT_EQ(NumberOfTrackers(), 4u);
348
349 collection_.StopSequence(FrameSequenceTrackerType::kCompositorAnimation);
350 EXPECT_EQ(NumberOfTrackers(), 3u);
351 EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kMainThreadAnimation));
352 EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kTouchScroll));
353 // StopSequence should have destroyed all trackers because there is no frame
354 // awaiting presentation.
355 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
356 }
357
358 // Base case for checkerboarding: present a single frame with checkerboarding,
359 // followed by a non-checkerboard frame.
TEST_F(FrameSequenceTrackerTest,CheckerboardingSimple)360 TEST_F(FrameSequenceTrackerTest, CheckerboardingSimple) {
361 CreateNewTracker();
362
363 const uint64_t source_1 = 1;
364 uint64_t sequence_1 = 0;
365
366 // Dispatch some frames, both causing damage to impl/main, and both impl and
367 // main providing damage to the frame.
368 auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
369 bool has_missing_content = true;
370 auto frame_token = DispatchCompleteFrame(args_1, kImplDamage | kMainDamage,
371 has_missing_content);
372
373 const auto interval = viz::BeginFrameArgs::DefaultInterval();
374 gfx::PresentationFeedback feedback(base::TimeTicks::Now(), interval, 0);
375 collection_.NotifyFramePresented(frame_token, feedback);
376
377 // Submit another frame with no checkerboarding.
378 has_missing_content = false;
379 frame_token =
380 DispatchCompleteFrame(CreateBeginFrameArgs(source_1, ++sequence_1),
381 kImplDamage | kMainDamage, has_missing_content);
382 feedback =
383 gfx::PresentationFeedback(base::TimeTicks::Now() + interval, interval, 0);
384 collection_.NotifyFramePresented(frame_token, feedback);
385
386 EXPECT_EQ(1u, number_of_frames_checkerboarded());
387 }
388
389 // Present a single frame with checkerboarding, followed by a non-checkerboard
390 // frame after a few vsyncs.
TEST_F(FrameSequenceTrackerTest,CheckerboardingMultipleFrames)391 TEST_F(FrameSequenceTrackerTest, CheckerboardingMultipleFrames) {
392 CreateNewTracker();
393
394 const uint64_t source_1 = 1;
395 uint64_t sequence_1 = 0;
396
397 // Dispatch some frames, both causing damage to impl/main, and both impl and
398 // main providing damage to the frame.
399 auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
400 bool has_missing_content = true;
401 auto frame_token = DispatchCompleteFrame(args_1, kImplDamage | kMainDamage,
402 has_missing_content);
403
404 const auto interval = viz::BeginFrameArgs::DefaultInterval();
405 gfx::PresentationFeedback feedback(base::TimeTicks::Now(), interval, 0);
406 collection_.NotifyFramePresented(frame_token, feedback);
407
408 // Submit another frame with no checkerboarding.
409 has_missing_content = false;
410 frame_token =
411 DispatchCompleteFrame(CreateBeginFrameArgs(source_1, ++sequence_1),
412 kImplDamage | kMainDamage, has_missing_content);
413 feedback = gfx::PresentationFeedback(base::TimeTicks::Now() + interval * 3,
414 interval, 0);
415 collection_.NotifyFramePresented(frame_token, feedback);
416
417 EXPECT_EQ(3u, number_of_frames_checkerboarded());
418 }
419
420 // Present multiple checkerboarded frames, followed by a non-checkerboard
421 // frame.
TEST_F(FrameSequenceTrackerTest,MultipleCheckerboardingFrames)422 TEST_F(FrameSequenceTrackerTest, MultipleCheckerboardingFrames) {
423 CreateNewTracker();
424
425 const uint32_t kFrames = 3;
426 const uint64_t source_1 = 1;
427 uint64_t sequence_1 = 0;
428
429 // Submit |kFrames| number of frames with checkerboarding.
430 std::vector<uint32_t> frames;
431 for (uint32_t i = 0; i < kFrames; ++i) {
432 auto args_1 = CreateBeginFrameArgs(source_1, ++sequence_1);
433 bool has_missing_content = true;
434 auto frame_token = DispatchCompleteFrame(args_1, kImplDamage | kMainDamage,
435 has_missing_content);
436 frames.push_back(frame_token);
437 }
438
439 base::TimeTicks present_now = base::TimeTicks::Now();
440 const auto interval = viz::BeginFrameArgs::DefaultInterval();
441 for (auto frame_token : frames) {
442 gfx::PresentationFeedback feedback(present_now, interval, 0);
443 collection_.NotifyFramePresented(frame_token, feedback);
444 present_now += interval;
445 }
446
447 // Submit another frame with no checkerboarding.
448 bool has_missing_content = false;
449 auto frame_token =
450 DispatchCompleteFrame(CreateBeginFrameArgs(source_1, ++sequence_1),
451 kImplDamage | kMainDamage, has_missing_content);
452 gfx::PresentationFeedback feedback(present_now, interval, 0);
453 collection_.NotifyFramePresented(frame_token, feedback);
454
455 EXPECT_EQ(kFrames, number_of_frames_checkerboarded());
456 }
457
TEST_F(FrameSequenceTrackerTest,ReportMetrics)458 TEST_F(FrameSequenceTrackerTest, ReportMetrics) {
459 base::HistogramTester histogram_tester;
460
461 // Test that there is no main thread frames expected.
462 ImplThroughput().frames_expected = 100u;
463 ImplThroughput().frames_produced = 85u;
464 ReportMetrics();
465 histogram_tester.ExpectTotalCount(
466 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll",
467 1u);
468 histogram_tester.ExpectTotalCount(
469 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll", 0u);
470 histogram_tester.ExpectTotalCount(
471 "Graphics.Smoothness.PercentDroppedFrames.SlowerThread.TouchScroll", 1u);
472
473 // Test that both are reported.
474 ImplThroughput().frames_expected = 100u;
475 ImplThroughput().frames_produced = 85u;
476 MainThroughput().frames_expected = 150u;
477 MainThroughput().frames_produced = 25u;
478 ReportMetrics();
479 histogram_tester.ExpectTotalCount(
480 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll",
481 2u);
482 histogram_tester.ExpectTotalCount(
483 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll", 1u);
484 histogram_tester.ExpectTotalCount(
485 "Graphics.Smoothness.PercentDroppedFrames.SlowerThread.TouchScroll", 2u);
486
487 // Test that none is reported.
488 MainThroughput().frames_expected = 2u;
489 MainThroughput().frames_produced = 1u;
490 ImplThroughput().frames_expected = 2u;
491 ImplThroughput().frames_produced = 1u;
492 ReportMetrics();
493 histogram_tester.ExpectTotalCount(
494 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll",
495 2u);
496 histogram_tester.ExpectTotalCount(
497 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll", 1u);
498 histogram_tester.ExpectTotalCount(
499 "Graphics.Smoothness.PercentDroppedFrames.SlowerThread.TouchScroll", 2u);
500
501 // Test the case where compositor and main thread have the same throughput.
502 ImplThroughput().frames_expected = 120u;
503 ImplThroughput().frames_produced = 118u;
504 MainThroughput().frames_expected = 120u;
505 MainThroughput().frames_produced = 118u;
506 ReportMetrics();
507 histogram_tester.ExpectTotalCount(
508 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll",
509 3u);
510 histogram_tester.ExpectTotalCount(
511 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll", 2u);
512 histogram_tester.ExpectTotalCount(
513 "Graphics.Smoothness.PercentDroppedFrames.SlowerThread.TouchScroll", 3u);
514 }
515
TEST_F(FrameSequenceTrackerTest,ReportMetricsAtFixedInterval)516 TEST_F(FrameSequenceTrackerTest, ReportMetricsAtFixedInterval) {
517 const uint64_t source = 1;
518 uint64_t sequence = 0;
519 base::TimeDelta first_time_delta = base::TimeDelta::FromSeconds(1);
520 auto args = CreateBeginFrameArgs(source, ++sequence,
521 base::TimeTicks::Now() + first_time_delta);
522
523 // args.frame_time is less than 5s of the tracker creation time, so won't
524 // schedule this tracker to report its throughput.
525 collection_.NotifyBeginImplFrame(args);
526 collection_.NotifyImplFrameCausedNoDamage(viz::BeginFrameAck(args, false));
527 collection_.NotifyFrameEnd(args, args);
528
529 EXPECT_EQ(NumberOfTrackers(), 1u);
530 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
531
532 ImplThroughput().frames_expected += 101;
533 // Now args.frame_time is 5s since the tracker creation time, so this tracker
534 // should be scheduled to report its throughput.
535 args = CreateBeginFrameArgs(source, ++sequence,
536 args.frame_time + TimeDeltaToReort());
537 collection_.NotifyBeginImplFrame(args);
538 collection_.NotifyImplFrameCausedNoDamage(viz::BeginFrameAck(args, false));
539 collection_.NotifyFrameEnd(args, args);
540 EXPECT_EQ(NumberOfTrackers(), 1u);
541 // At NotifyFrameEnd, the tracker is removed from removal_tracker_ list.
542 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
543 }
544
TEST_F(FrameSequenceTrackerTest,ReportWithoutBeginImplFrame)545 TEST_F(FrameSequenceTrackerTest, ReportWithoutBeginImplFrame) {
546 const uint64_t source = 1;
547 uint64_t sequence = 0;
548
549 auto args = CreateBeginFrameArgs(source, ++sequence);
550 collection_.NotifyBeginMainFrame(args);
551
552 EXPECT_EQ(BeginImplFrameDataPreviousSequence(), 0u);
553 // Call to ReportBeginMainFrame should early exit.
554 EXPECT_EQ(BeginMainFrameDataPreviousSequence(), 0u);
555
556 uint32_t frame_token = NextFrameToken();
557 collection_.NotifySubmitFrame(frame_token, false,
558 viz::BeginFrameAck(args, true), args);
559
560 // Call to ReportSubmitFrame should early exit.
561 EXPECT_TRUE(IgnoredFrameTokens().contains(frame_token));
562
563 gfx::PresentationFeedback feedback;
564 collection_.NotifyFramePresented(frame_token, feedback);
565 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
566 EXPECT_EQ(MainThroughput().frames_produced, 0u);
567 }
568
TEST_F(FrameSequenceTrackerTest,MainFrameTracking)569 TEST_F(FrameSequenceTrackerTest, MainFrameTracking) {
570 const uint64_t source = 1;
571 uint64_t sequence = 0;
572
573 auto args = CreateBeginFrameArgs(source, ++sequence);
574 auto frame_1 = DispatchCompleteFrame(args, kImplDamage | kMainDamage);
575
576 args = CreateBeginFrameArgs(source, ++sequence);
577 auto frame_2 = DispatchCompleteFrame(args, kImplDamage);
578
579 gfx::PresentationFeedback feedback;
580 collection_.NotifyFramePresented(frame_1, feedback);
581 collection_.NotifyFramePresented(frame_2, feedback);
582 }
583
TEST_F(FrameSequenceTrackerTest,MainFrameNoDamageTracking)584 TEST_F(FrameSequenceTrackerTest, MainFrameNoDamageTracking) {
585 const uint64_t source = 1;
586 uint64_t sequence = 0;
587
588 const auto first_args = CreateBeginFrameArgs(source, ++sequence);
589 DispatchCompleteFrame(first_args, kImplDamage | kMainDamage);
590
591 // Now, start the next frame, but for main, respond with the previous args.
592 const auto second_args = CreateBeginFrameArgs(source, ++sequence);
593 StartImplAndMainFrames(second_args);
594
595 uint32_t frame_token = NextFrameToken();
596 collection_.NotifySubmitFrame(frame_token, /*has_missing_content=*/false,
597 viz::BeginFrameAck(second_args, true),
598 first_args);
599 collection_.NotifyFrameEnd(second_args, second_args);
600
601 // Start and submit the next frame, with no damage from main.
602 auto args = CreateBeginFrameArgs(source, ++sequence);
603 collection_.NotifyBeginImplFrame(args);
604 frame_token = NextFrameToken();
605 collection_.NotifySubmitFrame(frame_token, /*has_missing_content=*/false,
606 viz::BeginFrameAck(args, true), first_args);
607 collection_.NotifyFrameEnd(args, args);
608
609 // Now, submit a frame with damage from main from |second_args|.
610 collection_.NotifyMainFrameProcessed(second_args);
611 args = CreateBeginFrameArgs(source, ++sequence);
612 StartImplAndMainFrames(args);
613 frame_token = NextFrameToken();
614 collection_.NotifySubmitFrame(frame_token, /*has_missing_content=*/false,
615 viz::BeginFrameAck(args, true), second_args);
616 collection_.NotifyFrameEnd(args, args);
617 }
618
TEST_F(FrameSequenceTrackerTest,BeginMainFrameSubmit)619 TEST_F(FrameSequenceTrackerTest, BeginMainFrameSubmit) {
620 // Start with a bunch of frames so that the metric does get reported at the
621 // end of the test.
622 ImplThroughput().frames_expected = 98u;
623 ImplThroughput().frames_produced = 98u;
624 MainThroughput().frames_expected = 98u;
625 MainThroughput().frames_produced = 98u;
626
627 const char sequence[] =
628 "b(1)B(0,1)n(1)e(1,0)b(2)E(1)B(1,2)s(1)S(1)e(2,1)P(1)";
629 GenerateSequence(sequence);
630 EXPECT_EQ(ImplThroughput().frames_expected, 99u);
631 EXPECT_EQ(MainThroughput().frames_expected, 100u);
632
633 base::HistogramTester histogram_tester;
634 ReportMetrics();
635
636 const char metric[] =
637 "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll";
638 histogram_tester.ExpectTotalCount(metric, 1u);
639 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
640 testing::ElementsAre(base::Bucket(1, 1)));
641 }
642
TEST_F(FrameSequenceTrackerTest,ScrollingThreadMetricCompositorThread)643 TEST_F(FrameSequenceTrackerTest, ScrollingThreadMetricCompositorThread) {
644 tracker_->metrics()->SetScrollingThread(
645 FrameSequenceMetrics::ThreadType::kCompositor);
646
647 // Start with a bunch of frames so that the metric does get reported at the
648 // end of the test.
649 ImplThroughput().frames_expected = 100u;
650 ImplThroughput().frames_produced = 100u;
651 MainThroughput().frames_expected = 100u;
652 MainThroughput().frames_produced = 90u;
653
654 base::HistogramTester histogram_tester;
655 ReportMetrics();
656
657 const char metric[] =
658 "Graphics.Smoothness.PercentDroppedFrames.ScrollingThread.TouchScroll";
659 histogram_tester.ExpectTotalCount(metric, 1u);
660 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
661 testing::ElementsAre(base::Bucket(0, 1)));
662 }
663
TEST_F(FrameSequenceTrackerTest,ScrollingThreadMetricMainThread)664 TEST_F(FrameSequenceTrackerTest, ScrollingThreadMetricMainThread) {
665 tracker_->metrics()->SetScrollingThread(
666 FrameSequenceMetrics::ThreadType::kMain);
667
668 // Start with a bunch of frames so that the metric does get reported at the
669 // end of the test.
670 ImplThroughput().frames_expected = 100u;
671 ImplThroughput().frames_produced = 100u;
672 MainThroughput().frames_expected = 100u;
673 MainThroughput().frames_produced = 90u;
674
675 base::HistogramTester histogram_tester;
676 ReportMetrics();
677
678 const char metric[] =
679 "Graphics.Smoothness.PercentDroppedFrames.ScrollingThread.TouchScroll";
680 histogram_tester.ExpectTotalCount(metric, 1u);
681 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
682 testing::ElementsAre(base::Bucket(10, 1)));
683 }
684
TEST_F(FrameSequenceTrackerTest,SimpleSequenceOneFrame)685 TEST_F(FrameSequenceTrackerTest, SimpleSequenceOneFrame) {
686 const char sequence[] = "b(1)B(0,1)s(1)S(1)e(1,0)P(1)";
687 GenerateSequence(sequence);
688 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
689 EXPECT_EQ(MainThroughput().frames_expected, 1u);
690 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
691 EXPECT_EQ(MainThroughput().frames_produced, 1u);
692 }
693
TEST_F(FrameSequenceTrackerTest,SimpleSequenceOneFrameNoDamage)694 TEST_F(FrameSequenceTrackerTest, SimpleSequenceOneFrameNoDamage) {
695 const char sequence[] = "b(1)B(0,1)N(1,1)n(1)e(1,0)";
696 GenerateSequence(sequence);
697 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
698 EXPECT_EQ(MainThroughput().frames_expected, 0u);
699 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
700 EXPECT_EQ(MainThroughput().frames_produced, 0u);
701
702 const char second_sequence[] = "b(2)B(1,2)n(2)N(2,2)e(2,0)";
703 GenerateSequence(second_sequence);
704 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
705 EXPECT_EQ(MainThroughput().frames_expected, 0u);
706 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
707 EXPECT_EQ(MainThroughput().frames_produced, 0u);
708 }
709
TEST_F(FrameSequenceTrackerTest,MultipleNoDamageNotifications)710 TEST_F(FrameSequenceTrackerTest, MultipleNoDamageNotifications) {
711 const char sequence[] = "b(1)n(1)n(1)e(1,0)";
712 GenerateSequence(sequence);
713 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
714 EXPECT_EQ(MainThroughput().frames_expected, 0u);
715 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
716 EXPECT_EQ(MainThroughput().frames_produced, 0u);
717 }
718
TEST_F(FrameSequenceTrackerTest,MultipleNoDamageNotificationsFromMain)719 TEST_F(FrameSequenceTrackerTest, MultipleNoDamageNotificationsFromMain) {
720 const char sequence[] = "b(1)B(0,1)N(1,1)n(1)N(0,1)e(1,0)";
721 GenerateSequence(sequence);
722 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
723 EXPECT_EQ(MainThroughput().frames_expected, 0u);
724 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
725 EXPECT_EQ(MainThroughput().frames_produced, 0u);
726 }
727
TEST_F(FrameSequenceTrackerTest,DelayedMainFrameNoDamage)728 TEST_F(FrameSequenceTrackerTest, DelayedMainFrameNoDamage) {
729 const char sequence[] =
730 "b(1)B(0,1)n(1)e(1,0)b(2)n(2)e(2,0)b(3)N(0,1)n(3)e(3,0)";
731 GenerateSequence(sequence);
732 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
733 EXPECT_EQ(MainThroughput().frames_expected, 0u);
734 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
735 EXPECT_EQ(MainThroughput().frames_produced, 0u);
736 }
737
TEST_F(FrameSequenceTrackerTest,DelayedMainFrameNoDamageFromOlderFrame)738 TEST_F(FrameSequenceTrackerTest, DelayedMainFrameNoDamageFromOlderFrame) {
739 // Start a sequence, and receive a 'no damage' from an earlier frame.
740 const char second_sequence[] = "b(2)B(0,2)N(2,1)n(2)N(2,2)e(2,0)";
741 GenerateSequence(second_sequence);
742 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
743 EXPECT_EQ(MainThroughput().frames_expected, 0u);
744 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
745 EXPECT_EQ(MainThroughput().frames_produced, 0u);
746 }
747
TEST_F(FrameSequenceTrackerTest,StateResetDuringSequence)748 TEST_F(FrameSequenceTrackerTest, StateResetDuringSequence) {
749 const char sequence[] = "b(1)B(0,1)n(1)N(1,1)Re(1,0)b(2)n(2)e(2,0)";
750 GenerateSequence(sequence);
751 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
752 EXPECT_EQ(MainThroughput().frames_expected, 0u);
753 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
754 EXPECT_EQ(MainThroughput().frames_produced, 0u);
755 }
756
TEST_F(FrameSequenceTrackerTest,NoCompositorDamageSubmitFrame)757 TEST_F(FrameSequenceTrackerTest, NoCompositorDamageSubmitFrame) {
758 const char sequence[] = "b(1)n(1)B(0,1)E(1)s(1)S(1)e(1,1)P(1)b(2)";
759 GenerateSequence(sequence);
760 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
761 EXPECT_EQ(MainThroughput().frames_expected, 1u);
762 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
763 EXPECT_EQ(MainThroughput().frames_produced, 1u);
764 }
765
TEST_F(FrameSequenceTrackerTest,SequenceStateResetsDuringFrame)766 TEST_F(FrameSequenceTrackerTest, SequenceStateResetsDuringFrame) {
767 const char sequence[] = "b(1)Rn(1)e(1,0)";
768 GenerateSequence(sequence);
769 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
770 EXPECT_EQ(MainThroughput().frames_expected, 0u);
771 EXPECT_EQ(ImplThroughput().frames_produced, 0u);
772 EXPECT_EQ(MainThroughput().frames_produced, 0u);
773
774 GenerateSequence("b(2)s(1)e(2,0)P(1)b(4)");
775 EXPECT_EQ(ImplThroughput().frames_expected, 3u);
776 EXPECT_EQ(MainThroughput().frames_expected, 0u);
777 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
778 EXPECT_EQ(MainThroughput().frames_produced, 0u);
779 }
780
TEST_F(FrameSequenceTrackerTest,BeginImplFrameBeforeTerminate)781 TEST_F(FrameSequenceTrackerTest, BeginImplFrameBeforeTerminate) {
782 const char sequence[] = "b(1)s(1)e(1,0)b(4)P(1)";
783 GenerateSequence(sequence);
784 EXPECT_EQ(ImplThroughput().frames_expected, 4u);
785 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
786 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
787 EXPECT_EQ(ImplThroughput().frames_expected, 4u);
788 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
789 }
790
791 // The following tests is for aggregating the compositor and main thread
792 // throughput. There are a few categories and each category have some tests.
793 // First category: no main frame involved.
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput1)794 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput1) {
795 const char sequence[] = "b(1)s(1)e(1,0)P(1)";
796 GenerateSequence(sequence);
797 // The test doesn't call TakeMetrics, so using the frames_expected in the
798 // ImplThroughput() to test the aggregated throughput.
799 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
800 EXPECT_EQ(AggregatedThroughput().frames_produced, 1u);
801 }
802
803 // Second category: one main frame and it responds in time.
804 // Main frame is submitted.
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput2)805 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput2) {
806 const char sequence[] = "b(1)B(0,1)E(1)s(1)S(1)e(1,1)P(1)";
807 GenerateSequence(sequence);
808 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
809 EXPECT_EQ(AggregatedThroughput().frames_produced, 1u);
810 }
811
812 // Main frame has no damage.
813 // variation: N(2,2) could be before s(1) or after.
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput3)814 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput3) {
815 const char sequence[] = "b(2)B(0,2)N(2,2)s(1)S(1)e(2,0)P(1)";
816 GenerateSequence(sequence);
817 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
818 EXPECT_EQ(AggregatedThroughput().frames_produced, 1u);
819 }
820
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput4)821 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput4) {
822 const char sequence[] = "b(2)B(0,2)s(1)S(1)N(2,2)e(2,0)P(1)";
823 GenerateSequence(sequence);
824 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
825 EXPECT_EQ(AggregatedThroughput().frames_produced, 1u);
826 }
827
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput5)828 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput5) {
829 const char sequence[] = "b(2)B(0,2)s(1)S(1)e(2,0)P(1)N(2,2)";
830 GenerateSequence(sequence);
831 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
832 EXPECT_EQ(AggregatedThroughput().frames_produced, 1u);
833 }
834
835 // Third category: one main frame and responds slowly.
836 // variation: the main frame could either report no-damage or submitted. The
837 // presentation of the first frame could arrive at different time.
838 // Main frame is submitted, P(1) could arrive at different time.
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput6)839 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput6) {
840 // At ReportSubmitFrame, |main_changes_after_sequence_start| is false at
841 // s(1)S(1).
842 const char sequence[] =
843 "b(2)B(0,2)s(1)S(1)e(2,0)b(3)E(1)s(2)S(2)e(3,1)P(1)P(2)";
844 GenerateSequence(sequence);
845 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
846 EXPECT_EQ(AggregatedThroughput().frames_produced, 1u);
847 }
848
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput7)849 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput7) {
850 const char sequence[] =
851 "b(2)B(0,2)s(1)S(1)e(2,0)P(1)b(3)E(1)s(2)S(2)e(3,1)P(2)";
852 GenerateSequence(sequence);
853 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
854 EXPECT_EQ(AggregatedThroughput().frames_produced, 1u);
855 }
856
857 // The main frame eventually reports no-damage.
858 // variation: P(1) arrives at different time, N(1,1) arrives before or after
859 // s(2).
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput8)860 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput8) {
861 const char sequence[] =
862 "b(2)B(0,2)s(1)S(1)e(2,0)b(3)s(2)S(1)N(2,2)e(3,0)P(1)P(2)";
863 GenerateSequence(sequence);
864 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
865 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
866 }
867
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput9)868 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput9) {
869 const char sequence[] =
870 "b(2)B(0,2)s(1)S(1)e(2,0)b(3)N(2,2)s(2)S(1)e(3,0)P(1)P(2)";
871 GenerateSequence(sequence);
872 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
873 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
874 }
875
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput10)876 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput10) {
877 const char sequence[] =
878 "b(2)B(0,2)s(1)S(1)e(2,0)P(1)b(3)N(2,2)s(2)S(1)e(3,0)P(2)";
879 GenerateSequence(sequence);
880 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
881 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
882 }
883
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput11)884 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput11) {
885 const char sequence[] =
886 "b(2)B(0,2)s(1)S(1)e(2,0)b(3)N(2,2)P(1)s(2)S(1)e(3,0)P(2)";
887 GenerateSequence(sequence);
888 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
889 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
890 }
891
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput12)892 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput12) {
893 const char sequence[] =
894 "b(2)B(0,2)s(1)S(1)e(2,0)P(1)b(3)s(2)S(1)N(2,2)e(3,0)P(2)";
895 GenerateSequence(sequence);
896 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
897 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
898 }
899
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput13)900 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput13) {
901 const char sequence[] =
902 "b(2)B(0,2)s(1)S(1)e(2,0)b(3)s(2)S(1)P(1)N(2,2)e(3,0)P(2)";
903 GenerateSequence(sequence);
904 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
905 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
906 }
907
908 // Fourth category: one main frame responds in time, but presentation comes
909 // late.
910 // variation: the main frame could be submitted or no damage.
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput14)911 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput14) {
912 const char sequence[] =
913 "b(1)B(0,1)E(1)s(1)S(1)e(1,1)b(2)s(2)S(1)e(2,1)P(1)P(2)";
914 GenerateSequence(sequence);
915 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
916 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
917 }
918
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput15)919 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput15) {
920 const char sequence[] =
921 "b(2)B(0,2)N(2,2)s(1)S(1)e(2,0)b(3)s(2)S(1)e(3,0)P(1)P(2)";
922 GenerateSequence(sequence);
923 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
924 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
925 }
926
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput16)927 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput16) {
928 const char sequence[] =
929 "b(2)B(0,2)s(1)S(1)N(2,2)e(2,0)b(3)s(2)S(1)e(3,0)P(1)P(2)";
930 GenerateSequence(sequence);
931 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
932 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
933 }
934
935 // Fifth category: two main frames, both responds in time.
936 // variation: it is enough that one main frame is submitted, or both are. The
937 // presentation of the first frame could arrive at different time.
938 // Both main frames are submitted, P(1) could arrive at different time.
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput17)939 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput17) {
940 const char sequence[] =
941 "b(1)B(0,1)E(1)s(1)S(1)e(1,1)P(1)b(2)B(1,2)E(2)s(2)S(2)e(2,2)P(2)";
942 GenerateSequence(sequence);
943 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
944 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
945 }
946
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput18)947 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput18) {
948 const char sequence[] =
949 "b(1)B(0,1)E(1)s(1)S(1)e(1,1)b(2)B(1,2)E(2)s(2)S(2)e(2,2)P(1)P(2)";
950 GenerateSequence(sequence);
951 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
952 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
953 }
954
955 // The second main frame has no damage.
956 // variation: N could come before or after s(2), and P(1) could arrive at
957 // different time.
958 // N after s(2).
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput19)959 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput19) {
960 const char sequence[] =
961 "b(2)B(0,2)E(2)s(1)S(2)e(2,2)b(3)B(2,3)s(2)S(1)N(3,3)e(3,2)P(1)P(2)";
962 GenerateSequence(sequence);
963 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
964 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
965 }
966
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput20)967 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput20) {
968 const char sequence[] =
969 "b(2)B(0,2)E(2)s(1)S(2)e(2,2)P(1)b(3)B(2,3)s(2)S(1)N(3,3)e(3,2)P(2)";
970 GenerateSequence(sequence);
971 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
972 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
973 }
974
975 // N before s(2).
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput21)976 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput21) {
977 const char sequence[] =
978 "b(2)B(0,2)E(2)s(1)S(2)e(2,2)b(3)B(2,3)N(3,3)s(2)S(1)e(3,2)P(1)P(2)";
979 GenerateSequence(sequence);
980 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
981 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
982 }
983
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput22)984 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput22) {
985 const char sequence[] =
986 "b(2)B(0,2)E(2)s(1)S(2)e(2,2)P(1)b(3)B(2,3)N(3,3)s(2)S(1)e(3,2)P(2)";
987 GenerateSequence(sequence);
988 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
989 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
990 }
991
992 // First main frame no damage.
993 // N before s(1).
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput23)994 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput23) {
995 const char sequence[] =
996 "b(2)B(0,2)N(2,2)s(1)S(1)e(2,0)P(1)b(3)B(0,3)E(3)s(2)S(3)e(3,3)P(2)";
997 GenerateSequence(sequence);
998 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
999 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
1000 }
1001
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput24)1002 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput24) {
1003 const char sequence[] =
1004 "b(2)B(0,2)N(2,2)s(1)S(1)e(2,0)b(3)B(0,3)E(3)s(2)S(3)e(3,3)P(1)P(2)";
1005 GenerateSequence(sequence);
1006 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
1007 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
1008 }
1009
1010 // N after s(1).
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput25)1011 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput25) {
1012 const char sequence[] =
1013 "b(2)B(0,2)s(1)S(1)N(2,2)e(2,0)P(1)b(3)B(0,3)E(3)s(2)S(3)e(3,3)P(2)";
1014 GenerateSequence(sequence);
1015 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
1016 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
1017 }
1018
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput26)1019 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput26) {
1020 const char sequence[] =
1021 "b(2)B(0,2)s(1)S(1)N(2,2)e(2,0)b(3)B(0,3)E(3)s(2)S(3)e(3,3)P(1)P(2)";
1022 GenerateSequence(sequence);
1023 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
1024 EXPECT_EQ(AggregatedThroughput().frames_produced, 2u);
1025 }
1026
1027 // Following tests comes from test cases on the bots.
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput27)1028 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput27) {
1029 const char sequence[] = "b(2)B(0,2)s(1)S(1)e(2,0)E(2)P(1)b(3)P(2)";
1030 GenerateSequence(sequence);
1031 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
1032 EXPECT_EQ(AggregatedThroughput().frames_produced, 0u);
1033 }
1034
1035 // At ReportSubmitFrame, |main_changes_include_new_changes| is false at
1036 // s(2)S(1).
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput28)1037 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput28) {
1038 const char sequence[] =
1039 "b(1)B(0,1)E(1)s(1)S(1)e(1,1)P(1)b(2)B(1,2)s(2)S(1)e(2,1)P(2)";
1040 GenerateSequence(sequence);
1041 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
1042 EXPECT_EQ(AggregatedThroughput().frames_produced, 1u);
1043 }
1044
1045 // At ReportSubmitFrame, |main_change_had_no_damage| is true at s(1)S(1).
TEST_F(FrameSequenceTrackerTest,AggregatedThroughput29)1046 TEST_F(FrameSequenceTrackerTest, AggregatedThroughput29) {
1047 const char sequence[] =
1048 "b(1)B(0,1)n(1)N(1,1)e(1,0)b(2)B(0,2)s(1)S(1)e(2,0)P(1)";
1049 GenerateSequence(sequence);
1050 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1051 EXPECT_EQ(AggregatedThroughput().frames_produced, 0u);
1052 }
1053
1054 // b(2417)B(0,2417)E(2417)n(2417)N(2417,2417)
TEST_F(FrameSequenceTrackerTest,SequenceNumberReset)1055 TEST_F(FrameSequenceTrackerTest, SequenceNumberReset) {
1056 const char sequence[] =
1057 "b(6)B(0,6)n(6)e(6,0)Rb(1)B(0,1)N(1,1)n(1)e(1,0)b(2)B(1,2)n(2)e(2,0)";
1058 GenerateSequence(sequence);
1059 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
1060 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1061 }
1062
TEST_F(FrameSequenceTrackerTest,MainThroughputWithHighLatency)1063 TEST_F(FrameSequenceTrackerTest, MainThroughputWithHighLatency) {
1064 const char sequence[] = "b(1)B(0,1)n(1)e(1,0)b(2)E(1)s(1)S(1)e(2,1)P(1)";
1065 GenerateSequence(sequence);
1066 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1067 EXPECT_EQ(ImplThroughput().frames_produced, 1u);
1068 EXPECT_EQ(MainThroughput().frames_expected, 2u);
1069 EXPECT_EQ(MainThroughput().frames_produced, 1u);
1070 }
1071
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame1)1072 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame1) {
1073 GenerateSequence("b(1)s(1)e(1,0)b(4)");
1074 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1075 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1076 FrameSequenceTracker* removal_tracker =
1077 collection_.GetRemovalTrackerForTesting(
1078 FrameSequenceTrackerType::kTouchScroll);
1079 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1080 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1081 GenerateSequence("P(1)");
1082 // There is still one impl-frame not processed not, so the tracker is not yet
1083 // ready for termination.
1084 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1085 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1086 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1087 }
1088
1089 // Following 3 cases are for: b(1)s(1)e(1,0)P(1), and StopSequence can happen
1090 // anywhere after b and before P.
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame2)1091 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame2) {
1092 base::HistogramTester histogram_tester;
1093 // Ensure we have enough data to report.
1094 ImplThroughput().frames_expected = 100u;
1095 ImplThroughput().frames_produced = 100u;
1096
1097 GenerateSequence("b(1)");
1098 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1099 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1100 FrameSequenceTracker* removal_tracker =
1101 collection_.GetRemovalTrackerForTesting(
1102 FrameSequenceTrackerType::kTouchScroll);
1103 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1104 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1105 GenerateSequence("s(1)e(1,0)P(1)");
1106 // Now the |removal_tracker| should have been destroyed.
1107 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1108
1109 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1110 // Both impl and slower threads reports 101 frames expected.
1111 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1112 // The main thread reports 0 frames expected.
1113 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1114 metric =
1115 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1116 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1117 }
1118
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame3)1119 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame3) {
1120 base::HistogramTester histogram_tester;
1121 // Ensure we have enough data to report.
1122 ImplThroughput().frames_expected = 100u;
1123 ImplThroughput().frames_produced = 100u;
1124
1125 GenerateSequence("b(1)s(1)");
1126 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1127 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1128 FrameSequenceTracker* removal_tracker =
1129 collection_.GetRemovalTrackerForTesting(
1130 FrameSequenceTrackerType::kTouchScroll);
1131 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1132 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1133 GenerateSequence("e(1,0)P(1)");
1134 // Now the |removal_tracker| should have been destroyed.
1135 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1136
1137 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1138 // Both impl and slower threads reports 101 frames expected.
1139 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1140 // The main thread reports 0 frames expected.
1141 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1142 metric =
1143 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1144 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1145 }
1146
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame4)1147 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame4) {
1148 base::HistogramTester histogram_tester;
1149 // Ensure we have enough data to report.
1150 ImplThroughput().frames_expected = 100u;
1151 ImplThroughput().frames_produced = 100u;
1152
1153 GenerateSequence("b(1)s(1)e(1,0)");
1154 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1155 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1156 FrameSequenceTracker* removal_tracker =
1157 collection_.GetRemovalTrackerForTesting(
1158 FrameSequenceTrackerType::kTouchScroll);
1159 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1160 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1161 GenerateSequence("P(1)");
1162 // Now the |removal_tracker| should have been destroyed.
1163 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1164
1165 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1166 // Both impl and slower threads reports 101 frames expected.
1167 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1168 // The main thread reports 0 frames expected.
1169 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1170 metric =
1171 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1172 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1173 }
1174
1175 // Following 2 cases are for: b(1)s(1)P(1), and StopSequence can happen
1176 // anywhere after b and before P. Because there is no e when P happens, the
1177 // tracker is not ready for termination.
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame5)1178 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame5) {
1179 GenerateSequence("b(1)");
1180 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1181 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1182 FrameSequenceTracker* removal_tracker =
1183 collection_.GetRemovalTrackerForTesting(
1184 FrameSequenceTrackerType::kTouchScroll);
1185 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1186 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1187 GenerateSequence("s(1)P(1)");
1188 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1189 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1190 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1191 }
1192
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame6)1193 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame6) {
1194 GenerateSequence("b(1)s(1)");
1195 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1196 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1197 FrameSequenceTracker* removal_tracker =
1198 collection_.GetRemovalTrackerForTesting(
1199 FrameSequenceTrackerType::kTouchScroll);
1200 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1201 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1202 GenerateSequence("P(1)");
1203 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1204 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1205 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1206 }
1207
1208 // All the following cases are for one complete impl + one incomplete:
1209 // b(1)s(1)e(1,0)xxxxxxxxP(1)
1210 // The 'xxxxx' is an incomplete impl frame that has no damage, it could be
1211 // 1. b(2)n(2)e(2,0)P(1), and StopSequence can happen anywhere after b and
1212 // before P.
1213 // 2. b(2)n(2)P(1), and StopSequence can happen anywhere after b and before P.
1214 // In this case, the tracker is not ready for termination yet because e never
1215 // happens.
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame7)1216 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame7) {
1217 base::HistogramTester histogram_tester;
1218 // Ensure we have enough data to report.
1219 ImplThroughput().frames_expected = 100u;
1220 ImplThroughput().frames_produced = 100u;
1221
1222 GenerateSequence("b(1)s(1)e(1,0)b(2)");
1223 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1224 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1225 FrameSequenceTracker* removal_tracker =
1226 collection_.GetRemovalTrackerForTesting(
1227 FrameSequenceTrackerType::kTouchScroll);
1228 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1229 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1230 GenerateSequence("n(2)e(2,0)P(1)");
1231 // Now the |removal_tracker| should have been destroyed.
1232 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1233
1234 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1235 // Both impl and slower threads reports 101 frames expected.
1236 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1237 // The main thread reports 0 frames expected.
1238 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1239 metric =
1240 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1241 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1242 }
1243
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame8)1244 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame8) {
1245 base::HistogramTester histogram_tester;
1246 // Ensure we have enough data to report.
1247 ImplThroughput().frames_expected = 100u;
1248 ImplThroughput().frames_produced = 100u;
1249
1250 GenerateSequence("b(1)s(1)e(1,0)b(2)n(2)");
1251 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1252 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1253 FrameSequenceTracker* removal_tracker =
1254 collection_.GetRemovalTrackerForTesting(
1255 FrameSequenceTrackerType::kTouchScroll);
1256 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1257 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1258 GenerateSequence("e(2,0)P(1)");
1259 // Now the |removal_tracker| should have been destroyed.
1260 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1261
1262 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1263 // Both impl and slower threads reports 101 frames expected.
1264 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1265 // The main thread reports 0 frames expected.
1266 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1267 metric =
1268 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1269 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1270 }
1271
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame9)1272 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame9) {
1273 base::HistogramTester histogram_tester;
1274 // Ensure we have enough data to report.
1275 ImplThroughput().frames_expected = 100u;
1276 ImplThroughput().frames_produced = 100u;
1277
1278 GenerateSequence("b(1)s(1)e(1,0)b(2)n(2)e(2,0)");
1279 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1280 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1281 FrameSequenceTracker* removal_tracker =
1282 collection_.GetRemovalTrackerForTesting(
1283 FrameSequenceTrackerType::kTouchScroll);
1284 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1285 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1286 GenerateSequence("P(1)");
1287 // Now the |removal_tracker| should have been destroyed.
1288 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1289
1290 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1291 // Both impl and slower threads reports 101 frames expected.
1292 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1293 // The main thread reports 0 frames expected.
1294 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1295 metric =
1296 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1297 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1298 }
1299
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame10)1300 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame10) {
1301 GenerateSequence("b(1)s(1)e(1,0)b(2)");
1302 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1303 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1304 FrameSequenceTracker* removal_tracker =
1305 collection_.GetRemovalTrackerForTesting(
1306 FrameSequenceTrackerType::kTouchScroll);
1307 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1308 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1309 GenerateSequence("n(2)P(1)");
1310 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1311 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1312 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1313 }
1314
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame11)1315 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame11) {
1316 GenerateSequence("b(1)s(1)e(1,0)b(2)n(2)");
1317 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1318 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1319 FrameSequenceTracker* removal_tracker =
1320 collection_.GetRemovalTrackerForTesting(
1321 FrameSequenceTrackerType::kTouchScroll);
1322 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1323 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1324 GenerateSequence("P(1)");
1325 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1326 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1327 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1328 }
1329
1330 // Following tests are for the case where the last impl-frame has no damage.
1331 // Basically b(1)s(1)e(1)P(1)b(2)n(2)e(2). And StopSequence can happen any time
1332 // after b(2).
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame12)1333 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame12) {
1334 base::HistogramTester histogram_tester;
1335 // Ensure we have enough data to report.
1336 ImplThroughput().frames_expected = 100u;
1337 ImplThroughput().frames_produced = 100u;
1338
1339 GenerateSequence("b(1)s(1)e(1,0)P(1)b(2)");
1340 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1341 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1342 FrameSequenceTracker* removal_tracker =
1343 collection_.GetRemovalTrackerForTesting(
1344 FrameSequenceTrackerType::kTouchScroll);
1345 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1346 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1347 GenerateSequence("n(2)e(2,0)");
1348 // Now the |removal_tracker| should have been destroyed.
1349 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1350
1351 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1352 // Both impl and slower threads reports 101 frames expected.
1353 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1354 // The main thread reports 0 frames expected.
1355 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1356 metric =
1357 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1358 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1359 }
1360
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame13)1361 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame13) {
1362 base::HistogramTester histogram_tester;
1363 // Ensure we have enough data to report.
1364 ImplThroughput().frames_expected = 100u;
1365 ImplThroughput().frames_produced = 100u;
1366
1367 GenerateSequence("b(1)s(1)e(1,0)P(1)b(2)n(2)");
1368 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1369 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1370 FrameSequenceTracker* removal_tracker =
1371 collection_.GetRemovalTrackerForTesting(
1372 FrameSequenceTrackerType::kTouchScroll);
1373 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1374 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1375 GenerateSequence("e(2,0)");
1376 // Now the |removal_tracker| should have been destroyed.
1377 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1378
1379 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1380 // Both impl and slower threads reports 101 frames expected.
1381 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1382 // The main thread reports 0 frames expected.
1383 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1384 metric =
1385 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1386 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1387 }
1388
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame14)1389 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame14) {
1390 base::HistogramTester histogram_tester;
1391 // Ensure we have enough data to report.
1392 ImplThroughput().frames_expected = 100u;
1393 ImplThroughput().frames_produced = 100u;
1394
1395 GenerateSequence("b(1)s(1)e(1,0)P(1)b(2)n(2)e(2,0)");
1396 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1397 // The tracker should have been removed from the removal_tracker_ list.
1398 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1399
1400 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1401 // Both impl and slower threads reports 101 frames expected.
1402 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1403 // The main thread reports 0 frames expected.
1404 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1405 metric =
1406 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1407 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1408 }
1409
1410 // Following tests are for the case where the presentation of the first impl
1411 // frame arrives late, and a second impl frame has started, and the tracker is
1412 // scheduled to terminate before the second impl frame starts. Basically:
1413 // 1. b(1)s(1)e(1,0)b(2)s(2)e(2,0)P(1), and StopSequence happens anywhere after
1414 // b(1) and before b(2)
1415 // 2. b(1)s(1)e(1,0)b(2)n(2)e(2,0)P(1), and StopSequence happens anywhere after
1416 // b(1) and before b(2)
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame15)1417 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame15) {
1418 base::HistogramTester histogram_tester;
1419 // Ensure we have enough data to report.
1420 ImplThroughput().frames_expected = 100u;
1421 ImplThroughput().frames_produced = 100u;
1422
1423 GenerateSequence("b(1)");
1424 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1425 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1426 FrameSequenceTracker* removal_tracker =
1427 collection_.GetRemovalTrackerForTesting(
1428 FrameSequenceTrackerType::kTouchScroll);
1429 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1430 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1431 GenerateSequence("s(1)e(1,0)b(2)s(2)e(2,0)P(1)");
1432 // Now the |removal_tracker| should have been destroyed.
1433 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1434
1435 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1436 // Both impl and slower threads reports 101 frames expected.
1437 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1438 // The main thread reports 0 frames expected.
1439 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1440 metric =
1441 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1442 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1443 }
1444
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame16)1445 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame16) {
1446 base::HistogramTester histogram_tester;
1447 // Ensure we have enough data to report.
1448 ImplThroughput().frames_expected = 100u;
1449 ImplThroughput().frames_produced = 100u;
1450
1451 GenerateSequence("b(1)s(1)");
1452 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1453 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1454 FrameSequenceTracker* removal_tracker =
1455 collection_.GetRemovalTrackerForTesting(
1456 FrameSequenceTrackerType::kTouchScroll);
1457 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1458 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1459 GenerateSequence("e(1,0)b(2)s(2)e(2,0)P(1)");
1460 // Now the |removal_tracker| should have been destroyed.
1461 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1462
1463 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1464 // Both impl and slower threads reports 101 frames expected.
1465 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1466 // The main thread reports 0 frames expected.
1467 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1468 metric =
1469 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1470 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1471 }
1472
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame17)1473 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame17) {
1474 base::HistogramTester histogram_tester;
1475 // Ensure we have enough data to report.
1476 ImplThroughput().frames_expected = 100u;
1477 ImplThroughput().frames_produced = 100u;
1478
1479 GenerateSequence("b(1)s(1)e(1,0)");
1480 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1481 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1482 FrameSequenceTracker* removal_tracker =
1483 collection_.GetRemovalTrackerForTesting(
1484 FrameSequenceTrackerType::kTouchScroll);
1485 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1486 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1487 GenerateSequence("b(2)s(2)e(2,0)P(1)");
1488 // Now the |removal_tracker| should have been destroyed.
1489 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1490
1491 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1492 // Both impl and slower threads reports 101 frames expected.
1493 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1494 // The main thread reports 0 frames expected.
1495 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1496 metric =
1497 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1498 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1499 }
1500
1501 // The second impl-frame has no damage.
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame18)1502 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame18) {
1503 base::HistogramTester histogram_tester;
1504 // Ensure we have enough data to report.
1505 ImplThroughput().frames_expected = 100u;
1506 ImplThroughput().frames_produced = 100u;
1507
1508 GenerateSequence("b(1)");
1509 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1510 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1511 FrameSequenceTracker* removal_tracker =
1512 collection_.GetRemovalTrackerForTesting(
1513 FrameSequenceTrackerType::kTouchScroll);
1514 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1515 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1516 GenerateSequence("s(1)e(1,0)b(2)n(2)e(2,0)P(1)");
1517 // Now the |removal_tracker| should have been destroyed.
1518 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1519
1520 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1521 // Both impl and slower threads reports 101 frames expected.
1522 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1523 // The main thread reports 0 frames expected.
1524 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1525 metric =
1526 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1527 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1528 }
1529
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame19)1530 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame19) {
1531 base::HistogramTester histogram_tester;
1532 // Ensure we have enough data to report.
1533 ImplThroughput().frames_expected = 100u;
1534 ImplThroughput().frames_produced = 100u;
1535
1536 GenerateSequence("b(1)s(1)");
1537 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1538 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1539 FrameSequenceTracker* removal_tracker =
1540 collection_.GetRemovalTrackerForTesting(
1541 FrameSequenceTrackerType::kTouchScroll);
1542 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1543 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1544 GenerateSequence("e(1,0)b(2)n(2)e(2,0)P(1)");
1545 // Now the |removal_tracker| should have been destroyed.
1546 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1547
1548 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1549 // Both impl and slower threads reports 101 frames expected.
1550 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1551 // The main thread reports 0 frames expected.
1552 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1553 metric =
1554 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1555 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1556 }
1557
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame20)1558 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame20) {
1559 base::HistogramTester histogram_tester;
1560 // Ensure we have enough data to report.
1561 ImplThroughput().frames_expected = 100u;
1562 ImplThroughput().frames_produced = 100u;
1563
1564 GenerateSequence("b(1)s(1)e(1,0)");
1565 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1566 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1567 FrameSequenceTracker* removal_tracker =
1568 collection_.GetRemovalTrackerForTesting(
1569 FrameSequenceTrackerType::kTouchScroll);
1570 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1571 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1572 GenerateSequence("b(2)n(2)e(2,0)P(1)");
1573 // Now the |removal_tracker| should have been destroyed.
1574 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1575
1576 std::string metric = "Graphics.Smoothness.FrameSequenceLength.TouchScroll";
1577 // Both impl and slower threads reports 101 frames expected.
1578 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 101), 2);
1579 // The main thread reports 0 frames expected.
1580 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1581 metric =
1582 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1583 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1584 }
1585
1586 // Following cases test that no frame needs to be presented, basically:
1587 // b(1)n(1)e(1,0), and StopSequence can happen anytime after b(1).
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame21)1588 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame21) {
1589 base::HistogramTester histogram_tester;
1590 // Ensure we have enough data to report.
1591 ImplThroughput().frames_expected = 100u;
1592 ImplThroughput().frames_produced = 100u;
1593
1594 GenerateSequence("b(1)");
1595 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1596 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1597 FrameSequenceTracker* removal_tracker =
1598 collection_.GetRemovalTrackerForTesting(
1599 FrameSequenceTrackerType::kTouchScroll);
1600 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1601 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1602 GenerateSequence("n(1)e(1,0)");
1603 // Ensure that this tracker is actually removed from the |removal_trackers_|
1604 // before the test terminates.
1605 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1606
1607 // If the tracker is terminated successfully, we should see this UMA.
1608 std::string metric =
1609 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1610 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1611 }
1612
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame22)1613 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame22) {
1614 base::HistogramTester histogram_tester;
1615 // Ensure we have enough data to report.
1616 ImplThroughput().frames_expected = 100u;
1617 ImplThroughput().frames_produced = 100u;
1618
1619 GenerateSequence("b(1)n(1)");
1620 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1621 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1622 FrameSequenceTracker* removal_tracker =
1623 collection_.GetRemovalTrackerForTesting(
1624 FrameSequenceTrackerType::kTouchScroll);
1625 EXPECT_EQ(GetTerminationStatusForTracker(removal_tracker),
1626 FrameSequenceTracker::TerminationStatus::kScheduledForTermination);
1627 GenerateSequence("e(1,0)");
1628 // Ensure that this tracker is actually removed from the |removal_trackers_|
1629 // before the test terminates.
1630 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1631
1632 // If the tracker is terminated successfully, we should see this UMA.
1633 std::string metric =
1634 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1635 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1636 }
1637
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame23)1638 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame23) {
1639 base::HistogramTester histogram_tester;
1640 // Ensure we have enough data to report.
1641 ImplThroughput().frames_expected = 100u;
1642 ImplThroughput().frames_produced = 100u;
1643
1644 GenerateSequence("b(1)n(1)e(1,0)");
1645 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1646 // Ensure that this tracker is actually removed from the |removal_trackers_|
1647 // before the test terminates.
1648 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1649
1650 // If the tracker is terminated successfully, we should see this UMA.
1651 std::string metric =
1652 "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.TouchScroll";
1653 EXPECT_EQ(histogram_tester.GetBucketCount(metric, 0), 1);
1654 }
1655
1656 // This test ensure that the tracker would terminate at e.
TEST_F(FrameSequenceTrackerTest,TrackLastImplFrame24)1657 TEST_F(FrameSequenceTrackerTest, TrackLastImplFrame24) {
1658 GenerateSequence("b(1)s(1)P(1)");
1659 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1660 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1661 GenerateSequence("e(1,0)");
1662 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1663 }
1664
TEST_F(FrameSequenceTrackerTest,IgnoredFrameTokensRemovedAtPresentation1)1665 TEST_F(FrameSequenceTrackerTest, IgnoredFrameTokensRemovedAtPresentation1) {
1666 GenerateSequence("b(5)");
1667 auto args = CreateBeginFrameArgs(/*source_id=*/1u, 1u);
1668 // Ack to an impl frame that doesn't exist in this tracker.
1669 collection_.NotifySubmitFrame(1, /*has_missing_content=*/false,
1670 viz::BeginFrameAck(args, true), args);
1671 EXPECT_EQ(IgnoredFrameTokens().size(), 1u);
1672 args = CreateBeginFrameArgs(1u, 5u);
1673 collection_.NotifySubmitFrame(2, false, viz::BeginFrameAck(args, true), args);
1674 GenerateSequence("e(5,0)b(6)");
1675 // Ack to an impl frame that doesn't exist in this tracker.
1676 args = CreateBeginFrameArgs(1u, 1u);
1677 collection_.NotifySubmitFrame(3, false, viz::BeginFrameAck(args, true), args);
1678 args = CreateBeginFrameArgs(1u, 6u);
1679 collection_.NotifySubmitFrame(4, false, viz::BeginFrameAck(args, true), args);
1680 EXPECT_EQ(IgnoredFrameTokens().size(), 2u);
1681 GenerateSequence("P(2)");
1682 // frame_token = 2 is presented, frame_token = 3 remains in the list.
1683 EXPECT_EQ(IgnoredFrameTokens().size(), 1u);
1684 GenerateSequence("P(4)");
1685 // Now frame_token = 4 is presented, frame_token = 3 should be removed.
1686 EXPECT_TRUE(IgnoredFrameTokens().empty());
1687 }
1688
1689 // Test the case where the frame tokens wraps around the 32-bit max value.
TEST_F(FrameSequenceTrackerTest,IgnoredFrameTokensRemovedAtPresentation2)1690 TEST_F(FrameSequenceTrackerTest, IgnoredFrameTokensRemovedAtPresentation2) {
1691 GenerateSequence("b(5)");
1692 auto args = CreateBeginFrameArgs(1u, 1u);
1693 // Ack to an impl frame that doesn't exist in this tracker.
1694 collection_.NotifySubmitFrame(UINT32_MAX, /*has_missing_content=*/false,
1695 viz::BeginFrameAck(args, true), args);
1696 EXPECT_EQ(IgnoredFrameTokens().size(), 1u);
1697
1698 args = CreateBeginFrameArgs(1u, 5u);
1699 collection_.NotifySubmitFrame(1, false, viz::BeginFrameAck(args, true), args);
1700 GenerateSequence("e(5,0)P(1)");
1701 EXPECT_TRUE(IgnoredFrameTokens().empty());
1702 }
1703
1704 // Test that a tracker is terminated after 3 submitted frames, remove this
1705 // once crbug.com/1072482 is fixed.
TEST_F(FrameSequenceTrackerTest,TerminationAfterThreeSubmissions1)1706 TEST_F(FrameSequenceTrackerTest, TerminationAfterThreeSubmissions1) {
1707 GenerateSequence("b(1)s(1)e(1,0)");
1708 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1709 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1710 GenerateSequence("b(2)s(2)e(2,0)b(3)s(3)e(3,0)b(4)s(4)e(4,0)b(5)s(5)e(5,0)");
1711 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1712 }
1713
TEST_F(FrameSequenceTrackerTest,TerminationAfterThreeSubmissions2)1714 TEST_F(FrameSequenceTrackerTest, TerminationAfterThreeSubmissions2) {
1715 GenerateSequence("b(1)");
1716 auto args = CreateBeginFrameArgs(1u, 1u);
1717 // Ack to an impl frame that doesn't exist in this tracker.
1718 collection_.NotifySubmitFrame(UINT32_MAX, /*has_missing_content=*/false,
1719 viz::BeginFrameAck(args, true), args);
1720 GenerateSequence("e(1,0)");
1721 collection_.StopSequence(FrameSequenceTrackerType::kTouchScroll);
1722 EXPECT_EQ(NumberOfRemovalTrackers(), 1u);
1723 GenerateSequence("b(2)s(1)e(2,0)b(3)s(2)e(3,0)b(4)s(3)e(4,0)");
1724 EXPECT_EQ(NumberOfRemovalTrackers(), 0u);
1725 }
1726
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage1)1727 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage1) {
1728 const char sequence[] =
1729 "b(1)B(0,1)n(1)e(1,0)b(2)E(1)B(1,2)n(2)e(2,1)b(3)E(2)B(2,3)n(3)e(3,2)";
1730 GenerateSequence(sequence);
1731 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
1732 // At E(2), B(0,1) is treated no damage.
1733 EXPECT_EQ(MainThroughput().frames_expected, 2u);
1734 }
1735
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage2)1736 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage2) {
1737 const char sequence[] =
1738 "b(1)B(0,1)n(1)e(1,0)b(2)E(1)B(1,2)n(2)e(2,1)b(3)n(3)e(3,1)b(4)n(4)e(4,1)"
1739 "b(8)E(2)"
1740 "B(8,8)n(8)e(8,2)";
1741 GenerateSequence(sequence);
1742 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
1743 // At E(2), B(0,1) is treated as no damage.
1744 EXPECT_EQ(MainThroughput().frames_expected, 7u);
1745 }
1746
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage3)1747 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage3) {
1748 const char sequence[] =
1749 "b(34)B(0,34)n(34)e(34,0)b(35)n(35)e(35,0)b(36)E(34)n(36)e(36,34)b(39)s("
1750 "1)e(39,34)";
1751 GenerateSequence(sequence);
1752 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1753 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1754 }
1755
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage4)1756 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage4) {
1757 const char sequence[] =
1758 "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)"
1759 "S(11)e(12,11)b(13)E(12)s(2)S(12)";
1760 GenerateSequence(sequence);
1761 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
1762 EXPECT_EQ(MainThroughput().frames_expected, 2u);
1763 }
1764
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage5)1765 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage5) {
1766 const char sequence[] =
1767 "b(1)B(0,1)E(1)s(1)S(1)e(1,0)b(2)n(2)e(2,0)b(3)B(1,3)n(3)e(3,0)E(3)b(4)B("
1768 "3,4)n("
1769 "4)e(4,3)E(4)";
1770 GenerateSequence(sequence);
1771 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1772 // At E(4), we treat B(1,3) as if it had no damage.
1773 EXPECT_EQ(MainThroughput().frames_expected, 3u);
1774 }
1775
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage6)1776 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage6) {
1777 const char sequence[] =
1778 "b(1)B(0,1)E(1)s(1)S(1)e(1,1)b(2)B(1,2)E(2)n(2)N(2,2)e(2,2)b(3)B(0,3)E(3)"
1779 "n(3)"
1780 "N(3,3)e(3,3)";
1781 GenerateSequence(sequence);
1782 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1783 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1784 }
1785
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage7)1786 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage7) {
1787 const char sequence[] =
1788 "b(8)B(0,8)n(8)e(8,0)b(9)E(8)B(8,9)E(9)s(1)S(8)e(9,9)b(10)s(2)S(9)e(10,"
1789 "9)";
1790 GenerateSequence(sequence);
1791 EXPECT_EQ(ImplThroughput().frames_expected, 2u);
1792 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1793 }
1794
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage8)1795 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage8) {
1796 const char sequence[] =
1797 "b(18)B(0,18)E(18)n(18)N(18,18)Re(18,18)b(20)B(0,20)N(20,20)n(20)N(0,20)"
1798 "e("
1799 "20,18)b(21)B(0,21)E(21)s(1)S(21)e(21,21)";
1800 GenerateSequence(sequence);
1801 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1802 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1803 }
1804
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage9)1805 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage9) {
1806 const char sequence[] =
1807 "b(78)n(78)Re(78,0)Rb(82)B(0,82)E(82)n(82)N(82,82)Re(82,82)b(86)B(0,86)E("
1808 "86)n("
1809 "86)e(86,86)b(87)s(1)S(86)e(87,86)";
1810 GenerateSequence(sequence);
1811 EXPECT_EQ(ImplThroughput().frames_expected, 1u);
1812 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1813 }
1814
TEST_F(FrameSequenceTrackerTest,OffScreenMainDamage10)1815 TEST_F(FrameSequenceTrackerTest, OffScreenMainDamage10) {
1816 const char sequence[] =
1817 "b(2)B(0,2)E(2)n(2)N(2,2)e(2,2)b(3)B(0,3)E(3)n(3)N(3,3)e(3,3)b(4)B(0,4)E("
1818 "4)n("
1819 "4)N(4,4)e(4,4)b(5)B(0,5)E(5)n(5)N(5,5)e(5,5)b(6)B(0,6)n(6)e(6,5)E(6)Rb("
1820 "8)B(0,"
1821 "8)E(8)n(8)N(8,8)e(8,8)";
1822 GenerateSequence(sequence);
1823 EXPECT_EQ(ImplThroughput().frames_expected, 0u);
1824 EXPECT_EQ(MainThroughput().frames_expected, 0u);
1825 }
1826
1827 // A presentation with a frame token that is > the main frame token submitted.
TEST_F(FrameSequenceTrackerTest,MainThreadPresentWithNonMatchedToken)1828 TEST_F(FrameSequenceTrackerTest, MainThreadPresentWithNonMatchedToken) {
1829 const char sequence[] = "b(1)B(0,1)E(1)s(1)S(1)e(1,0)b(2)s(2)S(1)e(2,1)P(2)";
1830 GenerateSequence(sequence);
1831 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1832 EXPECT_EQ(MainThroughput().frames_produced, 1u);
1833 }
1834
TEST_F(FrameSequenceTrackerTest,CoalescedMainThreadPresent)1835 TEST_F(FrameSequenceTrackerTest, CoalescedMainThreadPresent) {
1836 const char sequence[] =
1837 "b(1)B(0,1)E(1)s(1)S(1)e(1,1)b(2)B(1,2)E(2)s(2)S(2)e(2,2)P(2)";
1838 GenerateSequence(sequence);
1839 EXPECT_EQ(MainThroughput().frames_expected, 2u);
1840 EXPECT_EQ(MainThroughput().frames_produced, 1u);
1841 }
1842
TEST_F(FrameSequenceTrackerTest,MainThreadPresentWithNullTimeStamp)1843 TEST_F(FrameSequenceTrackerTest, MainThreadPresentWithNullTimeStamp) {
1844 const char sequence[] = "b(1)B(0,1)E(1)s(1)S(1)e(1,1)";
1845 GenerateSequence(sequence);
1846 collection_.NotifyFramePresented(
1847 1, {base::TimeTicks(), viz::BeginFrameArgs::DefaultInterval(), 0});
1848 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1849 // No presentation, no main frame produced.
1850 EXPECT_EQ(MainThroughput().frames_produced, 0u);
1851 GenerateSequence("b(2)s(2)S(1)e(2,0)P(2)");
1852 EXPECT_EQ(MainThroughput().frames_expected, 1u);
1853 // The main frame update is caught up here.
1854 EXPECT_EQ(MainThroughput().frames_produced, 1u);
1855 }
1856
TEST_F(FrameSequenceTrackerTest,TrackerTypeEncoding)1857 TEST_F(FrameSequenceTrackerTest, TrackerTypeEncoding) {
1858 // The test begins with a kTouchScroll tracker
1859 EXPECT_EQ(NumberOfTrackers(), 1u);
1860 ActiveFrameSequenceTrackers active_encoded =
1861 collection_.FrameSequenceTrackerActiveTypes();
1862 EXPECT_EQ(active_encoded, 16); // 1 << 4
1863 }
1864
TEST_F(FrameSequenceTrackerTest,CustomTrackers)1865 TEST_F(FrameSequenceTrackerTest, CustomTrackers) {
1866 // Start custom tracker 1.
1867 collection_.StartCustomSequence(1);
1868 EXPECT_EQ(1u, NumberOfCustomTrackers());
1869
1870 // No reports.
1871 uint32_t frame_token = 1u;
1872 collection_.NotifyFramePresented(frame_token, {});
1873 auto results = collection_.TakeCustomTrackerResults();
1874 EXPECT_EQ(0u, results.size());
1875
1876 // Start custom tracker 2 and 3 in addition to 1.
1877 collection_.StartCustomSequence(2);
1878 collection_.StartCustomSequence(3);
1879 EXPECT_EQ(3u, NumberOfCustomTrackers());
1880
1881 // All custom trackers are running. No reports.
1882 collection_.NotifyFramePresented(frame_token, {});
1883 results = collection_.TakeCustomTrackerResults();
1884 EXPECT_EQ(0u, results.size());
1885
1886 // Tracker 2 is stopped and scheduled to terminate.
1887 collection_.StopCustomSequence(2);
1888 EXPECT_EQ(2u, NumberOfCustomTrackers());
1889
1890 // Tracker 2 should report with no data.
1891 collection_.NotifyFramePresented(frame_token, {});
1892 results = collection_.TakeCustomTrackerResults();
1893 EXPECT_EQ(1u, results.size());
1894 EXPECT_EQ(0u, results[2].frames_expected);
1895
1896 // Simple sequence of one frame.
1897 const char sequence[] = "b(1)B(0,1)s(1)S(1)e(1,0)P(1)";
1898 GenerateSequence(sequence);
1899
1900 // Stop all custom trackers.
1901 collection_.StopCustomSequence(1);
1902 collection_.StopCustomSequence(3);
1903 EXPECT_EQ(0u, NumberOfCustomTrackers());
1904
1905 // Tracker 1 and 3 and should report.
1906 collection_.NotifyFramePresented(frame_token, {});
1907 results = collection_.TakeCustomTrackerResults();
1908 EXPECT_EQ(2u, results.size());
1909 EXPECT_EQ(1u, results[1].frames_produced);
1910 EXPECT_EQ(1u, results[1].frames_expected);
1911 EXPECT_EQ(1u, results[3].frames_produced);
1912 EXPECT_EQ(1u, results[3].frames_expected);
1913 }
1914
1915 } // namespace cc
1916