1 // Copyright (c) 2012 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.
5 #include "remoting/protocol/input_event_tracker.h"
7 #include "remoting/proto/event.pb.h"
8 #include "remoting/protocol/protocol_mock_objects.h"
9 #include "testing/gmock/include/gmock/gmock.h"
10 #include "testing/gtest/include/gtest/gtest.h"
13 using ::testing::ExpectationSet
;
14 using ::testing::InSequence
;
21 static const MouseEvent::MouseButton BUTTON_LEFT
= MouseEvent::BUTTON_LEFT
;
22 static const MouseEvent::MouseButton BUTTON_RIGHT
= MouseEvent::BUTTON_RIGHT
;
24 // A hardcoded value used to verify |lock_states| is preserved.
25 static const uint32 kTestLockStates
= protocol::KeyEvent::LOCK_STATES_CAPSLOCK
;
27 // Verify the usb key code and the "pressed" state.
28 // Also verify that the event doesn't have |lock_states| set.
29 MATCHER_P2(EqualsUsbEventWithoutLockStates
, usb_keycode
, pressed
, "") {
30 return arg
.usb_keycode() == static_cast<uint32
>(usb_keycode
) &&
31 arg
.pressed() == pressed
&&
32 !arg
.has_lock_states();
35 // Verify the usb key code, the "pressed" state, and the lock states.
36 MATCHER_P2(EqualsUsbEvent
, usb_keycode
, pressed
, "") {
37 return arg
.usb_keycode() == static_cast<uint32
>(usb_keycode
) &&
38 arg
.pressed() == pressed
&&
39 arg
.lock_states() == kTestLockStates
;
42 MATCHER_P4(EqualsMouseEvent
, x
, y
, button
, down
, "") {
43 return arg
.x() == x
&& arg
.y() == y
&& arg
.button() == button
&&
44 arg
.button_down() == down
;
47 MATCHER_P2(TouchPointIdsAndTypeEqual
, ids
, type
, "") {
48 if (arg
.event_type() != type
)
51 std::set
<uint32
> touch_ids
;
52 for (const TouchEventPoint
& point
: arg
.touch_points()) {
53 touch_ids
.insert(point
.id());
55 return touch_ids
== ids
;
58 static KeyEvent
NewUsbEvent(uint32 usb_keycode
,
61 event
.set_usb_keycode(usb_keycode
);
62 event
.set_pressed(pressed
);
63 // Create all key events with the hardcoded |lock_state| in this test.
64 event
.set_lock_states(kTestLockStates
);
68 static void PressAndReleaseUsb(InputStub
* input_stub
,
70 input_stub
->InjectKeyEvent(NewUsbEvent(usb_keycode
, true));
71 input_stub
->InjectKeyEvent(NewUsbEvent(usb_keycode
, false));
74 static MouseEvent
NewMouseEvent(int x
, int y
,
75 MouseEvent::MouseButton button
, bool down
) {
79 event
.set_button(button
);
80 event
.set_button_down(down
);
84 void AddTouchPoint(uint32 id
, TouchEvent
* event
) {
85 TouchEventPoint
* p
= event
->add_touch_points();
91 // Verify that keys that were pressed and released aren't re-released.
92 TEST(InputEventTrackerTest
, NothingToRelease
) {
93 MockInputStub mock_stub
;
94 InputEventTracker
input_tracker(&mock_stub
);
99 EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(1, true)));
100 EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(1, false)));
101 EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(2, true)));
102 EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(2, false)));
104 EXPECT_CALL(mock_stub
,
105 InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT
, true)));
106 EXPECT_CALL(mock_stub
,
107 InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT
, false)));
110 PressAndReleaseUsb(&input_tracker
, 1);
111 PressAndReleaseUsb(&input_tracker
, 2);
113 input_tracker
.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT
, true));
114 input_tracker
.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT
, false));
116 input_tracker
.ReleaseAll();
119 // Verify that keys that were left pressed get released.
120 TEST(InputEventTrackerTest
, ReleaseAllKeys
) {
121 MockInputStub mock_stub
;
122 InputEventTracker
input_tracker(&mock_stub
);
123 ExpectationSet injects
;
128 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(3, true)));
129 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(1, true)));
130 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(1, false)));
131 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(2, true)));
132 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(2, false)));
134 injects
+= EXPECT_CALL(mock_stub
,
135 InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_RIGHT
, true)));
136 injects
+= EXPECT_CALL(mock_stub
,
137 InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT
, true)));
138 injects
+= EXPECT_CALL(mock_stub
,
139 InjectMouseEvent(EqualsMouseEvent(1, 1, BUTTON_LEFT
, false)));
142 // The key should be released but |lock_states| should not be set.
143 EXPECT_CALL(mock_stub
,
144 InjectKeyEvent(EqualsUsbEventWithoutLockStates(3, false)))
146 EXPECT_CALL(mock_stub
,
147 InjectMouseEvent(EqualsMouseEvent(1, 1, BUTTON_RIGHT
, false)))
150 input_tracker
.InjectKeyEvent(NewUsbEvent(3, true));
151 PressAndReleaseUsb(&input_tracker
, 1);
152 PressAndReleaseUsb(&input_tracker
, 2);
154 input_tracker
.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_RIGHT
, true));
155 input_tracker
.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT
, true));
156 input_tracker
.InjectMouseEvent(NewMouseEvent(1, 1, BUTTON_LEFT
, false));
158 EXPECT_FALSE(input_tracker
.IsKeyPressed(1));
159 EXPECT_FALSE(input_tracker
.IsKeyPressed(2));
160 EXPECT_TRUE(input_tracker
.IsKeyPressed(3));
161 EXPECT_EQ(1, input_tracker
.PressedKeyCount());
163 input_tracker
.ReleaseAll();
166 // Verify that we track both USB-based key events correctly.
167 TEST(InputEventTrackerTest
, TrackUsbKeyEvents
) {
168 MockInputStub mock_stub
;
169 InputEventTracker
input_tracker(&mock_stub
);
170 ExpectationSet injects
;
175 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(3, true)));
176 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(6, true)));
177 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(7, true)));
178 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(5, true)));
179 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(5, true)));
180 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(2, true)));
181 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(2, false)));
184 // The key should be auto released with no |lock_states|.
185 EXPECT_CALL(mock_stub
,
186 InjectKeyEvent(EqualsUsbEventWithoutLockStates(3, false)))
188 EXPECT_CALL(mock_stub
,
189 InjectKeyEvent(EqualsUsbEventWithoutLockStates(6, false)))
191 EXPECT_CALL(mock_stub
,
192 InjectKeyEvent(EqualsUsbEventWithoutLockStates(7, false)))
194 EXPECT_CALL(mock_stub
,
195 InjectKeyEvent(EqualsUsbEventWithoutLockStates(5, false)))
198 input_tracker
.InjectKeyEvent(NewUsbEvent(3, true));
199 input_tracker
.InjectKeyEvent(NewUsbEvent(6, true));
200 input_tracker
.InjectKeyEvent(NewUsbEvent(7, true));
201 input_tracker
.InjectKeyEvent(NewUsbEvent(5, true));
202 input_tracker
.InjectKeyEvent(NewUsbEvent(5, true));
203 PressAndReleaseUsb(&input_tracker
, 2);
205 EXPECT_FALSE(input_tracker
.IsKeyPressed(1));
206 EXPECT_FALSE(input_tracker
.IsKeyPressed(2));
207 EXPECT_TRUE(input_tracker
.IsKeyPressed(3));
208 EXPECT_TRUE(input_tracker
.IsKeyPressed(5));
209 EXPECT_TRUE(input_tracker
.IsKeyPressed(6));
210 EXPECT_TRUE(input_tracker
.IsKeyPressed(7));
211 EXPECT_EQ(4, input_tracker
.PressedKeyCount());
213 input_tracker
.ReleaseAll();
216 // Verify that invalid events get passed through but not tracked.
217 TEST(InputEventTrackerTest
, InvalidEventsNotTracked
) {
218 MockInputStub mock_stub
;
219 InputEventTracker
input_tracker(&mock_stub
);
220 ExpectationSet injects
;
225 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(3, true)));
226 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(1, true)));
227 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(1, false)));
228 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(_
)).Times(2);
229 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(2, true)));
230 injects
+= EXPECT_CALL(mock_stub
, InjectKeyEvent(EqualsUsbEvent(2, false)));
233 EXPECT_CALL(mock_stub
,
234 InjectKeyEvent(EqualsUsbEventWithoutLockStates(3, false)))
237 input_tracker
.InjectKeyEvent(NewUsbEvent(3, true));
238 PressAndReleaseUsb(&input_tracker
, 1);
240 KeyEvent invalid_event1
;
241 invalid_event1
.set_pressed(true);
242 input_tracker
.InjectKeyEvent(invalid_event1
);
244 KeyEvent invalid_event2
;
245 invalid_event2
.set_usb_keycode(6);
246 input_tracker
.InjectKeyEvent(invalid_event2
);
248 PressAndReleaseUsb(&input_tracker
, 2);
250 EXPECT_FALSE(input_tracker
.IsKeyPressed(1));
251 EXPECT_FALSE(input_tracker
.IsKeyPressed(2));
252 EXPECT_TRUE(input_tracker
.IsKeyPressed(3));
253 EXPECT_EQ(1, input_tracker
.PressedKeyCount());
255 input_tracker
.ReleaseAll();
258 // All touch points added with multiple touch events should be released as a
260 TEST(InputEventTrackerTest
, ReleaseAllTouchPoints
) {
261 MockInputStub mock_stub
;
262 InputEventTracker
input_tracker(&mock_stub
);
264 std::set
<uint32
> expected_ids1
;
265 expected_ids1
.insert(1);
266 expected_ids1
.insert(2);
267 std::set
<uint32
> expected_ids2
;
268 expected_ids2
.insert(3);
269 expected_ids2
.insert(5);
270 expected_ids2
.insert(8);
272 std::set
<uint32
> all_touch_point_ids
;
273 all_touch_point_ids
.insert(expected_ids1
.begin(), expected_ids1
.end());
274 all_touch_point_ids
.insert(expected_ids2
.begin(), expected_ids2
.end());
277 EXPECT_CALL(mock_stub
, InjectTouchEvent(TouchPointIdsAndTypeEqual(
278 expected_ids1
, TouchEvent::TOUCH_POINT_START
)));
279 EXPECT_CALL(mock_stub
, InjectTouchEvent(TouchPointIdsAndTypeEqual(
280 expected_ids2
, TouchEvent::TOUCH_POINT_START
)));
282 EXPECT_CALL(mock_stub
,
283 InjectTouchEvent(TouchPointIdsAndTypeEqual(
284 all_touch_point_ids
, TouchEvent::TOUCH_POINT_CANCEL
)));
286 TouchEvent start_event1
;
287 start_event1
.set_event_type(TouchEvent::TOUCH_POINT_START
);
288 AddTouchPoint(1, &start_event1
);
289 AddTouchPoint(2, &start_event1
);
290 input_tracker
.InjectTouchEvent(start_event1
);
292 TouchEvent start_event2
;
293 start_event2
.set_event_type(TouchEvent::TOUCH_POINT_START
);
294 AddTouchPoint(3, &start_event2
);
295 AddTouchPoint(5, &start_event2
);
296 AddTouchPoint(8, &start_event2
);
297 input_tracker
.InjectTouchEvent(start_event2
);
299 input_tracker
.ReleaseAll();
302 // Add some touch points and remove only a subset of them. ReleaseAll() should
303 // cancel all the remaining touch points.
304 TEST(InputEventTrackerTest
, ReleaseAllRemainingTouchPoints
) {
305 MockInputStub mock_stub
;
306 InputEventTracker
input_tracker(&mock_stub
);
308 std::set
<uint32
> start_expected_ids
;
309 start_expected_ids
.insert(1);
310 start_expected_ids
.insert(2);
311 start_expected_ids
.insert(3);
313 std::set
<uint32
> end_expected_ids
;
314 end_expected_ids
.insert(1);
315 std::set
<uint32
> cancel_expected_ids
;
316 cancel_expected_ids
.insert(3);
318 std::set
<uint32
> all_remaining_touch_point_ids
;
319 all_remaining_touch_point_ids
.insert(2);
322 EXPECT_CALL(mock_stub
,
323 InjectTouchEvent(TouchPointIdsAndTypeEqual(
324 start_expected_ids
, TouchEvent::TOUCH_POINT_START
)));
325 EXPECT_CALL(mock_stub
, InjectTouchEvent(TouchPointIdsAndTypeEqual(
326 end_expected_ids
, TouchEvent::TOUCH_POINT_END
)));
327 EXPECT_CALL(mock_stub
,
328 InjectTouchEvent(TouchPointIdsAndTypeEqual(
329 cancel_expected_ids
, TouchEvent::TOUCH_POINT_CANCEL
)));
331 EXPECT_CALL(mock_stub
, InjectTouchEvent(TouchPointIdsAndTypeEqual(
332 all_remaining_touch_point_ids
,
333 TouchEvent::TOUCH_POINT_CANCEL
)));
335 TouchEvent start_event
;
336 start_event
.set_event_type(TouchEvent::TOUCH_POINT_START
);
337 AddTouchPoint(1, &start_event
);
338 AddTouchPoint(2, &start_event
);
339 AddTouchPoint(3, &start_event
);
340 input_tracker
.InjectTouchEvent(start_event
);
342 TouchEvent end_event
;
343 end_event
.set_event_type(TouchEvent::TOUCH_POINT_END
);
344 AddTouchPoint(1, &end_event
);
345 input_tracker
.InjectTouchEvent(end_event
);
347 TouchEvent cancel_event
;
348 cancel_event
.set_event_type(TouchEvent::TOUCH_POINT_CANCEL
);
349 AddTouchPoint(3, &cancel_event
);
350 input_tracker
.InjectTouchEvent(cancel_event
);
352 input_tracker
.ReleaseAll();
355 } // namespace protocol
356 } // namespace remoting