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.
4
5 #include "remoting/protocol/input_event_tracker.h"
6
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"
11
12 using ::testing::_;
13 using ::testing::ExpectationSet;
14 using ::testing::InSequence;
15
16 namespace remoting {
17 namespace protocol {
18
19 namespace {
20
21 static const MouseEvent::MouseButton BUTTON_LEFT = MouseEvent::BUTTON_LEFT;
22 static const MouseEvent::MouseButton BUTTON_RIGHT = MouseEvent::BUTTON_RIGHT;
23
24 // A hardcoded value used to verify |lock_states| is preserved.
25 static const uint32 kTestLockStates = protocol::KeyEvent::LOCK_STATES_CAPSLOCK;
26
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();
33 }
34
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;
40 }
41
42 MATCHER_P4(EqualsMouseEvent, x, y, button, down, "") {
43 return arg.x() == x && arg.y() == y && arg.button() == button &&
44 arg.button_down() == down;
45 }
46
NewUsbEvent(uint32 usb_keycode,bool pressed)47 static KeyEvent NewUsbEvent(uint32 usb_keycode,
48 bool pressed) {
49 KeyEvent event;
50 event.set_usb_keycode(usb_keycode);
51 event.set_pressed(pressed);
52 // Create all key events with the hardcoded |lock_state| in this test.
53 event.set_lock_states(kTestLockStates);
54 return event;
55 }
56
PressAndReleaseUsb(InputStub * input_stub,uint32 usb_keycode)57 static void PressAndReleaseUsb(InputStub* input_stub,
58 uint32 usb_keycode) {
59 input_stub->InjectKeyEvent(NewUsbEvent(usb_keycode, true));
60 input_stub->InjectKeyEvent(NewUsbEvent(usb_keycode, false));
61 }
62
NewMouseEvent(int x,int y,MouseEvent::MouseButton button,bool down)63 static MouseEvent NewMouseEvent(int x, int y,
64 MouseEvent::MouseButton button, bool down) {
65 MouseEvent event;
66 event.set_x(x);
67 event.set_y(y);
68 event.set_button(button);
69 event.set_button_down(down);
70 return event;
71 }
72
73 }
74
75 // Verify that keys that were pressed and released aren't re-released.
TEST(InputEventTrackerTest,NothingToRelease)76 TEST(InputEventTrackerTest, NothingToRelease) {
77 MockInputStub mock_stub;
78 InputEventTracker input_tracker(&mock_stub);
79
80 {
81 InSequence s;
82
83 EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, true)));
84 EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, false)));
85 EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, true)));
86 EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, false)));
87
88 EXPECT_CALL(mock_stub,
89 InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT, true)));
90 EXPECT_CALL(mock_stub,
91 InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT, false)));
92 }
93
94 PressAndReleaseUsb(&input_tracker, 1);
95 PressAndReleaseUsb(&input_tracker, 2);
96
97 input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT, true));
98 input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT, false));
99
100 input_tracker.ReleaseAll();
101 }
102
103 // Verify that keys that were left pressed get released.
TEST(InputEventTrackerTest,ReleaseAllKeys)104 TEST(InputEventTrackerTest, ReleaseAllKeys) {
105 MockInputStub mock_stub;
106 InputEventTracker input_tracker(&mock_stub);
107 ExpectationSet injects;
108
109 {
110 InSequence s;
111
112 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, true)));
113 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, true)));
114 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, false)));
115 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, true)));
116 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, false)));
117
118 injects += EXPECT_CALL(mock_stub,
119 InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_RIGHT, true)));
120 injects += EXPECT_CALL(mock_stub,
121 InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT, true)));
122 injects += EXPECT_CALL(mock_stub,
123 InjectMouseEvent(EqualsMouseEvent(1, 1, BUTTON_LEFT, false)));
124 }
125
126 // The key should be released but |lock_states| should not be set.
127 EXPECT_CALL(mock_stub,
128 InjectKeyEvent(EqualsUsbEventWithoutLockStates(3, false)))
129 .After(injects);
130 EXPECT_CALL(mock_stub,
131 InjectMouseEvent(EqualsMouseEvent(1, 1, BUTTON_RIGHT, false)))
132 .After(injects);
133
134 input_tracker.InjectKeyEvent(NewUsbEvent(3, true));
135 PressAndReleaseUsb(&input_tracker, 1);
136 PressAndReleaseUsb(&input_tracker, 2);
137
138 input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_RIGHT, true));
139 input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT, true));
140 input_tracker.InjectMouseEvent(NewMouseEvent(1, 1, BUTTON_LEFT, false));
141
142 EXPECT_FALSE(input_tracker.IsKeyPressed(1));
143 EXPECT_FALSE(input_tracker.IsKeyPressed(2));
144 EXPECT_TRUE(input_tracker.IsKeyPressed(3));
145 EXPECT_EQ(1, input_tracker.PressedKeyCount());
146
147 input_tracker.ReleaseAll();
148 }
149
150 // Verify that we track both USB-based key events correctly.
TEST(InputEventTrackerTest,TrackUsbKeyEvents)151 TEST(InputEventTrackerTest, TrackUsbKeyEvents) {
152 MockInputStub mock_stub;
153 InputEventTracker input_tracker(&mock_stub);
154 ExpectationSet injects;
155
156 {
157 InSequence s;
158
159 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, true)));
160 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(6, true)));
161 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(7, true)));
162 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(5, true)));
163 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(5, true)));
164 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, true)));
165 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, false)));
166 }
167
168 // The key should be auto released with no |lock_states|.
169 EXPECT_CALL(mock_stub,
170 InjectKeyEvent(EqualsUsbEventWithoutLockStates(3, false)))
171 .After(injects);
172 EXPECT_CALL(mock_stub,
173 InjectKeyEvent(EqualsUsbEventWithoutLockStates(6, false)))
174 .After(injects);
175 EXPECT_CALL(mock_stub,
176 InjectKeyEvent(EqualsUsbEventWithoutLockStates(7, false)))
177 .After(injects);
178 EXPECT_CALL(mock_stub,
179 InjectKeyEvent(EqualsUsbEventWithoutLockStates(5, false)))
180 .After(injects);
181
182 input_tracker.InjectKeyEvent(NewUsbEvent(3, true));
183 input_tracker.InjectKeyEvent(NewUsbEvent(6, true));
184 input_tracker.InjectKeyEvent(NewUsbEvent(7, true));
185 input_tracker.InjectKeyEvent(NewUsbEvent(5, true));
186 input_tracker.InjectKeyEvent(NewUsbEvent(5, true));
187 PressAndReleaseUsb(&input_tracker, 2);
188
189 EXPECT_FALSE(input_tracker.IsKeyPressed(1));
190 EXPECT_FALSE(input_tracker.IsKeyPressed(2));
191 EXPECT_TRUE(input_tracker.IsKeyPressed(3));
192 EXPECT_TRUE(input_tracker.IsKeyPressed(5));
193 EXPECT_TRUE(input_tracker.IsKeyPressed(6));
194 EXPECT_TRUE(input_tracker.IsKeyPressed(7));
195 EXPECT_EQ(4, input_tracker.PressedKeyCount());
196
197 input_tracker.ReleaseAll();
198 }
199
200 // Verify that invalid events get passed through but not tracked.
TEST(InputEventTrackerTest,InvalidEventsNotTracked)201 TEST(InputEventTrackerTest, InvalidEventsNotTracked) {
202 MockInputStub mock_stub;
203 InputEventTracker input_tracker(&mock_stub);
204 ExpectationSet injects;
205
206 {
207 InSequence s;
208
209 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, true)));
210 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, true)));
211 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, false)));
212 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(_)).Times(2);
213 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, true)));
214 injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, false)));
215 }
216
217 EXPECT_CALL(mock_stub,
218 InjectKeyEvent(EqualsUsbEventWithoutLockStates(3, false)))
219 .After(injects);
220
221 input_tracker.InjectKeyEvent(NewUsbEvent(3, true));
222 PressAndReleaseUsb(&input_tracker, 1);
223
224 KeyEvent invalid_event1;
225 invalid_event1.set_pressed(true);
226 input_tracker.InjectKeyEvent(invalid_event1);
227
228 KeyEvent invalid_event2;
229 invalid_event2.set_usb_keycode(6);
230 input_tracker.InjectKeyEvent(invalid_event2);
231
232 PressAndReleaseUsb(&input_tracker, 2);
233
234 EXPECT_FALSE(input_tracker.IsKeyPressed(1));
235 EXPECT_FALSE(input_tracker.IsKeyPressed(2));
236 EXPECT_TRUE(input_tracker.IsKeyPressed(3));
237 EXPECT_EQ(1, input_tracker.PressedKeyCount());
238
239 input_tracker.ReleaseAll();
240 }
241
242 } // namespace protocol
243 } // namespace remoting
244