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 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 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 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. 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. 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. 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. 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