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

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

Issue 19220002: [WIP] BufferedInputRouter (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix client assignment Created 7 years, 3 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/browser_input_event.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/ipc_input_event_payload.h"
14 #include "content/common/input/web_input_event_payload.h"
15 #include "content/common/input_messages.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/base/latency_info.h"
18
19 namespace content {
20 namespace {
21
22 using WebKit::WebGestureEvent;
23 using WebKit::WebInputEvent;
24 using WebKit::WebKeyboardEvent;
25 using WebKit::WebMouseEvent;
26 using WebKit::WebMouseWheelEvent;
27 using WebKit::WebTouchEvent;
28
29 class InputQueueTest : public testing::Test,
30 public InputQueueClient,
31 public BrowserInputEventClient {
32 public:
33 InputQueueTest()
34 : queue_(new InputQueue(this)),
35 routing_id_(0),
36 num_flush_completions_(0),
37 num_flush_requests_(0),
38 num_packet_deliveries_(0),
39 next_input_id_(1) {}
40
41 // InputQueueClient
42 virtual void Deliver(const EventPacket& packet) OVERRIDE {
43 EXPECT_LT(0u, packet.size());
44 ++num_packet_deliveries_;
45 current_packet_id_ = packet.id();
46 current_packet_dispositions_.resize(packet.size(), INPUT_EVENT_UNHANDLED);
47 }
48
49 virtual void DidFinishFlush() OVERRIDE { ++num_flush_completions_; }
50 virtual void SetNeedsFlush() OVERRIDE { ++num_flush_requests_; }
51
52 // BrowserInputEventClient
53 virtual void OnDispatched(const BrowserInputEvent& event,
54 InputEventDisposition disposition) OVERRIDE {
55 acked_dispositions_.push_back(disposition);
56 }
57
58 virtual void OnDispatched(
59 const BrowserInputEvent& event,
60 InputEventDisposition disposition,
61 ScopedVector<BrowserInputEvent>* followup) OVERRIDE {
62 acked_followup_dispositions_.push_back(disposition);
63 if (event_to_inject_)
64 followup->push_back(event_to_inject_.release());
65 }
66
67 int num_flush_requests() const { return num_flush_requests_; }
68 int num_flush_completions() const { return num_flush_completions_; }
69 int num_packet_deliveries() const { return num_packet_deliveries_; }
70
71 protected:
72 scoped_ptr<BrowserInputEvent> CreateIPCInputEvent(IPC::Message* message) {
73 return BrowserInputEvent::Create(
74 NextInputID(),
75 IPCInputEventPayload::Create(make_scoped_ptr(message)),
76 this);
77 }
78
79 scoped_ptr<BrowserInputEvent> CreateWebInputEvent(
80 WebInputEvent::Type web_type) {
81 WebKit::WebMouseEvent mouse;
82 WebKit::WebMouseWheelEvent wheel;
83 WebKit::WebTouchEvent touch;
84 WebKit::WebGestureEvent gesture;
85 WebKit::WebKeyboardEvent keyboard;
86
87 WebKit::WebInputEvent* web_event = NULL;
88 if (WebInputEvent::isMouseEventType(web_type))
89 web_event = &mouse;
90 else if (WebInputEvent::isKeyboardEventType(web_type))
91 web_event = &keyboard;
92 else if (WebInputEvent::isTouchEventType(web_type))
93 web_event = &touch;
94 else if (WebInputEvent::isGestureEventType(web_type))
95 web_event = &gesture;
96 else
97 web_event = &wheel;
98 web_event->type = web_type;
99
100 return BrowserInputEvent::Create(
101 NextInputID(),
102 WebInputEventPayload::Create(*web_event, ui::LatencyInfo(), false),
103 this);
104 }
105
106 void QueueEvent(IPC::Message* message) {
107 queue_->QueueEvent(CreateIPCInputEvent(message));
108 }
109
110 void QueueEvent(WebInputEvent::Type web_type) {
111 queue_->QueueEvent(CreateWebInputEvent(web_type));
112 }
113
114 bool Flush(InputEventDisposition disposition) {
115 StartFlush();
116 return FinishFlush(disposition);
117 }
118
119 void StartFlush() {
120 acked_dispositions_.clear();
121 acked_followup_dispositions_.clear();
122 current_packet_id_ = 0;
123 current_packet_dispositions_.clear();
124 queue_->BeginFlush();
125 }
126
127 bool FinishFlush(InputEventDisposition disposition) {
128 if (!current_packet_id_)
129 return false;
130 current_packet_dispositions_ = InputEventDispositions(
131 current_packet_dispositions_.size(), disposition);
132 return InputQueue::ACK_OK ==
133 queue_->OnEventPacketAck(current_packet_id_,
134 current_packet_dispositions_);
135 }
136
137 int64 NextInputID() { return next_input_id_++; }
138
139 scoped_ptr<InputQueue> queue_;
140
141 int routing_id_;
142 int64 current_packet_id_;
143 InputEventDispositions current_packet_dispositions_;
144
145 InputEventDispositions acked_dispositions_;
146 InputEventDispositions acked_followup_dispositions_;
147 scoped_ptr<BrowserInputEvent> event_to_inject_;
148
149 int num_flush_completions_;
150 int num_flush_requests_;
151 int num_packet_deliveries_;
152 int next_input_id_;
153 };
154
155 TEST_F(InputQueueTest, SetNeedsFlushOnQueueEvent) {
156 EXPECT_EQ(0, num_flush_requests());
157
158 QueueEvent(WebInputEvent::MouseDown);
159 EXPECT_EQ(1, num_flush_requests());
160
161 // Additional queued events should not trigger additional flush requests.
162 QueueEvent(WebInputEvent::MouseUp);
163 EXPECT_EQ(1, num_flush_requests());
164 QueueEvent(WebInputEvent::TouchStart);
165 EXPECT_EQ(1, num_flush_requests());
166 }
167
168 TEST_F(InputQueueTest, NoSetNeedsFlushOnQueueIfFlushing) {
169 QueueEvent(WebInputEvent::GestureScrollBegin);
170 EXPECT_EQ(1, num_flush_requests());
171
172 StartFlush();
173 EXPECT_EQ(1, num_flush_requests());
174 EXPECT_EQ(1, num_packet_deliveries());
175
176 // Events queued after a flush will not trigger an additional flush request.
177 QueueEvent(WebInputEvent::GestureScrollBegin);
178 EXPECT_EQ(1, num_flush_requests());
179 QueueEvent(WebInputEvent::GestureScrollEnd);
180 EXPECT_EQ(1, num_flush_requests());
181 }
182
183 #ifdef NDEBUG // This triggers a DCHECK.
184 TEST_F(InputQueueTest, NoSetNeedsFlushOnInvalidEvent) {
185 queue_->QueueEvent(BrowserInputEvent::Create(
186 0,
187 IPCInputEventPayload::Create(
188 scoped_ptr<IPC::Message>(new InputMsg_Copy(1))),
189 this));
190 EXPECT_EQ(0, num_flush_requests());
191
192 queue_->QueueEvent(
193 BrowserInputEvent::Create(1, scoped_ptr<IPCInputEventPayload>(), this));
194 EXPECT_EQ(0, num_flush_requests());
195 }
196 #endif
197
198 TEST_F(InputQueueTest, SetNeedsFlushAfterDidFinishFlushIfEventsQueued) {
199 QueueEvent(WebInputEvent::GestureScrollBegin);
200 EXPECT_EQ(1, num_flush_requests());
201
202 StartFlush();
203 EXPECT_EQ(1, num_packet_deliveries());
204
205 QueueEvent(WebInputEvent::GestureScrollBegin);
206 EXPECT_EQ(1, num_flush_requests());
207
208 // An additional flush request is sent for the event queued after the flush.
209 ASSERT_TRUE(current_packet_id_);
210 ASSERT_TRUE(FinishFlush(INPUT_EVENT_IMPL_THREAD_CONSUMED));
211 EXPECT_EQ(1, num_flush_completions());
212 EXPECT_EQ(2, num_flush_requests());
213 }
214
215 TEST_F(InputQueueTest, EventPacketSentAfterFlush) {
216 EXPECT_EQ(0, num_packet_deliveries());
217 QueueEvent(WebInputEvent::GestureScrollBegin);
218 EXPECT_EQ(0, num_packet_deliveries());
219 StartFlush();
220 EXPECT_EQ(1, num_packet_deliveries());
221 }
222
223 TEST_F(InputQueueTest, AcksHandledInProperOrder) {
224 QueueEvent(WebInputEvent::GestureScrollBegin);
225 QueueEvent(WebInputEvent::GestureScrollEnd);
226 QueueEvent(WebInputEvent::GestureFlingStart);
227
228 queue_->BeginFlush();
229 ASSERT_EQ(3u, current_packet_dispositions_.size());
230 current_packet_dispositions_[0] = INPUT_EVENT_IMPL_THREAD_CONSUMED;
231 current_packet_dispositions_[1] = INPUT_EVENT_MAIN_THREAD_CONSUMED;
232 current_packet_dispositions_[2] = INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS;
233 queue_->OnEventPacketAck(current_packet_id_, current_packet_dispositions_);
234 EXPECT_EQ(1, num_flush_completions());
235
236 ASSERT_EQ(3u, acked_dispositions_.size());
237 EXPECT_EQ(acked_dispositions_[0], INPUT_EVENT_IMPL_THREAD_CONSUMED);
238 EXPECT_EQ(acked_dispositions_[1], INPUT_EVENT_MAIN_THREAD_CONSUMED);
239 EXPECT_EQ(acked_dispositions_[2], INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS);
240 }
241
242 TEST_F(InputQueueTest, FollowupWhenFollowupEventNotConsumed) {
243 InputEventDisposition unconsumed_dispositions[] = {
244 INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS,
245 INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED,
246 INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS
247 };
248 for (size_t i = 0; i < arraysize(unconsumed_dispositions); ++i) {
249 QueueEvent(WebInputEvent::GestureScrollBegin);
250 QueueEvent(WebInputEvent::TouchStart);
251 QueueEvent(WebInputEvent::TouchMove);
252
253 Flush(unconsumed_dispositions[i]);
254 EXPECT_EQ(1u, acked_dispositions_.size()) << i;
255 EXPECT_EQ(2u, acked_followup_dispositions_.size()) << i;
256 }
257 }
258
259 TEST_F(InputQueueTest, NoFollowupWhenFollowupEventConsumed) {
260 InputEventDisposition consumed_dispositions[] = {
261 INPUT_EVENT_IMPL_THREAD_CONSUMED,
262 INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED,
263 INPUT_EVENT_MAIN_THREAD_CONSUMED
264 };
265 for (size_t i = 0; i < arraysize(consumed_dispositions); ++i) {
266 QueueEvent(WebInputEvent::GestureScrollBegin);
267 QueueEvent(WebInputEvent::TouchStart);
268 QueueEvent(WebInputEvent::TouchMove);
269
270 Flush(consumed_dispositions[i]);
271 EXPECT_EQ(3u, acked_dispositions_.size()) << i;
272 EXPECT_EQ(0u, acked_followup_dispositions_.size()) << i;
273 }
274 }
275
276 TEST_F(InputQueueTest, FlushOnEmptyQueueIgnored) {
277 Flush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
278 EXPECT_EQ(0, num_flush_requests());
279 EXPECT_EQ(0, num_flush_completions());
280
281 QueueEvent(WebInputEvent::GestureScrollBegin);
282 Flush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
283 EXPECT_EQ(1, num_flush_requests());
284 EXPECT_EQ(1, num_flush_completions());
285
286 Flush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
287 EXPECT_EQ(1, num_flush_requests());
288 EXPECT_EQ(1, num_flush_completions());
289 }
290
291 TEST_F(InputQueueTest, FlushContinuesUntilAllEventsProcessed) {
292 QueueEvent(WebInputEvent::GestureScrollBegin);
293 QueueEvent(WebInputEvent::GestureScrollEnd);
294 QueueEvent(WebInputEvent::GestureFlingStart);
295
296 EXPECT_EQ(1, num_flush_requests());
297 Flush(INPUT_EVENT_COULD_NOT_DELIVER);
298 EXPECT_EQ(0, num_flush_completions());
299
300 FinishFlush(INPUT_EVENT_COULD_NOT_DELIVER);
301 EXPECT_EQ(0, num_flush_completions());
302
303 ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED));
304 EXPECT_EQ(1, num_flush_completions());
305 }
306
307 TEST_F(InputQueueTest, InvalidPacketAckIgnored) {
308 // Packet never flushed, any ack should be ignored.
309 InputQueue::AckResult result =
310 queue_->OnEventPacketAck(0, InputEventDispositions());
311 EXPECT_EQ(InputQueue::ACK_UNEXPECTED, result);
312
313 QueueEvent(WebInputEvent::GestureScrollBegin);
314 StartFlush();
315 // Tamper with the sent packet by adding an extra event.
316 current_packet_dispositions_.push_back(INPUT_EVENT_MAIN_THREAD_CONSUMED);
317 bool valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
318 EXPECT_EQ(0, num_flush_completions());
319 EXPECT_FALSE(valid_packet_ack);
320
321 // Fix the packet.
322 current_packet_dispositions_.pop_back();
323 valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
324 EXPECT_EQ(1, num_flush_completions());
325 EXPECT_TRUE(valid_packet_ack);
326
327 // Tamper with the packet by changing the id.
328 QueueEvent(WebInputEvent::GestureScrollBegin);
329 StartFlush();
330 int64 packet_ack_id = -1;
331 std::swap(current_packet_id_, packet_ack_id);
332 valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
333 EXPECT_EQ(1, num_flush_completions());
334 EXPECT_FALSE(valid_packet_ack);
335
336 // Fix the packet.
337 std::swap(current_packet_id_, packet_ack_id);
338 valid_packet_ack = FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED);
339 EXPECT_EQ(2, num_flush_completions());
340 EXPECT_TRUE(valid_packet_ack);
341 }
342
343 TEST_F(InputQueueTest, InjectedEventsAckedBeforeDidFinishFlush) {
344 QueueEvent(WebInputEvent::GestureScrollBegin);
345 QueueEvent(WebInputEvent::TouchMove);
346
347 event_to_inject_ = CreateIPCInputEvent(new InputMsg_Copy(routing_id_));
348 Flush(INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS);
349 EXPECT_EQ(0, num_flush_completions());
350
351 // The injected event should now be in the event packet.
352 EXPECT_EQ(1u, current_packet_dispositions_.size());
353 EXPECT_EQ(1u, acked_followup_dispositions_.size());
354 ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED));
355 EXPECT_EQ(1, num_flush_completions());
356
357 QueueEvent(WebInputEvent::GestureScrollBegin);
358 QueueEvent(WebInputEvent::TouchStart);
359 event_to_inject_ = CreateWebInputEvent(WebInputEvent::TouchMove);
360 Flush(INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS);
361 // |event_to_inject_| is now in the event packet.
362 EXPECT_EQ(1u, acked_followup_dispositions_.size());
363 EXPECT_EQ(1u, current_packet_dispositions_.size());
364
365 event_to_inject_ = CreateWebInputEvent(WebInputEvent::TouchMove);
366 // the next |event_to_inject_| is now in the event packet.
367 ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS));
368
369 EXPECT_EQ(2u, acked_followup_dispositions_.size());
370 EXPECT_EQ(1u, current_packet_dispositions_.size());
371 EXPECT_EQ(1, num_flush_completions());
372
373 ASSERT_TRUE(FinishFlush(INPUT_EVENT_MAIN_THREAD_CONSUMED));
374 EXPECT_EQ(2, num_flush_completions());
375 }
376
377 } // namespace
378 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/input/input_queue_client.h ('k') | content/browser/renderer_host/input/input_router.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698