diff --git a/src/unittests/deskflow/CMakeLists.txt b/src/unittests/deskflow/CMakeLists.txt index 9118b1342..f4beb8abe 100644 --- a/src/unittests/deskflow/CMakeLists.txt +++ b/src/unittests/deskflow/CMakeLists.txt @@ -37,6 +37,14 @@ create_test( WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/deskflow" ) +create_test( + NAME KeyStateTests + DEPENDS app + LIBS arch base mt ${extra_libs} + SOURCE KeyStateTests.cpp + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/lib/deskflow" +) + create_test( NAME LanguageManagerTests DEPENDS app diff --git a/src/unittests/deskflow/KeyStateTests.cpp b/src/unittests/deskflow/KeyStateTests.cpp new file mode 100644 index 000000000..21ec6d9a7 --- /dev/null +++ b/src/unittests/deskflow/KeyStateTests.cpp @@ -0,0 +1,151 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. + * SPDX-FileCopyrightText: (C) 2011 Nick Bolton + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#include "KeyStateTests.h" +#include "base/EventQueue.h" +#include "deskflow/KeyMap.h" + +#include "MockEventQueue.h" +#include "MockKeyMap.h" +#include "MockKeyState.h" + +void KeyStateTests::initTestCase() +{ + m_arch.init(); +} + +void KeyStateTests::keyDown() +{ + deskflow::KeyMap keyMap; + EventQueue eventQueue; + MockKeyState keyState(eventQueue, keyMap); + + keyState.onKey(1, true, KeyModifierAlt); + + QVERIFY(keyState.getKeyState(1)); +} + +void KeyStateTests::keyUp() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + QVERIFY(!keyState.getKeyState(1)); +} + +void KeyStateTests::invalidKey() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + + keyState.onKey(0, true, KeyModifierAlt); + + QVERIFY(!keyState.getKeyState(0)); +} + +void KeyStateTests::onKey_aKeyDown_keyStateOne() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + + keyState.onKey(1, true, KeyModifierAlt); + + QVERIFY(keyState.getKeyState(1)); +} + +void KeyStateTests::onKey_aKeyUp_keyStateZero() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + + keyState.onKey(1, false, KeyModifierAlt); + + QVERIFY(!keyState.getKeyState(1)); +} + +void KeyStateTests::onKey_invalidKey_keyStateZero() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + + keyState.onKey(0, true, KeyModifierAlt); + + QVERIFY(!keyState.getKeyState(0)); +} + +void KeyStateTests::updateKeyState_pollDoesNothing_keyNotSet() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + + keyState.updateKeyState(); + + QVERIFY(!keyState.isKeyDown(1)); +} + +void KeyStateTests::updateKeyState_activeModifiers_maskNotSet() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + + keyState.updateKeyState(); + + QCOMPARE(0, keyState.getActiveModifiers()); +} + +void KeyStateTests::fakeKeyRepeat_invalidKey_returnsFalse() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + + QVERIFY(!keyState.fakeKeyRepeat(0, 0, 0, 0, "en")); +} + +void KeyStateTests::fakeKeyUp_buttonNotDown_returnsFalse() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + + QVERIFY(!keyState.fakeKeyUp(0)); +} + +void KeyStateTests::isKeyDown_noKeysDown_returnsFalse() +{ + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, m_keymap); + + QVERIFY(!keyState.isKeyDown(1)); +} + +void KeyStateTests::isKeyDown_keyDown_retrunsTrue() +{ + MockKeyMap keyMap; + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, keyMap); + + deskflow::KeyMap::KeyItem key; + key.m_button = 1; + keyState.fakeKeyDown(1, 0, 1, "en"); + + QVERIFY(keyState.isKeyDown(1)); +} + +void KeyStateTests::updateKeyState_pollInsertsSingleKey_keyIsDown() +{ + MockKeyMap keyMap; + MockEventQueue eventQueue; + MockKeyState keyState(eventQueue, keyMap); + + deskflow::KeyMap::KeyItem key; + key.m_button = 1; + keyState.fakeKeyDown(1, 0, 1, "en"); + + keyState.updateKeyState(); + QVERIFY(keyState.isKeyDown(1)); +} + +QTEST_MAIN(KeyStateTests) diff --git a/src/unittests/deskflow/KeyStateTests.h b/src/unittests/deskflow/KeyStateTests.h new file mode 100644 index 000000000..dc7a9c027 --- /dev/null +++ b/src/unittests/deskflow/KeyStateTests.h @@ -0,0 +1,37 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#include +#include + +#include "arch/Arch.h" +#include "base/Log.h" +#include "deskflow/KeyMap.h" + +class KeyStateTests : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void initTestCase(); + void keyDown(); + void keyUp(); + void invalidKey(); + void onKey_aKeyDown_keyStateOne(); + void onKey_aKeyUp_keyStateZero(); + void onKey_invalidKey_keyStateZero(); + void updateKeyState_pollDoesNothing_keyNotSet(); + void updateKeyState_activeModifiers_maskNotSet(); + void fakeKeyRepeat_invalidKey_returnsFalse(); + void fakeKeyUp_buttonNotDown_returnsFalse(); + void isKeyDown_noKeysDown_returnsFalse(); + void isKeyDown_keyDown_retrunsTrue(); + void updateKeyState_pollInsertsSingleKey_keyIsDown(); + +private: + Arch m_arch; + Log m_log; + deskflow::KeyMap m_keymap; +}; diff --git a/src/unittests/deskflow/MockEventQueue.h b/src/unittests/deskflow/MockEventQueue.h new file mode 100644 index 000000000..f15db02da --- /dev/null +++ b/src/unittests/deskflow/MockEventQueue.h @@ -0,0 +1,84 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. + * SPDX-FileCopyrightText: (C) 2011 Nick Bolton + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#pragma once + +#include "base/IEventQueue.h" + +class MockEventQueue : public IEventQueue +{ +public: + EventQueueTimer *newOneShotTimer(double duration, void *target) override + { + return nullptr; + } + + EventQueueTimer *newTimer(double, void *) override + { + return nullptr; + } + + bool getEvent(Event &, double) override + { + return true; + } + + void loop() override + { + // do nothing + } + + void adoptBuffer(IEventQueueBuffer *) override + { + // do nothing + } + + void removeHandlers(void *) override + { + // do nothing + } + + EventTypes registerType(const char *) + { + return EventTypes::Unknown; + } + + void addHandler(EventTypes, void *, const EventHandler &) override + { + // do nothing + } + + void addEvent(Event &&event) override + { + // do nothing + } + + void removeHandler(EventTypes, void *) override + { + // do nothing + } + + bool dispatchEvent(const Event &) override + { + return true; + } + + void deleteTimer(EventQueueTimer *) override + { + // do nothing + } + + void waitForReady() const override + { + // do nothing + } + + void *getSystemTarget() override + { + return nullptr; + } +}; diff --git a/src/unittests/deskflow/MockKeyMap.h b/src/unittests/deskflow/MockKeyMap.h new file mode 100644 index 000000000..d711957ae --- /dev/null +++ b/src/unittests/deskflow/MockKeyMap.h @@ -0,0 +1,39 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. + * SPDX-FileCopyrightText: (C) 2011 Nick Bolton + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ +#pragma once + +#include "deskflow/KeyMap.h" + +// NOTE: do not mock methods that are not pure virtual. this mock exists only +// to provide an implementation of the KeyMap abstract class. +class MockKeyMap : public deskflow::KeyMap +{ +public: + void swap(KeyMap &) noexcept override + { + } + + void finish() override + { + } + + void foreachKey(ForeachKeyCallback, void *) override + { + } + + void addHalfDuplexModifier(KeyID) override + { + } + + bool isHalfDuplex(KeyID, KeyButton) const override + { + return false; + } +}; + +using KeyID = uint32_t; diff --git a/src/unittests/deskflow/MockKeyState.h b/src/unittests/deskflow/MockKeyState.h new file mode 100644 index 000000000..923cebb05 --- /dev/null +++ b/src/unittests/deskflow/MockKeyState.h @@ -0,0 +1,72 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2025 Chris Rizzitello + * SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd. + * SPDX-FileCopyrightText: (C) 2011 Nick Bolton + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ +#pragma once + +#include "base/IEventQueue.h" +#include "deskflow/KeyState.h" + +// NOTE: do not mock methods that are not pure virtual. this mock exists only +// to provide an implementation of the KeyState abstract class. +class MockKeyState : public KeyState +{ +public: + MockKeyState(const IEventQueue &eventQueue) : KeyState((IEventQueue *)&eventQueue, {"en"}, true) + { + } + + MockKeyState(const IEventQueue &eventQueue, const deskflow::KeyMap &keyMap) + : KeyState((IEventQueue *)&eventQueue, (deskflow::KeyMap &)keyMap, {"en"}, true) + { + } + + int32_t pollActiveGroup() const override + { + return 0; + } + KeyModifierMask pollActiveModifiers() const override + { + return 0; + } + bool fakeCtrlAltDel() override + { + return false; + } + void getKeyMap(deskflow::KeyMap &) override + { + } + void fakeKey(const Keystroke &) override + { + } + bool fakeMediaKey(KeyID) override + { + return false; + } + void pollPressedKeys(KeyButtonSet &pressedKeys) const override + { + pressedKeys.insert(1); + } + void fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton serverID, const std::string &lang) override + { + m_key.m_button = id; + } + + bool isKeyDown(KeyButton id) const override + { + return m_key.m_button == id; + } + + void updateKeyState() override + { + // do Nothing + } + +private: + deskflow::KeyMap::KeyItem m_key; +}; + +using KeyID = uint32_t; diff --git a/src/unittests/legacytests/legacytests/deskflow/KeyStateTests.cpp b/src/unittests/legacytests/legacytests/deskflow/KeyStateTests.cpp index eb1e72379..5f4f2a7cb 100644 --- a/src/unittests/legacytests/legacytests/deskflow/KeyStateTests.cpp +++ b/src/unittests/legacytests/legacytests/deskflow/KeyStateTests.cpp @@ -29,39 +29,6 @@ const deskflow::KeyMap::KeyItem *stubMapKey( deskflow::KeyMap::Keystroke s_stubKeystroke(1, false, false); deskflow::KeyMap::KeyItem s_stubKeyItem; -TEST(CKeyStateTests, onKey_aKeyDown_keyStateOne) -{ - MockKeyMap keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - keyState.onKey(1, true, KeyModifierAlt); - - EXPECT_EQ(1, keyState.getKeyState(1)); -} - -TEST(KeyStateTests, onKey_aKeyUp_keyStateZero) -{ - MockKeyMap keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - keyState.onKey(1, false, KeyModifierAlt); - - EXPECT_EQ(0, keyState.getKeyState(1)); -} - -TEST(KeyStateTests, onKey_invalidKey_keyStateZero) -{ - MockKeyMap keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - keyState.onKey(0, true, KeyModifierAlt); - - EXPECT_EQ(0, keyState.getKeyState(0)); -} - TEST(KeyStateTests, sendKeyEvent_halfDuplexAndRepeat_addEventNotCalled) { NiceMock keyMap; @@ -87,31 +54,6 @@ TEST(KeyStateTests, updateKeyMap_mockKeyMap_keyMapGotMock) keyState.updateKeyMap(); } -TEST(KeyStateTests, updateKeyState_pollInsertsSingleKey_keyIsDown) -{ - NiceMock keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - ON_CALL(keyState, pollPressedKeys(_)).WillByDefault(Invoke(stubPollPressedKeys)); - - keyState.updateKeyState(); - - bool actual = keyState.isKeyDown(1); - ASSERT_TRUE(actual); -} - -TEST(KeyStateTests, updateKeyState_pollDoesNothing_keyNotSet) -{ - NiceMock keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - keyState.updateKeyState(); - - bool actual = keyState.isKeyDown(1); - ASSERT_FALSE(actual); -} - TEST(KeyStateTests, updateKeyState_activeModifiers_maskSet) { NiceMock keyMap; @@ -125,18 +67,6 @@ TEST(KeyStateTests, updateKeyState_activeModifiers_maskSet) ASSERT_EQ(KeyModifierAlt, actual); } -TEST(KeyStateTests, updateKeyState_activeModifiers_maskNotSet) -{ - NiceMock keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - keyState.updateKeyState(); - - KeyModifierMask actual = keyState.getActiveModifiers(); - ASSERT_EQ(0, actual); -} - TEST(KeyStateTests, updateKeyState_activeModifiers_keyMapGotModifers) { MockKeyMap keyMap; @@ -227,17 +157,6 @@ TEST(KeyStateTests, fakeKeyDown_mapReturnsKeystrokes_fakeKeyCalled) keyState.fakeKeyDown(1, 0, 0, "en"); } -TEST(KeyStateTests, fakeKeyRepeat_invalidKey_returnsFalse) -{ - MockKeyMap keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - bool actual = keyState.fakeKeyRepeat(0, 0, 0, 0, "en"); - - ASSERT_FALSE(actual); -} - TEST(KeyStateTests, fakeKeyRepeat_nullKey_returnsFalse) { NiceMock keyMap; @@ -305,17 +224,6 @@ TEST(KeyStateTests, fakeKeyRepeat_validKey_returnsTrue) ASSERT_TRUE(actual); } -TEST(KeyStateTests, fakeKeyUp_buttonNotDown_returnsFalse) -{ - MockKeyMap keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - bool actual = keyState.fakeKeyUp(0); - - ASSERT_FALSE(actual); -} - TEST(KeyStateTests, fakeKeyUp_buttonAlreadyDown_returnsTrue) { NiceMock keyMap; @@ -355,50 +263,6 @@ TEST(KeyStateTests, fakeAllKeysUp_keysWereDown_keysAreUp) ASSERT_FALSE(actual); } -TEST(KeyStateTests, isKeyDown_keyDown_returnsTrue) -{ - NiceMock keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - // press button 1 down. - s_stubKeyItem.m_button = 1; - ON_CALL(keyMap, mapKey(_, _, _, _, _, _, _, _)).WillByDefault(Invoke(stubMapKey)); - keyState.fakeKeyDown(1, 0, 1, "en"); - - // method under test - bool actual = keyState.isKeyDown(1); - - ASSERT_TRUE(actual); -} - -TEST(KeyStateTests, isKeyDown_noKeysDown_returnsFalse) -{ - MockKeyMap keyMap; - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - // method under test - bool actual = keyState.isKeyDown(1); - - ASSERT_FALSE(actual); -} - -TEST(KeyStateTests, updateKeyMap_exercised) -{ - deskflow::KeyMap keyMap; - deskflow::KeyMap::KeyItem keyItem; - keyItem.m_button = 'A'; - keyItem.m_group = 1; - keyItem.m_id = 'A'; - keyMap.addKeyEntry(keyItem); - keyMap.finish(); - MockEventQueue eventQueue; - KeyStateImpl keyState(eventQueue, keyMap); - - keyState.updateKeyMap(&keyMap); -} - void stubPollPressedKeys(IKeyState::KeyButtonSet &pressedKeys) { pressedKeys.insert(1);