| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "remoting/protocol/input_event_tracker.h" |
| |
| #include "remoting/proto/event.pb.h" |
| #include "remoting/protocol/protocol_mock_objects.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using ::testing::_; |
| using ::testing::ExpectationSet; |
| using ::testing::InSequence; |
| |
| namespace remoting { |
| namespace protocol { |
| |
| namespace { |
| |
| static const MouseEvent::MouseButton BUTTON_LEFT = MouseEvent::BUTTON_LEFT; |
| static const MouseEvent::MouseButton BUTTON_RIGHT = MouseEvent::BUTTON_RIGHT; |
| |
| // A hardcoded value used to verify |lock_states| is preserved. |
| static const uint32 kTestLockStates = protocol::KeyEvent::LOCK_STATES_CAPSLOCK; |
| |
| // Verify the usb key code and the "pressed" state. |
| // Also verify that the event doesn't have |lock_states| set. |
| MATCHER_P2(EqualsUsbEventWithoutLockStates, usb_keycode, pressed, "") { |
| return arg.usb_keycode() == static_cast<uint32>(usb_keycode) && |
| arg.pressed() == pressed && |
| !arg.has_lock_states(); |
| } |
| |
| // Verify the usb key code, the "pressed" state, and the lock states. |
| MATCHER_P2(EqualsUsbEvent, usb_keycode, pressed, "") { |
| return arg.usb_keycode() == static_cast<uint32>(usb_keycode) && |
| arg.pressed() == pressed && |
| arg.lock_states() == kTestLockStates; |
| } |
| |
| MATCHER_P4(EqualsMouseEvent, x, y, button, down, "") { |
| return arg.x() == x && arg.y() == y && arg.button() == button && |
| arg.button_down() == down; |
| } |
| |
| static KeyEvent NewUsbEvent(uint32 usb_keycode, |
| bool pressed) { |
| KeyEvent event; |
| event.set_usb_keycode(usb_keycode); |
| event.set_pressed(pressed); |
| // Create all key events with the hardcoded |lock_state| in this test. |
| event.set_lock_states(kTestLockStates); |
| return event; |
| } |
| |
| static void PressAndReleaseUsb(InputStub* input_stub, |
| uint32 usb_keycode) { |
| input_stub->InjectKeyEvent(NewUsbEvent(usb_keycode, true)); |
| input_stub->InjectKeyEvent(NewUsbEvent(usb_keycode, false)); |
| } |
| |
| static MouseEvent NewMouseEvent(int x, int y, |
| MouseEvent::MouseButton button, bool down) { |
| MouseEvent event; |
| event.set_x(x); |
| event.set_y(y); |
| event.set_button(button); |
| event.set_button_down(down); |
| return event; |
| } |
| |
| } |
| |
| // Verify that keys that were pressed and released aren't re-released. |
| TEST(InputEventTrackerTest, NothingToRelease) { |
| MockInputStub mock_stub; |
| InputEventTracker input_tracker(&mock_stub); |
| |
| { |
| InSequence s; |
| |
| EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, true))); |
| EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, false))); |
| EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, true))); |
| EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, false))); |
| |
| EXPECT_CALL(mock_stub, |
| InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT, true))); |
| EXPECT_CALL(mock_stub, |
| InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT, false))); |
| } |
| |
| PressAndReleaseUsb(&input_tracker, 1); |
| PressAndReleaseUsb(&input_tracker, 2); |
| |
| input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT, true)); |
| input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT, false)); |
| |
| input_tracker.ReleaseAll(); |
| } |
| |
| // Verify that keys that were left pressed get released. |
| TEST(InputEventTrackerTest, ReleaseAllKeys) { |
| MockInputStub mock_stub; |
| InputEventTracker input_tracker(&mock_stub); |
| ExpectationSet injects; |
| |
| { |
| InSequence s; |
| |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, false))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, false))); |
| |
| injects += EXPECT_CALL(mock_stub, |
| InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_RIGHT, true))); |
| injects += EXPECT_CALL(mock_stub, |
| InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT, true))); |
| injects += EXPECT_CALL(mock_stub, |
| InjectMouseEvent(EqualsMouseEvent(1, 1, BUTTON_LEFT, false))); |
| } |
| |
| // The key should be released but |lock_states| should not be set. |
| EXPECT_CALL(mock_stub, |
| InjectKeyEvent(EqualsUsbEventWithoutLockStates(3, false))) |
| .After(injects); |
| EXPECT_CALL(mock_stub, |
| InjectMouseEvent(EqualsMouseEvent(1, 1, BUTTON_RIGHT, false))) |
| .After(injects); |
| |
| input_tracker.InjectKeyEvent(NewUsbEvent(3, true)); |
| PressAndReleaseUsb(&input_tracker, 1); |
| PressAndReleaseUsb(&input_tracker, 2); |
| |
| input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_RIGHT, true)); |
| input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT, true)); |
| input_tracker.InjectMouseEvent(NewMouseEvent(1, 1, BUTTON_LEFT, false)); |
| |
| EXPECT_FALSE(input_tracker.IsKeyPressed(1)); |
| EXPECT_FALSE(input_tracker.IsKeyPressed(2)); |
| EXPECT_TRUE(input_tracker.IsKeyPressed(3)); |
| EXPECT_EQ(1, input_tracker.PressedKeyCount()); |
| |
| input_tracker.ReleaseAll(); |
| } |
| |
| // Verify that we track both USB-based key events correctly. |
| TEST(InputEventTrackerTest, TrackUsbKeyEvents) { |
| MockInputStub mock_stub; |
| InputEventTracker input_tracker(&mock_stub); |
| ExpectationSet injects; |
| |
| { |
| InSequence s; |
| |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(6, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(7, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(5, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(5, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, false))); |
| } |
| |
| // The key should be auto released with no |lock_states|. |
| EXPECT_CALL(mock_stub, |
| InjectKeyEvent(EqualsUsbEventWithoutLockStates(3, false))) |
| .After(injects); |
| EXPECT_CALL(mock_stub, |
| InjectKeyEvent(EqualsUsbEventWithoutLockStates(6, false))) |
| .After(injects); |
| EXPECT_CALL(mock_stub, |
| InjectKeyEvent(EqualsUsbEventWithoutLockStates(7, false))) |
| .After(injects); |
| EXPECT_CALL(mock_stub, |
| InjectKeyEvent(EqualsUsbEventWithoutLockStates(5, false))) |
| .After(injects); |
| |
| input_tracker.InjectKeyEvent(NewUsbEvent(3, true)); |
| input_tracker.InjectKeyEvent(NewUsbEvent(6, true)); |
| input_tracker.InjectKeyEvent(NewUsbEvent(7, true)); |
| input_tracker.InjectKeyEvent(NewUsbEvent(5, true)); |
| input_tracker.InjectKeyEvent(NewUsbEvent(5, true)); |
| PressAndReleaseUsb(&input_tracker, 2); |
| |
| EXPECT_FALSE(input_tracker.IsKeyPressed(1)); |
| EXPECT_FALSE(input_tracker.IsKeyPressed(2)); |
| EXPECT_TRUE(input_tracker.IsKeyPressed(3)); |
| EXPECT_TRUE(input_tracker.IsKeyPressed(5)); |
| EXPECT_TRUE(input_tracker.IsKeyPressed(6)); |
| EXPECT_TRUE(input_tracker.IsKeyPressed(7)); |
| EXPECT_EQ(4, input_tracker.PressedKeyCount()); |
| |
| input_tracker.ReleaseAll(); |
| } |
| |
| // Verify that invalid events get passed through but not tracked. |
| TEST(InputEventTrackerTest, InvalidEventsNotTracked) { |
| MockInputStub mock_stub; |
| InputEventTracker input_tracker(&mock_stub); |
| ExpectationSet injects; |
| |
| { |
| InSequence s; |
| |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(1, false))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(_)).Times(2); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, true))); |
| injects += EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(2, false))); |
| } |
| |
| EXPECT_CALL(mock_stub, |
| InjectKeyEvent(EqualsUsbEventWithoutLockStates(3, false))) |
| .After(injects); |
| |
| input_tracker.InjectKeyEvent(NewUsbEvent(3, true)); |
| PressAndReleaseUsb(&input_tracker, 1); |
| |
| KeyEvent invalid_event1; |
| invalid_event1.set_pressed(true); |
| input_tracker.InjectKeyEvent(invalid_event1); |
| |
| KeyEvent invalid_event2; |
| invalid_event2.set_usb_keycode(6); |
| input_tracker.InjectKeyEvent(invalid_event2); |
| |
| PressAndReleaseUsb(&input_tracker, 2); |
| |
| EXPECT_FALSE(input_tracker.IsKeyPressed(1)); |
| EXPECT_FALSE(input_tracker.IsKeyPressed(2)); |
| EXPECT_TRUE(input_tracker.IsKeyPressed(3)); |
| EXPECT_EQ(1, input_tracker.PressedKeyCount()); |
| |
| input_tracker.ReleaseAll(); |
| } |
| |
| } // namespace protocol |
| } // namespace remoting |