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