// 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/client/key_event_mapper.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 { using protocol::InputStub; using protocol::KeyEvent; using protocol::MockInputStub; // A hardcoded value used to verify |lock_states| is preserved. static const uint32 kTestLockStates = protocol::KeyEvent::LOCK_STATES_CAPSLOCK; MATCHER_P2(EqualsUsbEvent, usb_keycode, pressed, "") { return arg.usb_keycode() == static_cast<uint32>(usb_keycode) && arg.pressed() == pressed && // |lock_states| is hardcoded to kTestLockStates in all key events. arg.lock_states() == kTestLockStates; } MATCHER_P2(EqualsUsbEventLockStates, usb_keycode, pressed, "") { return arg.usb_keycode() == static_cast<uint32>(usb_keycode) && arg.pressed() == pressed && arg.lock_states() == kTestLockStates; } static KeyEvent NewUsbEvent(uint32 usb_keycode, bool pressed, uint32 lock_states) { KeyEvent event; event.set_usb_keycode(usb_keycode); event.set_pressed(pressed); event.set_lock_states(lock_states); return event; } static void PressAndReleaseUsb(InputStub* input_stub, uint32 usb_keycode) { input_stub->InjectKeyEvent(NewUsbEvent(usb_keycode, true, kTestLockStates)); input_stub->InjectKeyEvent(NewUsbEvent(usb_keycode, false, kTestLockStates)); } static void InjectTestSequence(InputStub* input_stub) { for (int i = 1; i <= 5; ++i) PressAndReleaseUsb(input_stub, i); } // Verify that keys are passed through the KeyEventMapper by default. TEST(KeyEventMapperTest, NoMappingOrTrapping) { MockInputStub mock_stub; KeyEventMapper event_mapper(&mock_stub); { InSequence s; for (int i = 1; i <= 5; ++i) { EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(i, true))); EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(i, false))); } EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, true))); EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, false))); } InjectTestSequence(&event_mapper); PressAndReleaseUsb(&event_mapper, 3); } // Verify that USB keys are remapped at most once. TEST(KeyEventMapperTest, RemapKeys) { MockInputStub mock_stub; KeyEventMapper event_mapper(&mock_stub); event_mapper.RemapKey(3, 4); event_mapper.RemapKey(4, 3); event_mapper.RemapKey(5, 3); { 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, InjectKeyEvent(EqualsUsbEvent(4, true))); EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(4, false))); EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, true))); EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, false))); EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, true))); EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(3, false))); } InjectTestSequence(&event_mapper); } static void HandleTrappedKey(MockInputStub* stub, const KeyEvent& event) { stub->InjectKeyEvent(event); } // Verify that trapped and mapped USB keys are trapped but not remapped. TEST(KeyEventMapperTest, TrapKeys) { MockInputStub mock_stub; MockInputStub trap_stub; KeyEventMapper event_mapper(&mock_stub); KeyEventMapper::KeyTrapCallback callback = base::Bind(&HandleTrappedKey, base::Unretained(&trap_stub)); event_mapper.SetTrapCallback(callback); event_mapper.TrapKey(4, true); event_mapper.TrapKey(5, true); event_mapper.RemapKey(3, 4); event_mapper.RemapKey(4, 3); event_mapper.RemapKey(5, 3); { 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, InjectKeyEvent(EqualsUsbEvent(4, true))); EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsUsbEvent(4, false))); EXPECT_CALL(trap_stub, InjectKeyEvent(EqualsUsbEvent(4, true))); EXPECT_CALL(trap_stub, InjectKeyEvent(EqualsUsbEvent(4, false))); EXPECT_CALL(trap_stub, InjectKeyEvent(EqualsUsbEvent(5, true))); EXPECT_CALL(trap_stub, InjectKeyEvent(EqualsUsbEvent(5, false))); } InjectTestSequence(&event_mapper); } } // namespace remoting