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
|
# files that are used both in tests and the app
|
||||||
set(GUI_COMMON_SOURCE_FILES
|
set(GUI_COMMON_SOURCE_FILES
|
||||||
|
src/Action.cpp
|
||||||
|
src/Hotkey.cpp
|
||||||
src/KeySequence.cpp
|
src/KeySequence.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(GUI_COMMON_HEADER_FILES
|
set(GUI_COMMON_HEADER_FILES
|
||||||
|
src/Action.h
|
||||||
|
src/Hotkey.h
|
||||||
src/KeySequence.h
|
src/KeySequence.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(GUI_SOURCE_FILES
|
set(GUI_SOURCE_FILES
|
||||||
src/AboutDialog.cpp
|
src/AboutDialog.cpp
|
||||||
src/Action.cpp
|
|
||||||
src/ActionDialog.cpp
|
src/ActionDialog.cpp
|
||||||
src/AddClientDialog.cpp
|
src/AddClientDialog.cpp
|
||||||
src/AppConfig.cpp
|
src/AppConfig.cpp
|
||||||
|
@ -27,7 +30,6 @@ set(GUI_SOURCE_FILES
|
||||||
src/DataDownloader.cpp
|
src/DataDownloader.cpp
|
||||||
src/DisplayIsValid.cpp
|
src/DisplayIsValid.cpp
|
||||||
src/Fingerprint.cpp
|
src/Fingerprint.cpp
|
||||||
src/Hotkey.cpp
|
|
||||||
src/HotkeyDialog.cpp
|
src/HotkeyDialog.cpp
|
||||||
src/IpcClient.cpp
|
src/IpcClient.cpp
|
||||||
src/Ipc.cpp
|
src/Ipc.cpp
|
||||||
|
@ -60,7 +62,6 @@ set(GUI_SOURCE_FILES
|
||||||
set(GUI_HEADER_FILES
|
set(GUI_HEADER_FILES
|
||||||
src/AboutDialog.h
|
src/AboutDialog.h
|
||||||
src/ActionDialog.h
|
src/ActionDialog.h
|
||||||
src/Action.h
|
|
||||||
src/AddClientDialog.h
|
src/AddClientDialog.h
|
||||||
src/AppConfig.h
|
src/AppConfig.h
|
||||||
src/BarrierLocale.h
|
src/BarrierLocale.h
|
||||||
|
@ -71,7 +72,6 @@ set(GUI_HEADER_FILES
|
||||||
src/ElevateMode.h
|
src/ElevateMode.h
|
||||||
src/Fingerprint.h
|
src/Fingerprint.h
|
||||||
src/HotkeyDialog.h
|
src/HotkeyDialog.h
|
||||||
src/Hotkey.h
|
|
||||||
src/IpcClient.h
|
src/IpcClient.h
|
||||||
src/Ipc.h
|
src/Ipc.h
|
||||||
src/IpcReader.h
|
src/IpcReader.h
|
||||||
|
@ -164,6 +164,7 @@ endif()
|
||||||
if (BARRIER_BUILD_TESTS)
|
if (BARRIER_BUILD_TESTS)
|
||||||
set(GUI_TEST_SOURCE_FILES
|
set(GUI_TEST_SOURCE_FILES
|
||||||
test/KeySequenceTests.cpp
|
test/KeySequenceTests.cpp
|
||||||
|
test/HotkeyTests.cpp
|
||||||
test/main.cpp
|
test/main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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_Launch1,
|
||||||
Qt::Key_Select,
|
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
|
} // namespace
|
||||||
|
|
||||||
class KeySequenceLoadSaveTestFixture :
|
class KeySequenceLoadSaveTestFixture :
|
||||||
|
@ -118,3 +127,21 @@ INSTANTIATE_TEST_CASE_P(
|
||||||
KeySequenceLoadSaveTestFixture,
|
KeySequenceLoadSaveTestFixture,
|
||||||
::testing::Combine(::testing::ValuesIn(s_key_sequence_test_keys),
|
::testing::Combine(::testing::ValuesIn(s_key_sequence_test_keys),
|
||||||
::testing::Values(QSettings::NativeFormat, QSettings::IniFormat)));
|
::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/QFile>
|
||||||
#include <QtCore/QTemporaryFile>
|
#include <QtCore/QTemporaryFile>
|
||||||
|
|
||||||
|
struct TestKey
|
||||||
|
{
|
||||||
|
int key = 0;
|
||||||
|
int modifier = Qt::NoModifier;
|
||||||
|
|
||||||
|
TestKey(int key, int modifier) : key{key}, modifier{modifier} {}
|
||||||
|
};
|
||||||
|
|
||||||
inline QString getTemporaryFilename()
|
inline QString getTemporaryFilename()
|
||||||
{
|
{
|
||||||
QTemporaryFile temp_file;
|
QTemporaryFile temp_file;
|
||||||
|
|
Loading…
Reference in New Issue