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/average_lag_tracker.h"
6 
7 #include <memory>
8 
9 #include "base/test/metrics/histogram_tester.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 
13 using base::Bucket;
14 using testing::ElementsAre;
15 
16 namespace cc {
17 namespace {
18 
19 class AverageLagTrackerTest : public testing::Test {
20  public:
AverageLagTrackerTest()21   AverageLagTrackerTest() { ResetHistograms(); }
22 
ResetHistograms()23   void ResetHistograms() {
24     histogram_tester_ = std::make_unique<base::HistogramTester>();
25   }
26 
histogram_tester()27   const base::HistogramTester& histogram_tester() { return *histogram_tester_; }
28 
SetUp()29   void SetUp() override {
30     average_lag_tracker_gpu_swap_ = std::make_unique<AverageLagTracker>(
31         AverageLagTracker::FinishTimeType::GpuSwapBegin);
32     average_lag_tracker_presentation_ = std::make_unique<AverageLagTracker>(
33         AverageLagTracker::FinishTimeType::PresentationFeedback);
34   }
35 
SyntheticTouchScrollBegin(base::TimeTicks event_time,base::TimeTicks frame_time,float delta,float predicted_delta=0)36   void SyntheticTouchScrollBegin(base::TimeTicks event_time,
37                                  base::TimeTicks frame_time,
38                                  float delta,
39                                  float predicted_delta = 0) {
40     AverageLagTracker::EventInfo event_info(
41         0, delta, predicted_delta != 0 ? predicted_delta : delta, event_time,
42         AverageLagTracker::EventType::ScrollBegin);
43     event_info.finish_timestamp = frame_time;
44 
45     // Always add the events to both and test if they have the same behavior
46     // regardless of the metrics names.
47     average_lag_tracker_gpu_swap_->AddScrollEventInFrame(event_info);
48     average_lag_tracker_presentation_->AddScrollEventInFrame(event_info);
49   }
50 
SyntheticTouchScrollUpdate(base::TimeTicks event_time,base::TimeTicks frame_time,float delta,float predicted_delta=0)51   void SyntheticTouchScrollUpdate(base::TimeTicks event_time,
52                                   base::TimeTicks frame_time,
53                                   float delta,
54                                   float predicted_delta = 0) {
55     AverageLagTracker::EventInfo event_info(
56         0, delta, predicted_delta != 0 ? predicted_delta : delta, event_time,
57         AverageLagTracker::EventType::ScrollUpdate);
58     event_info.finish_timestamp = frame_time;
59 
60     average_lag_tracker_gpu_swap_->AddScrollEventInFrame(event_info);
61     average_lag_tracker_presentation_->AddScrollEventInFrame(event_info);
62   }
63 
CheckScrollBeginHistograms(int bucket_value,int count)64   void CheckScrollBeginHistograms(int bucket_value, int count) {
65     EXPECT_THAT(histogram_tester().GetAllSamples(
66                     "Event.Latency.ScrollBegin.Touch.AverageLag"),
67                 ElementsAre(Bucket(bucket_value, count)));
68     EXPECT_THAT(histogram_tester().GetAllSamples(
69                     "Event.Latency.ScrollBegin.Touch.AverageLagPresentation"),
70                 ElementsAre(Bucket(bucket_value, count)));
71   }
72 
CheckScrollUpdateHistograms(int bucket_value,int count)73   void CheckScrollUpdateHistograms(int bucket_value, int count) {
74     EXPECT_THAT(histogram_tester().GetAllSamples(
75                     "Event.Latency.ScrollUpdate.Touch.AverageLag"),
76                 ElementsAre(Bucket(bucket_value, count)));
77 
78     EXPECT_THAT(histogram_tester().GetAllSamples(
79                     "Event.Latency.ScrollUpdate.Touch.AverageLagPresentation"),
80                 ElementsAre(Bucket(bucket_value, count)));
81   }
82 
CheckPredictionPositiveHistograms(int bucket_value,int count)83   void CheckPredictionPositiveHistograms(int bucket_value, int count) {
84     EXPECT_THAT(
85         histogram_tester().GetAllSamples(
86             "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionPositive"),
87         ElementsAre(Bucket(bucket_value, count)));
88 
89     EXPECT_THAT(histogram_tester().GetAllSamples(
90                     "Event.Latency.ScrollUpdate.Touch.AverageLagPresentation."
91                     "PredictionPositive"),
92                 ElementsAre(Bucket(bucket_value, count)));
93   }
94 
CheckPredictionNegativeHistograms(int bucket_value,int count)95   void CheckPredictionNegativeHistograms(int bucket_value, int count) {
96     EXPECT_THAT(
97         histogram_tester().GetAllSamples(
98             "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionNegative"),
99         ElementsAre(Bucket(bucket_value, count)));
100 
101     EXPECT_THAT(histogram_tester().GetAllSamples(
102                     "Event.Latency.ScrollUpdate.Touch.AverageLagPresentation."
103                     "PredictionNegative"),
104                 ElementsAre(Bucket(bucket_value, count)));
105   }
106 
CheckScrollUpdateHistogramsTotalCount(int count)107   void CheckScrollUpdateHistogramsTotalCount(int count) {
108     histogram_tester().ExpectTotalCount(
109         "Event.Latency.ScrollUpdate.Touch.AverageLag", count);
110     histogram_tester().ExpectTotalCount(
111         "Event.Latency.ScrollUpdate.Touch.AverageLagPresentation", count);
112   }
113 
CheckPredictionPositiveHistogramsTotalCount(int count)114   void CheckPredictionPositiveHistogramsTotalCount(int count) {
115     histogram_tester().ExpectTotalCount(
116         "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionPositive",
117         count);
118     histogram_tester().ExpectTotalCount(
119         "Event.Latency.ScrollUpdate.Touch.AverageLagPresentation."
120         "PredictionPositive",
121         count);
122   }
123 
CheckPredictionNegativeHistogramsTotalCount(int count)124   void CheckPredictionNegativeHistogramsTotalCount(int count) {
125     histogram_tester().ExpectTotalCount(
126         "Event.Latency.ScrollUpdate.Touch.AverageLag.PredictionNegative",
127         count);
128     histogram_tester().ExpectTotalCount(
129         "Event.Latency.ScrollUpdate.Touch.AverageLagPresentation."
130         "PredictionNegative",
131         count);
132   }
133 
134  protected:
135   std::unique_ptr<AverageLagTracker> average_lag_tracker_gpu_swap_;
136   std::unique_ptr<AverageLagTracker> average_lag_tracker_presentation_;
137 
138   std::unique_ptr<base::HistogramTester> histogram_tester_;
139 };
140 
MillisecondsToTimeTicks(float t_ms)141 base::TimeTicks MillisecondsToTimeTicks(float t_ms) {
142   return base::TimeTicks() + base::TimeDelta::FromMilliseconds(t_ms);
143 }
144 
145 // Simulate a simple situation that events at every 10ms and start at t=15ms,
146 // frame swaps at every 10ms too and start at t=20ms and test we record one
147 // UMA for ScrollUpdate in one second.
TEST_F(AverageLagTrackerTest,OneSecondInterval)148 TEST_F(AverageLagTrackerTest, OneSecondInterval) {
149   base::TimeTicks event_time =
150       base::TimeTicks() + base::TimeDelta::FromMilliseconds(5);
151   base::TimeTicks frame_time =
152       base::TimeTicks() + base::TimeDelta::FromMilliseconds(10);
153   float scroll_delta = 10;
154 
155   // ScrollBegin
156   event_time += base::TimeDelta::FromMilliseconds(10);  // 15ms
157   frame_time += base::TimeDelta::FromMilliseconds(10);  // 20ms
158   SyntheticTouchScrollBegin(event_time, frame_time, scroll_delta);
159 
160   // Send 101 ScrollUpdate events to verify that there is 1 AverageLag record
161   // per 1 second.
162   const int kUpdates = 101;
163   for (int i = 0; i < kUpdates; i++) {
164     event_time += base::TimeDelta::FromMilliseconds(10);
165     frame_time += base::TimeDelta::FromMilliseconds(10);
166     // First 50 has positive delta, others negetive delta.
167     const int sign = (i < kUpdates / 2) ? 1 : -1;
168     SyntheticTouchScrollUpdate(event_time, frame_time, sign * scroll_delta);
169   }
170 
171   // ScrollBegin report_time is at 20ms, so the next ScrollUpdate report_time is
172   // at 1020ms. The last event_time that finish this report should be later than
173   // 1020ms.
174   EXPECT_EQ(event_time,
175             base::TimeTicks() + base::TimeDelta::FromMilliseconds(1025));
176   EXPECT_EQ(frame_time,
177             base::TimeTicks() + base::TimeDelta::FromMilliseconds(1030));
178 
179   // ScrollBegin AverageLag are the area between the event original component
180   // (time=15ms, delta=10px) to the frame swap time (time=20ms, expect finger
181   // position at delta=15px). The AverageLag scaled to 1 second is
182   // (0.5*(10px+15px)*5ms)/5ms = 12.5px.
183   CheckScrollBeginHistograms(12, 1);
184 
185   // This ScrollUpdate AverageLag are calculated as the finger uniformly scroll
186   // 10px each frame. For scroll up/down frame, the Lag at the last frame swap
187   // is 5px, and Lag at this frame swap is 15px. For the one changing direction,
188   // the Lag is from 5 to 10 and down to 5 again. So total LagArea is 99 * 100,
189   // plus 75. the AverageLag in 1 second is 9.975px.
190   CheckScrollUpdateHistograms(9, 1);
191   CheckPredictionPositiveHistograms(0, 1);
192   CheckPredictionNegativeHistogramsTotalCount(0);
193 
194   ResetHistograms();
195 
196   // Send another ScrollBegin to end the unfinished ScrollUpdate report.
197   event_time += base::TimeDelta::FromMilliseconds(10);
198   frame_time += base::TimeDelta::FromMilliseconds(10);
199   SyntheticTouchScrollBegin(event_time, frame_time, scroll_delta);
200 
201   // The last ScrollUpdate's lag is 8.75px and truncated to 8.
202   CheckScrollUpdateHistograms(8, 1);
203   CheckPredictionPositiveHistograms(0, 1);
204   CheckPredictionNegativeHistogramsTotalCount(0);
205 }
206 
207 // Test the case that event's frame swap time is later than next event's
208 // creation time. (i.e, event at t=10ms will be dispatch at t=30ms, while next
209 // event is at t=20ms).
TEST_F(AverageLagTrackerTest,LargerLatency)210 TEST_F(AverageLagTrackerTest, LargerLatency) {
211   base::TimeTicks event_time = MillisecondsToTimeTicks(10);
212   base::TimeTicks frame_time =
213       event_time + base::TimeDelta::FromMilliseconds(20);
214   float scroll_delta = 10;
215 
216   SyntheticTouchScrollBegin(event_time, frame_time, scroll_delta);
217 
218   // Send 2 ScrollUpdate. The second one will record AverageLag.ScrollBegin as
219   // it's event_time is larger or equal to ScrollBegin's frame_time.
220   for (int i = 0; i < 2; i++) {
221     event_time += base::TimeDelta::FromMilliseconds(10);
222     frame_time = event_time + base::TimeDelta::FromMilliseconds(20);
223     SyntheticTouchScrollUpdate(event_time, frame_time, scroll_delta);
224   }
225 
226   // ScrollBegin AveragLag are from t=10ms to t=30ms, with absolute scroll
227   // position from 10 to 30. The AverageLag should be:
228   // (0.5*(10px + 30px)*20ms/20ms) = 20px.
229   CheckScrollBeginHistograms(20, 1);
230 
231   // Another ScrollBegin to flush unfinished frames.
232   // event_time doesn't matter here because the previous frames' lag are
233   // compute from their frame_time.
234   event_time = MillisecondsToTimeTicks(1000);
235   frame_time = MillisecondsToTimeTicks(1000);
236   SyntheticTouchScrollBegin(event_time, frame_time, scroll_delta);
237   // The to unfinished frames' lag are (finger_positon-rendered_position)*time,
238   // AverageLag is ((30px-10px)*10ms+(30px-20px)*10ms)/20ms = 15px.
239   CheckScrollUpdateHistograms(14, 1);
240 }
241 
242 // Test that multiple latency being flush in the same frame swap.
TEST_F(AverageLagTrackerTest,TwoLatencyInfoInSameFrame)243 TEST_F(AverageLagTrackerTest, TwoLatencyInfoInSameFrame) {
244   // ScrollBegin
245   base::TimeTicks event_time = MillisecondsToTimeTicks(10);
246   base::TimeTicks frame_time = MillisecondsToTimeTicks(20);
247   SyntheticTouchScrollBegin(event_time, frame_time, -10 /* scroll_delta */);
248 
249   // ScrollUpdate with event_time >= ScrollBegin frame_time will generate
250   // a histogram for AverageLag.ScrollBegin.
251   event_time = MillisecondsToTimeTicks(20);
252   frame_time = MillisecondsToTimeTicks(30);
253   SyntheticTouchScrollUpdate(event_time, frame_time, -10 /* scroll_delta */);
254 
255   // Absolute position from -10 to -20. The AverageLag should be:
256   // (0.5*(10px + 20px)*10ms/10ms) = 15px.
257   CheckScrollBeginHistograms(14, 1);
258 
259   event_time = MillisecondsToTimeTicks(25);
260   frame_time = MillisecondsToTimeTicks(30);
261   SyntheticTouchScrollUpdate(event_time, frame_time, 5 /* scroll_delta */);
262 
263   // Another ScrollBegin to flush unfinished frames.
264   event_time = MillisecondsToTimeTicks(1000);
265   frame_time = MillisecondsToTimeTicks(1000);
266   SyntheticTouchScrollBegin(event_time, frame_time, 0);
267 
268   // The ScrollUpdates are at t=20ms, finger_pos=-20px, rendered_pos=-10px,
269   // at t=25ms, finger_pos=-15px, rendered_pos=-10px;
270   // To t=30ms both events get flush.
271   // AverageLag is (0.5*(10px+5px)*5ms + 5px*5ms)/10ms = 6.25px
272   CheckScrollUpdateHistograms(6, 1);
273 }
274 
275 // Test the case that switching direction causes lag at current frame
276 // time and previous frame time are in different direction.
TEST_F(AverageLagTrackerTest,ChangeDirectionInFrame)277 TEST_F(AverageLagTrackerTest, ChangeDirectionInFrame) {
278   // ScrollBegin
279   base::TimeTicks event_time = MillisecondsToTimeTicks(10);
280   base::TimeTicks frame_time = MillisecondsToTimeTicks(20);
281   SyntheticTouchScrollBegin(event_time, frame_time, 10 /* scroll_delta */);
282 
283   // At t=20, lag = 10px.
284   event_time = MillisecondsToTimeTicks(20);
285   frame_time = MillisecondsToTimeTicks(30);
286   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */);
287 
288   // At t=30, lag = -10px.
289   event_time = MillisecondsToTimeTicks(30);
290   frame_time = MillisecondsToTimeTicks(40);
291   SyntheticTouchScrollUpdate(event_time, frame_time, -20 /* scroll_delta */);
292 
293   // Another ScrollBegin to flush unfinished frames.
294   event_time = MillisecondsToTimeTicks(1000);
295   frame_time = MillisecondsToTimeTicks(1000);
296   SyntheticTouchScrollBegin(event_time, frame_time, 0);
297 
298   // From t=20 to t=30, lag_area=2*(0.5*10px*5ms)=50px*ms.
299   // From t=30 to t=40, lag_area=20px*10ms=200px*ms
300   // AverageLag = (50+200)/20 = 12.5px.
301   CheckScrollUpdateHistograms(12, 1);
302 }
303 
304 // A simple case without scroll prediction to compare with the two with
305 // prediction cases below.
TEST_F(AverageLagTrackerTest,NoScrollPrediction)306 TEST_F(AverageLagTrackerTest, NoScrollPrediction) {
307   // ScrollBegin, at t=5, finger_pos=5px.
308   base::TimeTicks event_time = MillisecondsToTimeTicks(5);
309   base::TimeTicks frame_time = MillisecondsToTimeTicks(10);
310   SyntheticTouchScrollBegin(event_time, frame_time, 5 /* scroll_delta */);
311 
312   // ScrollUpdate, at t=15, finger_pos=15px.
313   event_time = MillisecondsToTimeTicks(15);
314   frame_time = MillisecondsToTimeTicks(20);
315   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */);
316 
317   // ScrollUpdate, at t=25, finger_pos=25px.
318   event_time = MillisecondsToTimeTicks(25);
319   frame_time = MillisecondsToTimeTicks(30);
320   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */);
321 
322   // Another ScrollBegin to flush unfinished frames.
323   event_time = MillisecondsToTimeTicks(1000);
324   frame_time = MillisecondsToTimeTicks(1000);
325   SyntheticTouchScrollBegin(event_time, frame_time, 0);
326 
327   // Prediction hasn't take affect on ScrollBegin so it'll stay the same.
328   CheckScrollBeginHistograms(7, 1);
329   // At t=10, finger_pos = 10px, rendered_pos = 5px.
330   // At t=20, finger_pos = 20px, rendered_pos = 15px.
331   // At t=30, finger_pos = 25px, rendered_pos = 25px.
332   // AverageLag = ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms
333   //            = 9.375
334   CheckScrollUpdateHistograms(9, 1);
335 }
336 
337 // Test AverageLag with perfect scroll prediction.
TEST_F(AverageLagTrackerTest,ScrollPrediction)338 TEST_F(AverageLagTrackerTest, ScrollPrediction) {
339   // ScrollBegin, at t=5, finger_pos=5px.
340   // Predict frame_time=10, predicted_pos = 10px.
341   base::TimeTicks event_time = MillisecondsToTimeTicks(5);
342   base::TimeTicks frame_time = MillisecondsToTimeTicks(10);
343   SyntheticTouchScrollBegin(event_time, frame_time, 5 /* scroll_delta */,
344                             10 /* predicted_delta */);
345 
346   // ScrollUpdate, at t=15, finger_pos=15px.
347   // Predict frame_time=20, predicted_pos = 20px.
348   event_time = MillisecondsToTimeTicks(15);
349   frame_time = MillisecondsToTimeTicks(20);
350   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */,
351                              10 /* predicted_delta */);
352 
353   // ScrollUpdate, at t=25, finger_pos=25px.
354   // Predict frame_time=30, predicted_pos = 30px.
355   event_time = MillisecondsToTimeTicks(25);
356   frame_time = MillisecondsToTimeTicks(30);
357   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */,
358                              10 /* predicted_delta */);
359 
360   // Another ScrollBegin to flush unfinished frames.
361   event_time = MillisecondsToTimeTicks(1000);
362   frame_time = MillisecondsToTimeTicks(1000);
363   SyntheticTouchScrollBegin(event_time, frame_time, 0);
364 
365   // Prediction hasn't take affect on ScrollBegin so it'll stay the same.
366   CheckScrollBeginHistograms(7, 1);
367   // At t=10, finger_pos = 10px, rendered_pos = 10px.
368   // At t=20, finger_pos = 20px, rendered_pos = 20px.
369   // At t=30, finger_pos = 25px, rendered_pos = 30px.
370   // AverageLag = ((0px+10px)*10ms/2 + (0px+5px)*10ms/2 + 5px*5ms)/20ms
371   //            = 4.375px
372   // AverageLag (w/o prediction)
373   //              ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms
374   //            = 9.375px
375   // Positive effect of prediction = 5px
376   CheckScrollUpdateHistograms(4, 1);
377   CheckPredictionPositiveHistograms(5, 1);
378   CheckPredictionNegativeHistogramsTotalCount(0);
379 }
380 
381 // Test AverageLag with imperfect scroll prediction.
TEST_F(AverageLagTrackerTest,ImperfectScrollPrediction)382 TEST_F(AverageLagTrackerTest, ImperfectScrollPrediction) {
383   // ScrollBegin, at t=5, finger_pos=5px.
384   // Predict frame_time=10, predicted_pos(over) = 12px.
385   base::TimeTicks event_time = MillisecondsToTimeTicks(5);
386   base::TimeTicks frame_time = MillisecondsToTimeTicks(10);
387   SyntheticTouchScrollBegin(event_time, frame_time, 5 /* scroll_delta */,
388                             12 /* predicted_delta */);
389 
390   // ScrollUpdate, at t=15, finger_pos=15px.
391   // Predict frame_time=20, predicted_pos(under) = 17px.
392   event_time = MillisecondsToTimeTicks(15);
393   frame_time = MillisecondsToTimeTicks(20);
394   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */,
395                              5 /* predicted_delta */);
396 
397   // ScrollUpdate, at t=25, finger_pos=25px.
398   // Predict frame_time=30, predicted_pos(over) = 31px.
399   event_time = MillisecondsToTimeTicks(25);
400   frame_time = MillisecondsToTimeTicks(30);
401   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */,
402                              14 /* predicted_delta */);
403 
404   // Another ScrollBegin to flush unfinished frames.
405   event_time = MillisecondsToTimeTicks(1000);
406   frame_time = MillisecondsToTimeTicks(1000);
407   SyntheticTouchScrollBegin(event_time, frame_time, 0);
408 
409   CheckScrollBeginHistograms(7, 1);
410   // AverageLag = ((2px*2ms/2+8px*8ms/2)+ ((3px+8px)*5ms/2+8px*5ms))/20ms
411   //            = 5.075px
412   CheckScrollUpdateHistograms(5, 1);
413   // AverageLag (w/o prediction =
414   //              ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms
415   //            = 9.375px
416   // Positive effect of prediction = 4.3px
417   CheckPredictionPositiveHistograms(4, 1);
418   CheckPredictionNegativeHistogramsTotalCount(0);
419 }
420 
TEST_F(AverageLagTrackerTest,NegativePredictionEffect)421 TEST_F(AverageLagTrackerTest, NegativePredictionEffect) {
422   // ScrollBegin, at t=5, finger_pos=5px.
423   // Predict frame_time=10, predicted_pos(over) = 20px.
424   base::TimeTicks event_time = MillisecondsToTimeTicks(5);
425   base::TimeTicks frame_time = MillisecondsToTimeTicks(10);
426   SyntheticTouchScrollBegin(event_time, frame_time, 5 /* scroll_delta */,
427                             20 /* predicted_delta */);
428 
429   // ScrollUpdate, at t=15, finger_pos=15px.
430   // Predict frame_time=20, predicted_pos(over) = 60px.
431   event_time = MillisecondsToTimeTicks(15);
432   frame_time = MillisecondsToTimeTicks(20);
433   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */,
434                              40 /* predicted_delta */);
435 
436   // ScrollUpdate, at t=25, finger_pos=25px.
437   // Predict frame_time=30, predicted_pos(over) = 60px.
438   event_time = MillisecondsToTimeTicks(25);
439   frame_time = MillisecondsToTimeTicks(30);
440   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */,
441                              0 /* predicted_delta */);
442 
443   // Another ScrollBegin to flush unfinished frames.
444   event_time = MillisecondsToTimeTicks(1000);
445   frame_time = MillisecondsToTimeTicks(1000);
446   SyntheticTouchScrollBegin(event_time, frame_time, 0);
447 
448   CheckScrollBeginHistograms(7, 1);
449   // AverageLag = ((10px+0px)*10ms/2)+ ((40px+35px)*5ms/2+35px*5ms))/20ms
450   //            = 20.625px
451   CheckScrollUpdateHistograms(20, 1);
452   // AverageLag (w/o prediction =
453   //              ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms
454   //            = 9.375px
455   // Negative effect of prediction = 11.25
456   CheckPredictionPositiveHistogramsTotalCount(0);
457   CheckPredictionNegativeHistograms(11, 1);
458 }
459 
TEST_F(AverageLagTrackerTest,NoPredictionEffect)460 TEST_F(AverageLagTrackerTest, NoPredictionEffect) {
461   // ScrollBegin, at t=5, finger_pos=5px.
462   // Predict frame_time=10, predicted_pos(over) = 25px.
463   base::TimeTicks event_time = MillisecondsToTimeTicks(5);
464   base::TimeTicks frame_time = MillisecondsToTimeTicks(10);
465   SyntheticTouchScrollBegin(event_time, frame_time, 5 /* scroll_delta */,
466                             25 /* predicted_delta */);
467 
468   // ScrollUpdate, at t=15, finger_pos=15px.
469   // Predict frame_time=20, predicted_pos(over) = 32px.
470   event_time = MillisecondsToTimeTicks(15);
471   frame_time = MillisecondsToTimeTicks(20);
472   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */,
473                              7 /* predicted_delta */);
474 
475   // ScrollUpdate, at t=25, finger_pos=25px.
476   // Predict frame_time=30, predicted_pos(over) = 37px.
477   event_time = MillisecondsToTimeTicks(25);
478   frame_time = MillisecondsToTimeTicks(30);
479   SyntheticTouchScrollUpdate(event_time, frame_time, 10 /* scroll_delta */,
480                              5 /* predicted_delta */);
481 
482   // Another ScrollBegin to flush unfinished frames.
483   event_time = MillisecondsToTimeTicks(1000);
484   frame_time = MillisecondsToTimeTicks(1000);
485   SyntheticTouchScrollBegin(event_time, frame_time, 0);
486 
487   CheckScrollBeginHistograms(7, 1);
488   // AverageLag = ((15px+5px)*10ms/2 + (12px+7px)*5ms/2 + 7px*5ms)/20ms
489   //            = 9.125px
490   CheckScrollUpdateHistograms(9, 1);
491   // AverageLag (w/o prediction) =
492   //              ((5px+15px)*10ms/2 + (5px+10px)*5ms/2 + 10px*5ms)/20ms
493   //            = 9.375px
494   // Prediction slightly positive, we should see a 0 bucket in
495   // PredictionPositive UMA
496   CheckPredictionPositiveHistograms(0, 1);
497   CheckPredictionNegativeHistogramsTotalCount(0);
498 }
499 
500 // Tests that when an event arrives out-of-order, the average lag tracker
501 // properly ignores it.
TEST_F(AverageLagTrackerTest,EventOutOfOrder)502 TEST_F(AverageLagTrackerTest, EventOutOfOrder) {
503   base::TimeTicks event_time = MillisecondsToTimeTicks(5);
504   base::TimeTicks frame_time = MillisecondsToTimeTicks(10);
505   float scroll_delta = 5.f;
506   SyntheticTouchScrollBegin(event_time, frame_time, scroll_delta);
507 
508   event_time = MillisecondsToTimeTicks(15);
509   frame_time = MillisecondsToTimeTicks(20);
510   SyntheticTouchScrollUpdate(event_time, frame_time, scroll_delta);
511 
512   event_time = MillisecondsToTimeTicks(25);
513   frame_time = MillisecondsToTimeTicks(30);
514   SyntheticTouchScrollUpdate(event_time, frame_time, scroll_delta);
515 
516   // A ScrollBegin to flush unfinished frames.
517   event_time = MillisecondsToTimeTicks(1000);
518   frame_time = MillisecondsToTimeTicks(1000);
519   SyntheticTouchScrollBegin(event_time, frame_time, 0);
520 
521   CheckScrollUpdateHistogramsTotalCount(1);
522 
523   // Send an event whose timestamp is earlier than the most recent event,
524   // representing an event that gets process out of order.
525   base::TimeTicks earlier_event_time = MillisecondsToTimeTicks(15);
526   frame_time = MillisecondsToTimeTicks(1010);
527   SyntheticTouchScrollUpdate(earlier_event_time, frame_time, scroll_delta);
528 
529   // Another ScrollBegin to flush unfinished frames.
530   event_time = MillisecondsToTimeTicks(2000);
531   frame_time = MillisecondsToTimeTicks(2000);
532   SyntheticTouchScrollBegin(event_time, frame_time, 0);
533 
534   // Ensure that the event was ignored.
535   CheckScrollUpdateHistogramsTotalCount(1);
536 }
537 
538 }  // namespace
539 }  // namespace cc
540