spiegel-keyman/linux/mcompile/keymap/test/keymap.tests.cpp
Markus Greiner 9cf4e784b2
Some checks are pending
Keyman Build Summary / Summarize build status checks (push) Waiting to run
fixing typo
2026-05-06 18:25:41 +02:00

289 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Keyman is copyright (C) SIL Global. MIT License.
*
* Mnemonic layout support for Linux
*/
#include <gtest/gtest.h>
#include <vector>
#include <gdk/gdk.h>
#include <giomm-2.4/giomm.h>
#include <glibmm-2.4/glibmm.h>
#include <gdk/gdkx.h>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdint>
#include "mcompile.h"
#include "keymap.h"
class TestDataValues {
private:
guint keycode;
KMX_WCHAR expected_char;
std::string layout;
guint shiftstate;
public:
TestDataValues(guint k, KMX_WCHAR e, std::string l, guint s) : keycode(k), expected_char(e), layout(l), shiftstate(s) {
this->keycode = k;
this->expected_char = e;
this->layout = l;
this->shiftstate = s;
}
guint get_keycode() {
return keycode;
}
KMX_WCHAR get_expected_char() {
return expected_char;
}
std::string get_layout() {
return layout;
}
guint get_shiftstate() {
return shiftstate;
}
};
class KeyboardTestParameters {
public:
KeyboardTestParameters(std::vector<KMX_WCHAR> e, std::string l, guint s) : expected_keysyms(e), layout(l), shiftstate(s) {
expected_keysyms = e;
layout = l;
shiftstate = s;
generate_test_data_values();
}
std::vector<TestDataValues> get_test_data() {
return test_data_values;
}
protected:
std::vector<KMX_WCHAR> expected_keysyms;
std::vector<TestDataValues> test_data_values = {};
std::string layout;
guint shiftstate;
std::vector<guint> keycodes = { 38, 56, 54, 40, 26, 41, 42, 43, 31, 44, 45, 46, 58, 57, 32,
33, 24, 27, 39, 28, 30, 55, 25, 53, 29, 52, 19, 10, 11, 12,
13, 14, 15, 16, 17, 18, 65, 49, 20, 21, 34, 35, 51, 47, 48,
59, 60, 61, 123, 94};
void generate_test_data_values() {
EXPECT_EQ(keycodes.size(), expected_keysyms.size()) << "Keycodes and expected keysyms vectors must be of the same size.";
for (guint k = 0; k < keycodes.size() && k < expected_keysyms.size(); k++) {
test_data_values.emplace_back(TestDataValues(keycodes[k], expected_keysyms[k], layout, shiftstate));
}
}
};
class KeyboardConversionTest : public ::testing::TestWithParam<TestDataValues> {
public:
protected:
GdkKeymap* test_keymap;
GdkDisplay* test_display;
gint argc = 0;
char** argv = nullptr;
std::string default_layout;
private:
void initialize_keymap() {
gdk_init(&argc, &argv);
test_display = nullptr;
test_keymap = nullptr;
test_display = gdk_display_get_default();
ASSERT_NE(test_display, nullptr) << "ERROR: can't get display";
test_keymap = gdk_keymap_get_for_display(test_display);
ASSERT_NE(test_keymap, nullptr) << "ERROR: Can't get keymap";
}
void retrieve_default_layout() {
std::vector<std::tuple<Glib::ustring, Glib::ustring>> sources;
Gio::init();
auto settings = Gio::Settings::create("org.gnome.desktop.input-sources");
Glib::VariantBase base;
settings->get_value("sources", base);
using SourcesVariant = Glib::Variant<std::vector<std::tuple<Glib::ustring, Glib::ustring>>>;
auto variant = Glib::VariantBase::cast_dynamic<SourcesVariant>(base);
sources = variant.get();
if (sources.empty()) {
GTEST_SKIP() << "ERROR: No input sources found";
}
const auto& [type, system_layout] = sources[0];
if (type == "xkb") {
if (system_layout == "de" || system_layout == "us") {
default_layout = system_layout;
}
else {
GTEST_SKIP() << "Default layout is not DE or US.";
}
}
else {
GTEST_SKIP() << "Default input source type is not xkb.";
}
}
void SetUp() override {
initialize_keymap();
retrieve_default_layout();
if (!GDK_IS_X11_DISPLAY(test_display)) {
GTEST_SKIP() << "Not running on X11 display, skipping tests that require X11 keymap functionality.";
}
}
void TearDown() override {
default_layout.clear();
argc = 0;
free(argv);
argv = nullptr;
if (test_display) {
gdk_display_close(test_display);
test_display = nullptr;
}
}
};
TEST_P(KeyboardConversionTest, Base) {
guint keycode;
KMX_WCHAR expected_char;
std::string test_layout;
guint shiftstate;
TestDataValues parameter = GetParam();
keycode = parameter.get_keycode();
expected_char = parameter.get_expected_char();
test_layout = parameter.get_layout();
shiftstate = parameter.get_shiftstate();
std::cout << "Testing keycode: " << keycode << " expecting char: " << expected_char << " with layout: " << test_layout << " and shiftstate: " << shiftstate << std::endl;
if (test_layout != default_layout) {
GTEST_SKIP() << "Default layout is not " << default_layout << ".";
}
KMX_WCHAR deadkey;
KMX_WCHAR result = KMX_get_KeyValUnderlying_From_KeyCodeUnderlying(
test_keymap,
keycode,
shiftstate,
&deadkey
);
EXPECT_EQ(result, expected_char) << "Failed for keycode: " << keycode;
}
INSTANTIATE_TEST_SUITE_P(BaseUs,
KeyboardConversionTest,
testing::ValuesIn(KeyboardTestParameters(
{u'a', u'b', u'c', u'd', u'e', u'f', u'g', u'h', u'i',
u'j', u'k', u'l', u'm', u'n', u'o', u'p', u'q', u'r',
u's', u't', u'u', u'v', u'w', u'x', u'y', u'z', u'0',
u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9',
u' ', u'`', u'-', u'=', u'[', u']', u'\\', u';', u'\'',
u',', u'.', u'/', u'\000', u'<'},
"us",
0).get_test_data()));
INSTANTIATE_TEST_SUITE_P(ShiftUs,
KeyboardConversionTest,
testing::ValuesIn(KeyboardTestParameters(
{u'A', u'B', u'C', u'D', u'E', u'F', u'G', u'H', u'I',
u'J', u'K', u'L', u'M', u'N', u'O', u'P', u'Q', u'R',
u'S', u'T', u'U', u'V', u'W', u'X', u'Y', u'Z', u')',
u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'*', u'(',
u' ', u'~', u'_', u'+', u'{', u'}', u'|', u':', u'"',
u'<', u'>', u'?', u'\000', u'>'},
"us",
K_SHIFTFLAG).get_test_data()));
INSTANTIATE_TEST_SUITE_P(AltGrUs,
KeyboardConversionTest,
testing::ValuesIn(KeyboardTestParameters(
{u'a', u'b', u'c', u'd', u'e', u'f', u'g', u'h', u'i', u'j', u'k',
u'l', u'm', u'n', u'o', u'p', u'q', u'r', u's', u't', u'u', u'v',
u'w', u'x', u'y', u'z', u'0', u'1', u'2', u'3', u'4', u'5', u'6',
u'7', u'8', u'9', u'\000', u'`', u'-', u'=', u'[', u']', u'\\',
u';', u'\'', u',', u'.', u'/', u'\000', u'|'},
"us",
(LCTRLFLAG | RALTFLAG)).get_test_data()));
INSTANTIATE_TEST_SUITE_P(ShiftAltGrUs,
KeyboardConversionTest,
testing::ValuesIn(KeyboardTestParameters(
{u'A', u'B', u'C', u'D', u'E', u'F', u'G', u'H', u'I', u'J', u'K',
u'L', u'M', u'N', u'O', u'P', u'Q', u'R', u'S', u'T', u'U', u'V',
u'W', u'X', u'Y', u'Z', u')', u'!', u'@', u'#', u'$', u'%', u'^',
u'&', u'*', u'(', u'\000', u'~', u'_', u'+', u'{', u'}', u'|',
u':', u'"', u'<', u'>', u'?', u'\000', u'¦'},
"us",
(K_SHIFTFLAG | LCTRLFLAG | RALTFLAG)).get_test_data()));
INSTANTIATE_TEST_SUITE_P(BaseDe,
KeyboardConversionTest,
testing::ValuesIn(KeyboardTestParameters(
{u'a', u'b', u'c', u'd', u'e', u'f', u'g', u'h', u'i', u'j',
u'k', u'l', u'm', u'n', u'o', u'p', u'q', u'r', u's', u't',
u'u', u'v', u'w', u'x', u'z', u'y', u'0', u'1', u'2', u'3',
u'4', u'5', u'6', u'7', u'8', u'9', u' ', u'\xffff', u'ß',
u'\xffff', u'ü', u'+', u'#', u'ö', u'ä', u',', u'.', u'-',
u'\000', u'<'},
"de",
0).get_test_data()));
INSTANTIATE_TEST_SUITE_P(ShiftDe,
KeyboardConversionTest,
testing::ValuesIn(KeyboardTestParameters(
{u'A', u'B', u'C', u'D', u'E', u'F', u'G', u'H', u'I',
u'J', u'K', u'L', u'M', u'N', u'O', u'P', u'Q', u'R',
u'S', u'T', u'U', u'V', u'W', u'X', u'Z', u'Y', u'=',
u'!', u'"', u'§', u'$', u'%', u'&', u'/', u'(', u')',
u' ', u'°', u'?', u'\xffff', u'Ü', u'*', u'\'', u'Ö',
u'Ä', u';', u':', u'_', u'\000', u'>'},
"de",
K_SHIFTFLAG).get_test_data()));
INSTANTIATE_TEST_SUITE_P(AltGrDe,
KeyboardConversionTest,
testing::ValuesIn(KeyboardTestParameters(
{u'æ', u'\xfffe', u'¢', u'ð', u'\xfffe', u'\xfffe', u'\xfffe', u'\xfffe',
u'\xfffe', u'\xffff', u'\xfffe', u'\xfffe', u'µ', u'\xfffe', u'ø', u'þ',
u'@', u'', u'\xfffe', u'\xfffe', u'\xfffe', u'\xfffe', u'\xfffe', u'«',
u'\xfffe', u'»', u'}', u'¹', u'²', u'³', u'¼', u'½', u'¬', u'{', u'[',
u']', u'\000', u'\xfffe', u'\\', u'\xffff', u'\xffff', u'~', u'\xfffe',
u'\xffff', u'\xffff', u'·', u'\xfffe', u'\xfffe', u'\000', u'|'},
"de",
(LCTRLFLAG | RALTFLAG)).get_test_data()));
INSTANTIATE_TEST_SUITE_P(ShiftAltGrDe,
KeyboardConversionTest,
testing::ValuesIn(KeyboardTestParameters(
{u'Æ', u'\xfffe', u'©', u'Ð', u'\xfffe', u'ª', u'\xfffe',
u'\xfffe', u'\xfffe', u'\xffff', u'&', u'\xfffe', u'º',
u'\xfffe', u'Ø', u'Þ', u'\xfffe', u'®', u'\xfffe', u'\xfffe',
u'\xfffe', u'\xfffe', u'§', u'\xfffe', u'¥', u'\xfffe', u'°',
u'¡', u'\xfffe', u'£', u'¤', u'\xfffe', u'\xfffe', u'\xfffe',
u'\xfffe', u'±', u'\000', u'\xfffe', u'¿', u'\xffff', u'\xffff',
u'¯', u'\xffff', u'\xffff', u'\xffff', u'×', u'÷', u'\xfffe',
u'\000', u'\xffff'},
"de",
(K_SHIFTFLAG | LCTRLFLAG | RALTFLAG)).get_test_data()));