mirror of
https://github.com/debauchee/barrier.git
synced 2024-12-23 11:02:21 +03:00
gui/test: Add tests for Hotkey serialization to QSettings
This commit is contained in:
parent
68cfb4e585
commit
fb067d4001
@ -8,16 +8,19 @@ set (CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
# files that are used both in tests and the app
|
||||
set(GUI_COMMON_SOURCE_FILES
|
||||
src/Action.cpp
|
||||
src/Hotkey.cpp
|
||||
src/KeySequence.cpp
|
||||
)
|
||||
|
||||
set(GUI_COMMON_HEADER_FILES
|
||||
src/Action.h
|
||||
src/Hotkey.h
|
||||
src/KeySequence.h
|
||||
)
|
||||
|
||||
set(GUI_SOURCE_FILES
|
||||
src/AboutDialog.cpp
|
||||
src/Action.cpp
|
||||
src/ActionDialog.cpp
|
||||
src/AddClientDialog.cpp
|
||||
src/AppConfig.cpp
|
||||
@ -27,7 +30,6 @@ set(GUI_SOURCE_FILES
|
||||
src/DataDownloader.cpp
|
||||
src/DisplayIsValid.cpp
|
||||
src/Fingerprint.cpp
|
||||
src/Hotkey.cpp
|
||||
src/HotkeyDialog.cpp
|
||||
src/IpcClient.cpp
|
||||
src/Ipc.cpp
|
||||
@ -60,7 +62,6 @@ set(GUI_SOURCE_FILES
|
||||
set(GUI_HEADER_FILES
|
||||
src/AboutDialog.h
|
||||
src/ActionDialog.h
|
||||
src/Action.h
|
||||
src/AddClientDialog.h
|
||||
src/AppConfig.h
|
||||
src/BarrierLocale.h
|
||||
@ -71,7 +72,6 @@ set(GUI_HEADER_FILES
|
||||
src/ElevateMode.h
|
||||
src/Fingerprint.h
|
||||
src/HotkeyDialog.h
|
||||
src/Hotkey.h
|
||||
src/IpcClient.h
|
||||
src/Ipc.h
|
||||
src/IpcReader.h
|
||||
@ -164,6 +164,7 @@ endif()
|
||||
if (BARRIER_BUILD_TESTS)
|
||||
set(GUI_TEST_SOURCE_FILES
|
||||
test/KeySequenceTests.cpp
|
||||
test/HotkeyTests.cpp
|
||||
test/main.cpp
|
||||
)
|
||||
|
||||
|
244
src/gui/test/HotkeyTests.cpp
Normal file
244
src/gui/test/HotkeyTests.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
/* barrier -- mouse and keyboard sharing utility
|
||||
Copyright (C) 2021 Povilas Kanapickas <povilas@radix.lt>
|
||||
|
||||
This package is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
found in the file LICENSE that should have accompanied this file.
|
||||
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "../src/Hotkey.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include "Utils.h"
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
|
||||
struct TestAction
|
||||
{
|
||||
Action::ActionType type = Action::keyDown;
|
||||
std::vector<TestKey> keys;
|
||||
std::vector<std::string> type_screen_names;
|
||||
std::string screen_name;
|
||||
Action::SwitchDirection switch_direction;
|
||||
Action::LockCursorMode lock_cursor_mode;
|
||||
|
||||
static TestAction createKeyAction(Action::ActionType type, const std::vector<TestKey>& keys,
|
||||
const std::vector<std::string>& type_screen_names = {})
|
||||
{
|
||||
TestAction action;
|
||||
action.type = Action::keyDown;
|
||||
action.keys = keys;
|
||||
action.type_screen_names = type_screen_names;
|
||||
return action;
|
||||
}
|
||||
|
||||
static TestAction createKeyDown(const std::vector<TestKey>& keys,
|
||||
const std::vector<std::string>& type_screen_names = {})
|
||||
{
|
||||
return createKeyAction(Action::keyDown, keys, type_screen_names);
|
||||
}
|
||||
|
||||
static TestAction createKeyUp(const std::vector<TestKey>& keys,
|
||||
const std::vector<std::string>& type_screen_names = {})
|
||||
{
|
||||
return createKeyAction(Action::keyUp, keys, type_screen_names);
|
||||
}
|
||||
|
||||
static TestAction createKeyStroke(const std::vector<TestKey>& keys,
|
||||
const std::vector<std::string>& type_screen_names = {})
|
||||
{
|
||||
return createKeyAction(Action::keystroke, keys, type_screen_names);
|
||||
}
|
||||
|
||||
static TestAction createSwitchToScreen(const std::string& screen_name)
|
||||
{
|
||||
TestAction action;
|
||||
action.type = Action::switchToScreen;
|
||||
action.screen_name = screen_name;
|
||||
return action;
|
||||
}
|
||||
|
||||
static TestAction createToggleScreen()
|
||||
{
|
||||
TestAction action;
|
||||
action.type = Action::toggleScreen;
|
||||
return action;
|
||||
}
|
||||
|
||||
static TestAction createSwitchInDirection(Action::SwitchDirection switch_direction)
|
||||
{
|
||||
TestAction action;
|
||||
action.type = Action::switchInDirection;
|
||||
action.switch_direction = switch_direction;
|
||||
return action;
|
||||
}
|
||||
|
||||
static TestAction createLockCursorToScreen(Action::LockCursorMode lock_cursor_mode)
|
||||
{
|
||||
TestAction action;
|
||||
action.type = Action::lockCursorToScreen;
|
||||
action.lock_cursor_mode = lock_cursor_mode;
|
||||
return action;
|
||||
}
|
||||
};
|
||||
|
||||
struct TestHotKey
|
||||
{
|
||||
std::vector<TestKey> keys;
|
||||
std::vector<TestAction> actions;
|
||||
};
|
||||
|
||||
Action createAction(const TestAction& test_action)
|
||||
{
|
||||
Action action;
|
||||
action.setType(test_action.type);
|
||||
|
||||
switch (test_action.type) {
|
||||
case Action::keyDown:
|
||||
case Action::keyUp:
|
||||
case Action::keystroke: {
|
||||
KeySequence sequence;
|
||||
for (auto key : test_action.keys) {
|
||||
sequence.appendKey(key.key, key.modifier);
|
||||
}
|
||||
action.setKeySequence(sequence);
|
||||
for (const auto& type_screen_name : test_action.type_screen_names) {
|
||||
action.appendTypeScreenName(QString::fromStdString(type_screen_name));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Action::switchToScreen:
|
||||
action.setSwitchScreenName(QString::fromStdString(test_action.screen_name));
|
||||
break;
|
||||
case Action::toggleScreen:
|
||||
break;
|
||||
case Action::switchInDirection:
|
||||
action.setSwitchDirection(test_action.switch_direction);
|
||||
break;
|
||||
case Action::lockCursorToScreen:
|
||||
action.setLockCursorMode(test_action.lock_cursor_mode);
|
||||
break;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
void doHotkeyLoadSaveTest(const TestHotKey& test_hotkey, QSettings::Format format)
|
||||
{
|
||||
auto filename = getTemporaryFilename();
|
||||
|
||||
Hotkey hotkey_before, hotkey_after;
|
||||
{
|
||||
QSettings settings(filename, format);
|
||||
|
||||
|
||||
KeySequence sequence;
|
||||
for (auto key : test_hotkey.keys) {
|
||||
sequence.appendKey(key.key, key.modifier);
|
||||
}
|
||||
hotkey_before.setKeySequence(sequence);
|
||||
|
||||
for (auto action : test_hotkey.actions) {
|
||||
hotkey_before.appendAction(createAction(action));
|
||||
}
|
||||
|
||||
settings.beginGroup("test");
|
||||
hotkey_before.saveSettings(settings);
|
||||
settings.endGroup();
|
||||
}
|
||||
{
|
||||
QSettings settings(filename, format);
|
||||
|
||||
settings.beginGroup("test");
|
||||
hotkey_after.loadSettings(settings);
|
||||
settings.endGroup();
|
||||
|
||||
ASSERT_EQ(hotkey_before.keySequence().sequence(), hotkey_after.keySequence().sequence());
|
||||
ASSERT_EQ(hotkey_before.keySequence().modifiers(), hotkey_after.keySequence().modifiers());
|
||||
|
||||
const auto& actions_before = hotkey_before.actions();
|
||||
const auto& actions_after = hotkey_after.actions();
|
||||
|
||||
ASSERT_EQ(actions_before.size(), actions_after.size());
|
||||
for (int i = 0; i < actions_before.size(); ++i) {
|
||||
const auto& action_before = actions_before[i];
|
||||
const auto& action_after = actions_after[i];
|
||||
|
||||
ASSERT_EQ(action_before.keySequence().sequence(), action_after.keySequence().sequence());
|
||||
ASSERT_EQ(action_before.keySequence().modifiers(), action_after.keySequence().modifiers());
|
||||
ASSERT_EQ(action_before.type(), action_after.type());
|
||||
ASSERT_EQ(action_before.typeScreenNames(), action_after.typeScreenNames());
|
||||
ASSERT_EQ(action_before.switchScreenName(), action_after.switchScreenName());
|
||||
ASSERT_EQ(action_before.switchDirection(), action_after.switchDirection());
|
||||
ASSERT_EQ(action_before.lockCursorMode(), action_after.lockCursorMode());
|
||||
ASSERT_EQ(action_before.activeOnRelease(), action_after.activeOnRelease());
|
||||
ASSERT_EQ(action_before.haveScreens(), action_after.haveScreens());
|
||||
}
|
||||
}
|
||||
|
||||
QFile::remove(filename);
|
||||
}
|
||||
|
||||
TEST(HotkeyLoadSaveTests, Empty)
|
||||
{
|
||||
TestHotKey hotkey;
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::NativeFormat);
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::IniFormat);
|
||||
}
|
||||
|
||||
TEST(HotkeyLoadSaveTests, KeysNoActions)
|
||||
{
|
||||
TestHotKey hotkey = {{{Qt::Key_A, Qt::NoModifier}, {Qt::Key_B, Qt::NoModifier}}, {}};
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::NativeFormat);
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::IniFormat);
|
||||
}
|
||||
|
||||
TEST(HotkeyLoadSaveTests, CommaKeyNoActions)
|
||||
{
|
||||
TestHotKey hotkey = {
|
||||
{
|
||||
{Qt::Key_A, Qt::NoModifier},
|
||||
{Qt::Key_Comma, Qt::NoModifier},
|
||||
{Qt::Key_B, Qt::NoModifier}
|
||||
}, {}};
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::NativeFormat);
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::IniFormat);
|
||||
}
|
||||
|
||||
TEST(HotkeyLoadSaveTests, KeysSingleAction)
|
||||
{
|
||||
TestHotKey hotkey = {
|
||||
{
|
||||
{Qt::Key_A, Qt::NoModifier},
|
||||
{Qt::Key_B, Qt::NoModifier}
|
||||
},
|
||||
{
|
||||
TestAction::createKeyDown({{Qt::Key_Z, Qt::NoModifier}})
|
||||
}
|
||||
};
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::NativeFormat);
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::IniFormat);
|
||||
}
|
||||
|
||||
TEST(HotkeyLoadSaveTests, KeysMultipleAction)
|
||||
{
|
||||
TestHotKey hotkey = {
|
||||
{
|
||||
{Qt::Key_A, Qt::NoModifier},
|
||||
{Qt::Key_B, Qt::NoModifier}
|
||||
},
|
||||
{
|
||||
TestAction::createKeyDown({{Qt::Key_Z, Qt::NoModifier}}),
|
||||
TestAction::createSwitchToScreen("test_screen")
|
||||
}
|
||||
};
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::NativeFormat);
|
||||
doHotkeyLoadSaveTest(hotkey, QSettings::IniFormat);
|
||||
}
|
@ -74,6 +74,15 @@ namespace {
|
||||
Qt::Key_Launch1,
|
||||
Qt::Key_Select,
|
||||
};
|
||||
|
||||
std::string keySequenceToString(const std::vector<TestKey>& key_pairs)
|
||||
{
|
||||
KeySequence sequence;
|
||||
for (auto key_pair : key_pairs) {
|
||||
sequence.appendKey(key_pair.key, key_pair.modifier);
|
||||
}
|
||||
return sequence.toString().toStdString();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class KeySequenceLoadSaveTestFixture :
|
||||
@ -118,3 +127,21 @@ INSTANTIATE_TEST_CASE_P(
|
||||
KeySequenceLoadSaveTestFixture,
|
||||
::testing::Combine(::testing::ValuesIn(s_key_sequence_test_keys),
|
||||
::testing::Values(QSettings::NativeFormat, QSettings::IniFormat)));
|
||||
|
||||
TEST(KeySequenceTests, ToString)
|
||||
{
|
||||
ASSERT_EQ(keySequenceToString({{Qt::Key_Menu, Qt::MetaModifier}}),
|
||||
"Meta");
|
||||
ASSERT_EQ(keySequenceToString({{Qt::Key_A, 0}, {Qt::Key_B, 0}}),
|
||||
"a+b");
|
||||
ASSERT_EQ(keySequenceToString({{Qt::Key_A, 0}, {Qt::Key_Comma, 0}, {Qt::Key_B, 0}}),
|
||||
"a+,+b");
|
||||
ASSERT_EQ(keySequenceToString({{Qt::Key_A, 0}, {Qt::Key_Semicolon, 0}, {Qt::Key_B, 0}}),
|
||||
"a+;+b");
|
||||
ASSERT_EQ(keySequenceToString({{Qt::Key_A, 0}, {Qt::Key_Shift, Qt::ShiftModifier},
|
||||
{Qt::Key_0, Qt::ShiftModifier}}),
|
||||
"a+Shift+0");
|
||||
ASSERT_EQ(keySequenceToString({{Qt::Key_A, 0}, {Qt::Key_Control, Qt::ControlModifier},
|
||||
{Qt::Key_0, Qt::ControlModifier}}),
|
||||
"a+Control+0");
|
||||
}
|
||||
|
@ -20,6 +20,14 @@
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QTemporaryFile>
|
||||
|
||||
struct TestKey
|
||||
{
|
||||
int key = 0;
|
||||
int modifier = Qt::NoModifier;
|
||||
|
||||
TestKey(int key, int modifier) : key{key}, modifier{modifier} {}
|
||||
};
|
||||
|
||||
inline QString getTemporaryFilename()
|
||||
{
|
||||
QTemporaryFile temp_file;
|
||||
|
Loading…
Reference in New Issue
Block a user