Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: chrome/browser/page_load_metrics/user_input_tracker_unittest.cc

Issue 2540183003: Add UserInputTracker, which keeps track of recent user input events. (Closed)
Patch Set: address comments Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/page_load_metrics/user_input_tracker.cc ('k') | chrome/test/BUILD.gn » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 "chrome/browser/page_load_metrics/user_input_tracker.h"
6
7 #include "base/time/time.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/WebKit/public/platform/WebInputEvent.h"
10
11 namespace page_load_metrics {
12
13 namespace {
14
15 // UserInputTracker allows events to be at most 2 seconds old. Thus we use
16 // 2100ms to make sure the age is greater than 2 seconds.
17 const int kTooOldMilliseconds = 2100;
18
19 double ToMonotonicallyIncreasingSeconds(base::TimeTicks t) {
20 return (t - base::TimeTicks()).InSecondsF();
21 }
22
23 class FakeInputEvent : public blink::WebInputEvent {
24 public:
25 FakeInputEvent() : WebInputEvent(sizeof(FakeInputEvent)) {
26 timeStampSeconds = ToMonotonicallyIncreasingSeconds(base::TimeTicks::Now());
27 type = blink::WebInputEvent::Char;
28 }
29
30 base::TimeTicks GetTimeStamp() {
31 return UserInputTracker::GetEventTime(*this);
32 }
33
34 base::TimeTicks GetTimeStampRounded() {
35 return UserInputTracker::RoundToRateLimitedOffset(GetTimeStamp());
36 }
37 };
38
39 } // namespace
40
41 class UserInputTrackerTest : public testing::Test {};
42
43 TEST_F(UserInputTrackerTest, Basic) {
44 UserInputTracker tracker;
45 EXPECT_EQ(base::TimeTicks(),
46 tracker.FindMostRecentUserInputEventBefore(base::TimeTicks()));
47 EXPECT_EQ(base::TimeTicks(),
48 tracker.FindMostRecentUserInputEventBefore(base::TimeTicks::Now()));
49 }
50
51 TEST_F(UserInputTrackerTest, SingleEvent) {
52 UserInputTracker tracker;
53 FakeInputEvent e;
54 tracker.OnInputEvent(e);
55
56 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
57 e.GetTimeStampRounded()));
58
59 base::TimeTicks after =
60 e.GetTimeStampRounded() + base::TimeDelta::FromMicroseconds(1);
61
62 EXPECT_EQ(e.GetTimeStampRounded(),
63 tracker.FindMostRecentUserInputEventBefore(after));
64
65 EXPECT_TRUE(tracker.FindAndConsumeInputEventsBefore(e.GetTimeStamp()));
Charlie Harrison 2016/12/06 22:04:55 Won't this flake if e.GetTimeStamp() == e.GetTimeS
Bryan McQuade 2016/12/06 22:15:21 Ah, good catch, yes, I've fixed all of these cases
66
67 EXPECT_EQ(base::TimeTicks(),
68 tracker.FindMostRecentUserInputEventBefore(after));
69 }
70
71 TEST_F(UserInputTrackerTest, MultipleEvents) {
72 FakeInputEvent e1;
73 FakeInputEvent e2;
74
75 // Make sure that the two events are monotonically increasing, and that both
76 // are in the past.
77 e1.timeStampSeconds = ToMonotonicallyIncreasingSeconds(
78 e2.GetTimeStamp() - base::TimeDelta::FromMilliseconds(100));
79
80 base::TimeTicks after =
81 e2.GetTimeStampRounded() + base::TimeDelta::FromMicroseconds(1);
82
83 {
84 UserInputTracker tracker;
85 tracker.OnInputEvent(e1);
86 tracker.OnInputEvent(e2);
87
88 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
89 e1.GetTimeStampRounded()));
90 EXPECT_EQ(
91 e1.GetTimeStampRounded(),
92 tracker.FindMostRecentUserInputEventBefore(e2.GetTimeStampRounded()));
93
94 EXPECT_EQ(e2.GetTimeStampRounded(),
95 tracker.FindMostRecentUserInputEventBefore(after));
96
97 EXPECT_FALSE(
98 tracker.FindAndConsumeInputEventsBefore(e1.GetTimeStampRounded()));
99 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
100 e1.GetTimeStampRounded()));
101 EXPECT_EQ(
102 e1.GetTimeStampRounded(),
103 tracker.FindMostRecentUserInputEventBefore(e2.GetTimeStampRounded()));
104 EXPECT_EQ(e2.GetTimeStampRounded(),
105 tracker.FindMostRecentUserInputEventBefore(after));
106
107 EXPECT_TRUE(tracker.FindAndConsumeInputEventsBefore(e2.GetTimeStamp()));
108 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
109 e1.GetTimeStampRounded()));
110 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
111 e2.GetTimeStampRounded()));
112 EXPECT_EQ(base::TimeTicks(),
113 tracker.FindMostRecentUserInputEventBefore(after));
114 }
115
116 {
117 UserInputTracker tracker;
118 tracker.OnInputEvent(e1);
119 tracker.OnInputEvent(e2);
120 EXPECT_EQ(e2.GetTimeStampRounded(),
121 tracker.FindMostRecentUserInputEventBefore(after));
122 EXPECT_TRUE(tracker.FindAndConsumeInputEventsBefore(e2.GetTimeStamp()));
123 EXPECT_EQ(base::TimeTicks(),
124 tracker.FindMostRecentUserInputEventBefore(after));
125 }
126 }
127
128 TEST_F(UserInputTrackerTest, IgnoreEventsOlderThanConsumed) {
129 FakeInputEvent e1;
130 FakeInputEvent e2;
131
132 // Make sure that the two events are monotonically increasing, and that both
133 // are in the past.
134 e1.timeStampSeconds = ToMonotonicallyIncreasingSeconds(
135 e2.GetTimeStamp() - base::TimeDelta::FromMilliseconds(100));
136
137 base::TimeTicks after =
138 e2.GetTimeStampRounded() + base::TimeDelta::FromMicroseconds(1);
139
140 UserInputTracker tracker;
141 tracker.OnInputEvent(e2);
142
143 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
144 e1.GetTimeStampRounded()));
145 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
146 e2.GetTimeStampRounded()));
147 EXPECT_EQ(e2.GetTimeStampRounded(),
148 tracker.FindMostRecentUserInputEventBefore(after));
149
150 EXPECT_TRUE(tracker.FindAndConsumeInputEventsBefore(e2.GetTimeStamp()));
151 EXPECT_EQ(base::TimeTicks(),
152 tracker.FindMostRecentUserInputEventBefore(after));
153
154 tracker.OnInputEvent(e1);
155 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
156 e1.GetTimeStampRounded()));
157 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
158 e1.GetTimeStampRounded() +
159 base::TimeDelta::FromMicroseconds(1)));
160 }
161
162 TEST_F(UserInputTrackerTest, ExcludeOldEvents) {
163 UserInputTracker tracker;
164 FakeInputEvent e1;
165 FakeInputEvent e2;
166 // make sure e1 is too old to be considered.
167 e1.timeStampSeconds = ToMonotonicallyIncreasingSeconds(
168 e2.GetTimeStamp() -
169 base::TimeDelta::FromMilliseconds(kTooOldMilliseconds));
170
171 tracker.OnInputEvent(e1);
172 tracker.OnInputEvent(e2);
173
174 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
175 e1.GetTimeStampRounded() +
176 base::TimeDelta::FromMilliseconds(1)));
177 EXPECT_EQ(base::TimeTicks(),
178 tracker.FindMostRecentUserInputEventBefore(
179 e2.GetTimeStampRounded() +
180 base::TimeDelta::FromMilliseconds(kTooOldMilliseconds)));
181 EXPECT_EQ(
182 e2.GetTimeStampRounded(),
183 tracker.FindMostRecentUserInputEventBefore(
184 e2.GetTimeStampRounded() + base::TimeDelta::FromMilliseconds(1)));
185
186 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
187 e2.GetTimeStampRounded()));
188 }
189
190 TEST_F(UserInputTrackerTest, RateLimit) {
191 const size_t kTooManyEntries = UserInputTracker::kMaxTrackedEvents * 5;
192
193 UserInputTracker tracker;
194 FakeInputEvent e;
195
196 // UserInputTracker DCHECKs that event timestamps aren't after the current
197 // time, so to be safe, we use a starting timestamp that is twice
198 // kTooManyEntries milliseconds in the past, and then synthesize one event for
199 // each of kTooManyEntries after this start point. This guarantees that all
200 // events are in the past.
201 e.timeStampSeconds = ToMonotonicallyIncreasingSeconds(
202 e.GetTimeStamp() -
203 base::TimeDelta::FromMilliseconds(kTooManyEntries * 2));
204
205 // Insert more than kMaxEntries entries. The rate limiting logic should
206 // prevent more than kMaxEntries entries from actually being inserted. A
207 // DCHECK in OnInputEvent verifies that we don't exceed the expected capacity.
208 for (size_t i = 0; i < kTooManyEntries; ++i) {
209 tracker.OnInputEvent(e);
210 e.timeStampSeconds += base::TimeDelta::FromMilliseconds(1).InSecondsF();
211 }
212
213 // Do a basic sanity check to make sure we can find events in the tracker.
214 EXPECT_NE(base::TimeTicks(),
215 tracker.FindMostRecentUserInputEventBefore(base::TimeTicks::Now()));
216 }
217
218 TEST_F(UserInputTrackerTest, IgnoredEventType) {
219 UserInputTracker tracker;
220 FakeInputEvent e;
221 e.type = blink::WebInputEvent::MouseMove;
222 tracker.OnInputEvent(e);
223 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
224 e.GetTimeStampRounded() +
225 base::TimeDelta::FromMilliseconds(1)));
226 }
227
228 TEST_F(UserInputTrackerTest, IgnoreRepeatEvents) {
229 UserInputTracker tracker;
230 FakeInputEvent e;
231 e.modifiers |= blink::WebInputEvent::IsAutoRepeat;
232 tracker.OnInputEvent(e);
233 EXPECT_EQ(base::TimeTicks(), tracker.FindMostRecentUserInputEventBefore(
234 e.GetTimeStampRounded() +
235 base::TimeDelta::FromMilliseconds(1)));
236 }
237
238 } // namespace page_load_metrics
OLDNEW
« no previous file with comments | « chrome/browser/page_load_metrics/user_input_tracker.cc ('k') | chrome/test/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698