• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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