spiegel-keyman/core/tests/unit/api/action_api.tests.cpp
Marc Durdin d61e5bbb18 refactor(core): clean up unit tests
Consolidate test frameworks and cleanup, including:
* all tests use Google Test
* reorganize folders, esp. kmnkbd -> api
* move all api tests into api folder
* replace references to test_assert or test_color with gtest equivalents
* leverage gtest patterns to remove boilerplate code
* dramatically simplify meson.build files and localize variables
* move shared helper code into helpers/ folder
* make test names unique and add gtest protocol for reporting back to
  teamcity

Fixes:
* CLDR test keyboards had invalid unicodeset escapes (needs to be raised
  upstream also) - was not failing tests because files were not loading
  but returning success

Test-bot: skip
2026-04-28 12:17:44 +02:00

209 lines
8.1 KiB
C++

/*
* Keyman is copyright (C) SIL International. MIT License.
*
* Created by Marc Durdin on 2023-10-23
*
* Keyman Core - tests for actions API family of functions
*/
#include <gtest/gtest.h>
#include <string>
#include "keyman_core.h"
#include "path.hpp"
#include "action.hpp"
#include "../helpers/emscripten_filesystem.h"
#include "../helpers/action_items.hpp"
//-------------------------------------------------------------------------------------
TEST(ActionItemListToActionsObject, TwoBackspacesWithSingleContextCharDeletesOnlyOneChar) {
const km_core_action_item action_items[] = {
km::tests::char_action_item('D'),
km::tests::bksp_action_item(KM_CORE_BT_CHAR, 'D'),
km::tests::bksp_action_item(KM_CORE_BT_CHAR, 'E'),
km::tests::end_action_item()
};
km_core_actions actions;
ASSERT_TRUE(km::core::action_item_list_to_actions_object(action_items, &actions));
EXPECT_EQ(actions.code_points_to_delete, 1);
EXPECT_EQ(std::u32string(actions.output), U"");
ASSERT_TRUE(actions.persist_options != nullptr);
EXPECT_EQ(actions.persist_options[0].key, nullptr);
EXPECT_EQ(actions.persist_options[0].value, nullptr);
EXPECT_EQ(actions.persist_options[0].scope, KM_CORE_OPT_UNKNOWN);
EXPECT_EQ(actions.do_alert, KM_CORE_FALSE);
EXPECT_EQ(actions.emit_keystroke, KM_CORE_FALSE);
EXPECT_EQ(actions.new_caps_lock_state, KM_CORE_CAPS_UNCHANGED);
EXPECT_EQ(actions.deleted_context, nullptr);
km::core::actions_dispose(actions);
}
//-------------------------------------------------------------------------------------
TEST(ActionItemListToActionsObject, InterleavedMarkersAreHandledCorrectly) {
const km_core_action_item action_items[] = {
km::tests::char_action_item('A'),
km::tests::marker_action_item(1),
km::tests::char_action_item('B'),
km::tests::marker_action_item(2),
km::tests::char_action_item('C'),
km::tests::bksp_action_item(KM_CORE_BT_CHAR, 'C'),
km::tests::bksp_action_item(KM_CORE_BT_MARKER, 2),
km::tests::char_action_item('D'),
km::tests::end_action_item()
};
km_core_actions actions;
ASSERT_TRUE(km::core::action_item_list_to_actions_object(action_items, &actions));
EXPECT_EQ(actions.code_points_to_delete, 0);
EXPECT_EQ(std::u32string(actions.output), U"ABD");
ASSERT_TRUE(actions.persist_options != nullptr);
EXPECT_EQ(actions.persist_options[0].key, nullptr);
EXPECT_EQ(actions.persist_options[0].value, nullptr);
EXPECT_EQ(actions.persist_options[0].scope, KM_CORE_OPT_UNKNOWN);
EXPECT_EQ(actions.do_alert, KM_CORE_FALSE);
EXPECT_EQ(actions.emit_keystroke, KM_CORE_FALSE);
EXPECT_EQ(actions.new_caps_lock_state, KM_CORE_CAPS_UNCHANGED);
EXPECT_EQ(actions.deleted_context, nullptr);
km::core::actions_dispose(actions);
}
//-------------------------------------------------------------------------------------
TEST(ActionItemListToActionsObject, AlertGeneratesDoAlert) {
const km_core_action_item action_items[] = {
km::tests::alert_action_item(),
km::tests::end_action_item()
};
km_core_actions actions;
ASSERT_TRUE(km::core::action_item_list_to_actions_object(action_items, &actions));
EXPECT_EQ(actions.code_points_to_delete, 0);
EXPECT_EQ(std::u32string(actions.output), U"");
ASSERT_TRUE(actions.persist_options != nullptr);
EXPECT_EQ(actions.persist_options[0].key, nullptr);
EXPECT_EQ(actions.persist_options[0].value, nullptr);
EXPECT_EQ(actions.persist_options[0].scope, KM_CORE_OPT_UNKNOWN);
EXPECT_EQ(actions.do_alert, KM_CORE_TRUE);
EXPECT_EQ(actions.emit_keystroke, KM_CORE_FALSE);
EXPECT_EQ(actions.new_caps_lock_state, KM_CORE_CAPS_UNCHANGED);
EXPECT_EQ(actions.deleted_context, nullptr);
km::core::actions_dispose(actions);
}
//-------------------------------------------------------------------------------------
TEST(ActionItemListToActionsObject, EmitKeystrokeGeneratesEmitKeystroke) {
const km_core_action_item action_items[] = {
km::tests::emit_keystroke_action_item(),
km::tests::end_action_item()
};
km_core_actions actions;
ASSERT_TRUE(km::core::action_item_list_to_actions_object(action_items, &actions));
EXPECT_EQ(actions.code_points_to_delete, 0);
EXPECT_EQ(std::u32string(actions.output), U"");
ASSERT_TRUE(actions.persist_options != nullptr);
EXPECT_EQ(actions.persist_options[0].key, nullptr);
EXPECT_EQ(actions.persist_options[0].value, nullptr);
EXPECT_EQ(actions.persist_options[0].scope, KM_CORE_OPT_UNKNOWN);
EXPECT_EQ(actions.do_alert, KM_CORE_FALSE);
EXPECT_EQ(actions.emit_keystroke, KM_CORE_TRUE);
EXPECT_EQ(actions.new_caps_lock_state, KM_CORE_CAPS_UNCHANGED);
EXPECT_EQ(actions.deleted_context, nullptr);
km::core::actions_dispose(actions);
}
//-------------------------------------------------------------------------------------
TEST(ActionItemListToActionsObject, InvalidateContextIsIgnored) {
// note, this generates a no-op
const km_core_action_item action_items[] = {
km::tests::invalidate_context_action_item(),
km::tests::end_action_item()
};
km_core_actions actions;
ASSERT_TRUE(km::core::action_item_list_to_actions_object(action_items, &actions));
EXPECT_EQ(actions.code_points_to_delete, 0);
EXPECT_EQ(std::u32string(actions.output), U"");
ASSERT_TRUE(actions.persist_options != nullptr);
EXPECT_EQ(actions.persist_options[0].key, nullptr);
EXPECT_EQ(actions.persist_options[0].value, nullptr);
EXPECT_EQ(actions.persist_options[0].scope, KM_CORE_OPT_UNKNOWN);
EXPECT_EQ(actions.do_alert, KM_CORE_FALSE);
EXPECT_EQ(actions.emit_keystroke, KM_CORE_FALSE);
EXPECT_EQ(actions.new_caps_lock_state, KM_CORE_CAPS_UNCHANGED);
EXPECT_EQ(actions.deleted_context, nullptr);
km::core::actions_dispose(actions);
}
//-------------------------------------------------------------------------------------
TEST(ActionItemListToActionsObject, PersistOptGeneratesPersistOption) {
const km_core_option_item option = {
u"key",
u"value",
KM_CORE_OPT_KEYBOARD
};
const km_core_action_item action_items[] = {
km::tests::persist_opt_action_item(&option),
km::tests::end_action_item()
};
km_core_actions actions;
ASSERT_TRUE(km::core::action_item_list_to_actions_object(action_items, &actions));
EXPECT_EQ(actions.code_points_to_delete, 0);
EXPECT_EQ(std::u32string(actions.output), U"");
ASSERT_TRUE(actions.persist_options != nullptr);
EXPECT_EQ(std::u16string(actions.persist_options[0].key), u"key");
EXPECT_EQ(std::u16string(actions.persist_options[0].value), u"value");
EXPECT_EQ(actions.persist_options[0].scope, KM_CORE_OPT_KEYBOARD);
EXPECT_EQ(actions.do_alert, KM_CORE_FALSE);
EXPECT_EQ(actions.emit_keystroke, KM_CORE_FALSE);
EXPECT_EQ(actions.new_caps_lock_state, KM_CORE_CAPS_UNCHANGED);
EXPECT_EQ(actions.deleted_context, nullptr);
// verify that data is copied
EXPECT_NE(actions.persist_options[0].key, option.key);
EXPECT_NE(actions.persist_options[0].value, option.value);
// verify that we have a KM_CORE_OPTIONS_END term
EXPECT_EQ(actions.persist_options[1].key, nullptr);
EXPECT_EQ(actions.persist_options[1].value, nullptr);
EXPECT_EQ(actions.persist_options[1].scope, KM_CORE_OPT_UNKNOWN);
km::core::actions_dispose(actions);
}
/**
* Note: this is just to print size of structures for cross-platform reference
*/
TEST(ActionItemListToActionsObject, MetaPrintSizeofTest) {
km_core_actions act = {0};
std::cout << "sizeof(km_core_actions): " << sizeof(km_core_actions) << std::endl;
std::cout << "&km_core_actions.code_points_to_delete: " << ((intptr_t)(&act.code_points_to_delete)-(intptr_t)(&act)) << std::endl;
std::cout << "&km_core_actions.output: " << ((intptr_t)(&act.output)-(intptr_t)(&act)) << std::endl;
std::cout << "&km_core_actions.persist_options: " << ((intptr_t)(&act.persist_options)-(intptr_t)(&act)) << std::endl;
std::cout << "&km_core_actions.do_alert: " << ((intptr_t)(&act.do_alert)-(intptr_t)(&act)) << std::endl;
std::cout << "&km_core_actions.emit_keystroke: " << ((intptr_t)(&act.emit_keystroke)-(intptr_t)(&act)) << std::endl;
std::cout << "&km_core_actions.new_caps_lock_state: " << ((intptr_t)(&act.new_caps_lock_state)-(intptr_t)(&act)) << std::endl;
std::cout << "&km_core_actions.deleted_context: " << ((intptr_t)(&act.deleted_context)-(intptr_t)(&act)) << std::endl;
SUCCEED();
}