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

Side by Side Diff: content/browser/renderer_host/input/input_queue_unittest.cc

Issue 20356003: Provided batched input delivery with a BufferedInputRouter (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: BufferedInputRouter unit tests Created 7 years, 4 months 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
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 <vector>
6
7 #include "base/memory/scoped_ptr.h"
8 #include "content/browser/renderer_host/input/event_ack_handler.h"
9 #include "content/browser/renderer_host/input/input_queue.h"
10 #include "content/browser/renderer_host/input/input_queue_client.h"
11 #include "content/common/input/event_packet.h"
12 #include "content/common/input/input_event.h"
13 #include "content/common/input_messages.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/base/latency_info.h"
16
17 namespace content {
18 namespace {
19
20 using WebKit::WebGestureEvent;
21 using WebKit::WebInputEvent;
22 using WebKit::WebKeyboardEvent;
23 using WebKit::WebMouseEvent;
24 using WebKit::WebMouseWheelEvent;
25 using WebKit::WebTouchEvent;
26
27 class InputQueueTest : public testing::Test,
28 public InputQueueClient,
29 public EventAckHandler {
30 public:
31 InputQueueTest()
32 : queue_(new InputQueue(this)),
33 routing_id_(0),
34 num_flush_completions_(0),
35 num_flush_requests_(0),
36 last_input_id_(0) {
37 }
38
39 // InputQueueClient
40 virtual void Deliver(const EventPacket& packet) OVERRIDE {
41 EXPECT_LT(0u, packet.events.size());
42 current_packet_.reset(new EventPacket(packet));
43 }
44
45 virtual void DidFlush() OVERRIDE {
46 ++num_flush_completions_;
47 }
48
49 virtual void SetNeedsFlush() OVERRIDE {
50 ++num_flush_requests_;
51 }
52
53 // EventAckHandler
54 virtual void OnInputEventAck(const InputEvent& acked_event) OVERRIDE {
55 acked_events_.push_back(acked_event);
56 }
57
58 virtual void OnInputEventAck(const InputEvent& acked_event,
59 EventInjector* injector) OVERRIDE {
60 ASSERT_TRUE(injector != NULL);
61 acked_events_with_followup_.push_back(acked_event);
62 if (event_to_inject_)
63 injector->InjectEvent(*event_to_inject_, this);
64 }
65
66 int num_flush_requests() const { return num_flush_requests_; }
67 int num_flush_completions() const { return num_flush_completions_; }
68
69 protected:
70
71 void QueueEvent(WebInputEvent::Type web_type, bool has_followup = false) {
72 scoped_ptr<WebInputEvent> web_event;
73 if (WebInputEvent::isMouseEventType(web_type)) {
74 web_event.reset(new WebMouseEvent());
75 } else if (WebInputEvent::isKeyboardEventType(web_type)) {
76 web_event.reset(new WebKeyboardEvent());
77 } else if (WebInputEvent::isTouchEventType(web_type)) {
78 web_event.reset(new WebTouchEvent());
79 } else if (WebInputEvent::isUserGestureEventType(web_type)) {
80 web_event.reset(new WebGestureEvent());
81 } else {
82 web_event.reset(new WebMouseWheelEvent());
83 }
84 web_event->type = web_type;
85
86 InputEventType type = has_followup ? INPUT_EVENT_NEEDS_ACK_AND_HAS_FOLLOWUP
87 : INPUT_EVENT_NEEDS_ACK;
88
89 QueueEvent(InputMsg_HandleInputEvent(routing_id_,
90 web_event.get(),
91 ui::LatencyInfo(),
92 false), type);
93 }
94
95 void QueueEvent(const IPC::Message& message, InputEventType type) {
96 queue_->QueueEvent(InputEvent(NewInputID(), type, message), this);
97 }
98
99 bool Flush(InputEventState ack_state) {
100 StartFlush();
101 return FinishFlush(ack_state);
102 }
103
104 void StartFlush() {
105 acked_events_.clear();
106 acked_events_with_followup_.clear();
107 current_packet_.reset();
108 queue_->FlushEventsInCurrentFrame();
109 }
110
111 bool FinishFlush(InputEventState ack_state) {
112 if (!current_packet_)
113 return false;
114 for (size_t i = 0; i < current_packet_->events.size(); ++i)
115 current_packet_->events[i].state = ack_state;
116 bool valid_packet = queue_->OnEventPacketAck(*current_packet_);
117 return valid_packet;
118 }
119
120 int64 NewInputID() {
121 return ++last_input_id_;
122 }
123
124 scoped_ptr<InputQueue> queue_;
125
126 int routing_id_;
127 scoped_ptr<EventPacket> current_packet_;
128 std::vector<InputEvent> acked_events_;
129 std::vector<InputEvent> acked_events_with_followup_;
130 scoped_ptr<InputEvent> event_to_inject_;
131
132 int num_flush_completions_;
133 int num_flush_requests_;
134 int last_input_id_;
135 };
136
137 TEST_F(InputQueueTest, SetNeedsFlushOnQueueEvent) {
138 EXPECT_EQ(0, num_flush_requests());
139
140 QueueEvent(WebInputEvent::MouseDown);
141 EXPECT_EQ(1, num_flush_requests());
142
143 // Additional queued events should not trigger additional flush requests.
144 QueueEvent(WebInputEvent::MouseUp);
145 EXPECT_EQ(1, num_flush_requests());
146 QueueEvent(WebInputEvent::TouchStart);
147 EXPECT_EQ(1, num_flush_requests());
148 }
149
150 TEST_F(InputQueueTest, NoSetNeedsFlushOnQueueIfFlushing) {
151 QueueEvent(WebInputEvent::GestureScrollBegin);
152 EXPECT_EQ(1, num_flush_requests());
153
154 queue_->FlushEventsInCurrentFrame();
155 EXPECT_EQ(1, num_flush_requests());
156
157 // Events queued after a flush will not trigger an additional flush request.
158 QueueEvent(WebInputEvent::GestureScrollBegin);
159 EXPECT_EQ(1, num_flush_requests());
160 QueueEvent(WebInputEvent::GestureScrollEnd);
161 EXPECT_EQ(1, num_flush_requests());
162 }
163
164 TEST_F(InputQueueTest, SetNeedsFlushAfterDidFlushIfEventsQueued) {
165 QueueEvent(WebInputEvent::GestureScrollBegin);
166 EXPECT_EQ(1, num_flush_requests());
167
168 StartFlush();
169
170 QueueEvent(WebInputEvent::GestureScrollBegin);
171 EXPECT_EQ(1, num_flush_requests());
172
173 // An additional flush request is sent for the event queued after the flush.
174 EXPECT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_ABSORBED));
175 EXPECT_EQ(1, num_flush_completions());
176 EXPECT_EQ(2, num_flush_requests());
177 }
178
179 TEST_F(InputQueueTest, EventPacketSentAfterFlush) {
180 EXPECT_EQ(NULL, current_packet_.get());
181 QueueEvent(WebInputEvent::GestureScrollBegin);
182 EXPECT_EQ(NULL, current_packet_.get());
183 StartFlush();
184 EXPECT_TRUE(NULL != current_packet_.get());
185 }
186
187 TEST_F(InputQueueTest, AcksHandledInProperOrder) {
188 QueueEvent(WebInputEvent::GestureScrollBegin);
189 QueueEvent(WebInputEvent::GestureScrollEnd);
190 QueueEvent(WebInputEvent::GestureFlingStart);
191
192 queue_->FlushEventsInCurrentFrame();
193 current_packet_->events[0].state = INPUT_EVENT_IMPL_THREAD_ABSORBED;
194 current_packet_->events[1].state = INPUT_EVENT_MAIN_THREAD_ABSORBED;
195 current_packet_->events[2].state = INPUT_EVENT_MAIN_THREAD_NO_HANDLER_EXISTS;
196 queue_->OnEventPacketAck(*current_packet_);
197 EXPECT_EQ(1, num_flush_completions());
198
199 EXPECT_EQ(acked_events_[0].state, INPUT_EVENT_IMPL_THREAD_ABSORBED);
200 EXPECT_EQ(acked_events_[1].state, INPUT_EVENT_MAIN_THREAD_ABSORBED);
201 EXPECT_EQ(acked_events_[2].state, INPUT_EVENT_MAIN_THREAD_NO_HANDLER_EXISTS);
202 }
203
204 TEST_F(InputQueueTest, NullAckHandlerOK) {
205 queue_->QueueEvent(
206 InputEvent(NewInputID(),
207 INPUT_EVENT_ONE_WAY,
208 InputMsg_Copy(routing_id_)),
209 NULL);
210 queue_->QueueEvent(
211 InputEvent(NewInputID(),
212 INPUT_EVENT_NEEDS_ACK,
213 InputMsg_Copy(routing_id_)),
214 NULL);
215
216 Flush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
217 EXPECT_EQ(0u, acked_events_.size());
218 EXPECT_EQ(1, num_flush_completions());
219 }
220
221 TEST_F(InputQueueTest, AckInjectorOnlyIfHasFollowup) {
222 QueueEvent(WebInputEvent::GestureScrollBegin);
223 QueueEvent(WebInputEvent::GestureScrollEnd, true);
224 QueueEvent(WebInputEvent::GestureFlingStart, true);
225
226 Flush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
227 EXPECT_EQ(1u, acked_events_.size());
228 EXPECT_EQ(2u, acked_events_with_followup_.size());
229 }
230
231 TEST_F(InputQueueTest, FlushOnEmptyQueueIgnored) {
232 Flush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
233 EXPECT_EQ(0, num_flush_requests());
234 EXPECT_EQ(0, num_flush_completions());
235
236 QueueEvent(WebInputEvent::GestureScrollBegin);
237 Flush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
238 EXPECT_EQ(1, num_flush_requests());
239 EXPECT_EQ(1, num_flush_completions());
240
241 Flush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
242 EXPECT_EQ(1, num_flush_requests());
243 EXPECT_EQ(1, num_flush_completions());
244 }
245
246 TEST_F(InputQueueTest, FlushContinuesUntilAllEventsProcessed) {
247 QueueEvent(WebInputEvent::GestureScrollBegin);
248 QueueEvent(WebInputEvent::GestureScrollEnd);
249 QueueEvent(WebInputEvent::GestureFlingStart);
250
251 EXPECT_EQ(1, num_flush_requests());
252 Flush(INPUT_EVENT_IMPL_THREAD_COULD_NOT_DELIVER);
253 EXPECT_EQ(0, num_flush_completions());
254
255 FinishFlush(INPUT_EVENT_MAIN_THREAD_COULD_NOT_DELIVER);
256 EXPECT_EQ(0, num_flush_completions());
257
258 ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_ABSORBED));
259 EXPECT_EQ(1, num_flush_completions());
260 }
261
262 TEST_F(InputQueueTest, InvalidPacketAckIgnored) {
263 // Packet never flushed, any ack should be ignored.
264 bool valid_packet_ack = queue_->OnEventPacketAck(EventPacket());
265 EXPECT_FALSE(valid_packet_ack);
266
267 QueueEvent(WebInputEvent::GestureScrollBegin);
268 StartFlush();
269 // Tamper with the sent packet by adding an extra event.
270 current_packet_->events.push_back(
271 InputEvent(NewInputID(),
272 INPUT_EVENT_NEEDS_ACK,
273 InputMsg_Copy(routing_id_)));
274 valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
275 EXPECT_EQ(0, num_flush_completions());
276 EXPECT_FALSE(valid_packet_ack);
277
278 // Fix the packet.
279 current_packet_->events.pop_back();
280 valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
281 EXPECT_EQ(1, num_flush_completions());
282 EXPECT_TRUE(valid_packet_ack);
283
284 // Tamper with the packet by changing an event type.
285 QueueEvent(WebInputEvent::GestureScrollBegin);
286 StartFlush();
287 current_packet_->events[0].type = INPUT_EVENT_ONE_WAY;
288 valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
289 EXPECT_EQ(1, num_flush_completions());
290 EXPECT_FALSE(valid_packet_ack);
291
292 // Fix the packet.
293 current_packet_->events[0].type = INPUT_EVENT_NEEDS_ACK;
294 valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
295 EXPECT_EQ(2, num_flush_completions());
296 EXPECT_TRUE(valid_packet_ack);
297 }
298
299 TEST_F(InputQueueTest, InjectedEventsAckedBeforeDidFlush) {
300 QueueEvent(WebInputEvent::GestureScrollBegin);
301 QueueEvent(WebInputEvent::GestureScrollEnd, true);
302
303 event_to_inject_.reset(
304 new InputEvent(NewInputID(),
305 INPUT_EVENT_ONE_WAY,
306 InputMsg_Copy(routing_id_)));
307 Flush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
308 EXPECT_EQ(0, num_flush_completions());
309
310 // The injected event should now be in the event packet.
311 EXPECT_EQ(1u, current_packet_->events.size());
312 EXPECT_EQ(1u, acked_events_with_followup_.size());
313 ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_ABSORBED));
314 EXPECT_EQ(1, num_flush_completions());
315
316 QueueEvent(WebInputEvent::GestureScrollBegin);
317 QueueEvent(WebInputEvent::GestureScrollEnd, true);
318 event_to_inject_.reset(
319 new InputEvent(NewInputID(),
320 INPUT_EVENT_NEEDS_ACK_AND_HAS_FOLLOWUP,
321 InputMsg_Copy(routing_id_)));
322 Flush(INPUT_EVENT_MAIN_THREAD_ABSORBED);
323 // |event_to_inject_| should now be in the event packet.
324 EXPECT_EQ(1u, acked_events_with_followup_.size());
325 EXPECT_EQ(1u, current_packet_->events.size());
326 ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_ABSORBED));
327
328 // |event_to_inject_| should still be in the event packet.
329 EXPECT_EQ(2u, acked_events_with_followup_.size());
330 EXPECT_EQ(1u, current_packet_->events.size());
331 EXPECT_EQ(1, num_flush_completions());
332 event_to_inject_.reset();
333
334 ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_ABSORBED));
335 EXPECT_EQ(2, num_flush_completions());
336 }
337
338 TEST_F(InputQueueTest, DelayedPacketsBasic) {
339 // Ignore drop requests when there is no outstanding packet.
340 queue_->OnEventPacketAckDelayed();
341 EXPECT_EQ(0, num_flush_requests());
342 EXPECT_EQ(0, num_flush_completions());
343
344 QueueEvent(WebInputEvent::GestureScrollBegin);
345 QueueEvent(WebInputEvent::GestureScrollEnd);
346 QueueEvent(WebInputEvent::GestureFlingStart);
347 EXPECT_EQ(1, num_flush_requests());
348
349 // A delayed packet signal should trigger a DidFlush(), but the queue is still
350 // waiting for the original ack.
351 StartFlush();
352 queue_->OnEventPacketAckDelayed();
353 EXPECT_EQ(1, num_flush_completions());
354 EXPECT_EQ(0U, acked_events_.size());
355
356 // An Event queued after the delay will not trigger a flush request; that will
357 // happen when the delayed packet is finally ack'ed.
358 EXPECT_EQ(1, num_flush_requests());
359 QueueEvent(WebInputEvent::GestureFlingStart);
360 EXPECT_EQ(1, num_flush_requests());
361
362 // Ack'ing the delayed packet should behave normally.
363 EXPECT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_ABSORBED));
364 EXPECT_EQ(2, num_flush_requests());
365 EXPECT_EQ(1, num_flush_completions());
366 EXPECT_EQ(acked_events_[0].state, INPUT_EVENT_MAIN_THREAD_ABSORBED);
367 EXPECT_EQ(acked_events_[1].state, INPUT_EVENT_MAIN_THREAD_ABSORBED);
368 EXPECT_EQ(acked_events_[2].state, INPUT_EVENT_MAIN_THREAD_ABSORBED);
369
370 // Honor the second flush request.
371 EXPECT_TRUE(Flush(INPUT_EVENT_MAIN_THREAD_ABSORBED));
372 EXPECT_EQ(2, num_flush_requests());
373 EXPECT_EQ(2, num_flush_completions());
374 EXPECT_EQ(1U, acked_events_.size());
375 }
376
377 } // namespace
378 } // namespace content
379
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698