mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-19 23:07:42 +00:00
Merge pull request #15923 from keymanapp/chore/core/15913-unit-test-follow-on
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled
chore(core): additional cleanup of unit tests 🎼
This commit is contained in:
commit
b2d4cf98de
13 changed files with 1217 additions and 1387 deletions
|
|
@ -3,6 +3,9 @@
|
|||
*
|
||||
* Keyman Core - Shared test library to load .kmn test rules for automated
|
||||
* testing of .kmn keyboards
|
||||
*
|
||||
* Note that this file is superficially similar to ldml_test_source.cpp, but the
|
||||
* parsing and use diverges far enough that they cannot be easily merged.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
|
|
|||
|
|
@ -15,73 +15,26 @@
|
|||
#include "context.hpp"
|
||||
|
||||
#include "../helpers/core_test_helpers.h"
|
||||
#include "./actions_test_data.h"
|
||||
|
||||
struct TestData {
|
||||
const char* test_name;
|
||||
|
||||
/**
|
||||
* the app context stored in the state, _before_ transform is applied -- NFU
|
||||
*/
|
||||
const km_core_cu *initial_app_context;
|
||||
|
||||
/**
|
||||
* cached context _after_ actions have been applied -- guaranteed NFD
|
||||
* (essentially, this is initial_cached_context -
|
||||
* actions_code_points_to_delete + actions_output) - no markers supported
|
||||
*/
|
||||
const km_core_cu *final_cached_context;
|
||||
|
||||
/**
|
||||
* number of NFD code points that the keyboard processor has asked to remove
|
||||
* in its actions
|
||||
*/
|
||||
int actions_code_points_to_delete;
|
||||
|
||||
/**
|
||||
* NFD string that the keyboard processor has asked to insert in its actions
|
||||
*/
|
||||
const std::u32string actions_output;
|
||||
|
||||
/**
|
||||
* expected: NFU code points to ask app to remove
|
||||
*/
|
||||
const unsigned int expected_delete;
|
||||
|
||||
/**
|
||||
* expected: adjusted NFC output to insert into the app
|
||||
*/
|
||||
const std::u32string expected_output;
|
||||
|
||||
/**
|
||||
* expected: NFU adjusted final app context, which will be NFC from the
|
||||
* boundary of the transform, but will not have been modified prior to that.
|
||||
* Should match char-for-char what the app ends up with in its text buffer.
|
||||
*/
|
||||
const km_core_cu *expected_final_app_context;
|
||||
|
||||
/**
|
||||
* expected: the characters deleted from the context
|
||||
*/
|
||||
const std::u32string expected_deleted_context;
|
||||
};
|
||||
|
||||
std::string GenerateTestName(const testing::TestParamInfo<TestData>& info) {
|
||||
return info.param.test_name;
|
||||
}
|
||||
|
||||
class GetActionApiTest : public testing::TestWithParam<TestData> {
|
||||
class GetActionApiTest : public testing::TestWithParam<ActionsTestData> {
|
||||
protected:
|
||||
km_core_keyboard * test_kb = nullptr;
|
||||
km_core_state * test_state = nullptr;
|
||||
km_core_actions * test_actions = nullptr;
|
||||
|
||||
void Initialize(TestData const& data) {
|
||||
void Initialize(ActionsTestData const& data) {
|
||||
if(data.final_cached_context_string == nullptr) {
|
||||
// We skip the shared tests that don't have a input context string
|
||||
return;
|
||||
}
|
||||
|
||||
km::core::path path = km::core::path::join(test_dir, "..", "ldml", "fixtures", "keyboards", "17.0", "k_001_tiny.kmx");
|
||||
auto blob = km::tests::load_kmx_file(path.native().c_str());
|
||||
ASSERT_STATUS_OK(km_core_keyboard_load_from_blob(path.stem().c_str(), blob.data(), blob.size(), &test_kb));
|
||||
ASSERT_STATUS_OK(km_core_state_create(test_kb, test_empty_env_opts, &test_state));
|
||||
|
||||
ASSERT_STATUS_OK(set_context_from_string(km_core_state_context(test_state), data.final_cached_context));
|
||||
ASSERT_STATUS_OK(set_context_from_string(km_core_state_context(test_state), data.final_cached_context_string));
|
||||
ASSERT_STATUS_OK(set_context_from_string(km_core_state_app_context(test_state), data.initial_app_context));
|
||||
|
||||
test_actions = new km_core_actions;
|
||||
|
|
@ -115,6 +68,7 @@ protected:
|
|||
}
|
||||
if(test_actions) {
|
||||
delete [] test_actions->output;
|
||||
delete [] test_actions->persist_options;
|
||||
delete test_actions;
|
||||
test_actions = nullptr;
|
||||
}
|
||||
|
|
@ -132,6 +86,11 @@ TEST_P(GetActionApiTest, TestActionsApi) {
|
|||
auto data = GetParam();
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize(data));
|
||||
|
||||
if(data.final_cached_context_string == nullptr) {
|
||||
GTEST_SKIP() << "Skip the shared tests that don't have a input context string";
|
||||
return;
|
||||
}
|
||||
|
||||
auto actual_actions = km_core_state_get_actions(test_state);
|
||||
|
||||
std::cout << " (" << data.test_name << "): delete: " << data.expected_delete << " output: |" << std::u32string(actual_actions->output) << "|" << std::endl;
|
||||
|
|
@ -160,184 +119,6 @@ TEST_P(GetActionApiTest, TestActionsApi) {
|
|||
delete [] actual_final_app_context;
|
||||
}
|
||||
|
||||
const TestData values[] = {
|
||||
// Null boundary tests
|
||||
// Note that .final_cached_context_items is not used in these tests
|
||||
|
||||
{
|
||||
"Noop",
|
||||
/* app context pre transform: */ u"",
|
||||
/* cached context post transform: */ u"",
|
||||
/* action del, output: */ 0, U"",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"",
|
||||
/* app_context: */ u"",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"NoOutput",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abc",
|
||||
/* action del, output: */ 0, U"",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"",
|
||||
/* app_context: */ u"abc",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"NoContext",
|
||||
/* app context pre transform: */ u"",
|
||||
/* cached context post transform: */ u"def",
|
||||
/* action del, output: */ 0, U"def",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"def",
|
||||
/* app_context: */ u"def",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
// Simple tests -- no deletions involved
|
||||
|
||||
{
|
||||
"NoNormalization",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcdef",
|
||||
/* action del, output: */ 0, U"def",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"def",
|
||||
/* app_context: */ u"abcdef",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"OutputToNfcBasic",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcde\u0300f",
|
||||
/* action del, output: */ 0, U"de\u0300f",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"dèf",
|
||||
/* app_context: */ u"abcdèf",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"OutputToNfcHefty",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcA\u0300" u"e\u0316\u0301" u"\u0073\u0323\u0307" u"\u0041\u030a" u"\U000114B9\U000114B0",
|
||||
/* action del, output: */ 0, U"A\u0300" U"e\u0316\u0301" U"\u0073\u0323\u0307" U"\u0041\u030a" U"\U000114B9\U000114B0",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"À" U"é̖" U"\u1e69" U"\u00c5" U"\U000114BC",
|
||||
/* app_context: */ u"abcÀé̖\u1e69\u00c5\U000114BC",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
// Interaction with input context when not on normalization boundary
|
||||
|
||||
{
|
||||
"BacktrackOneCharacterToCombineAsNfc",
|
||||
/* app context pre transform: */ u"XYZA",
|
||||
/* cached context post transform: */ u"XYZA\u0300abc",
|
||||
/* action del, output: */ 0, U"\u0300abc",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"Àabc",
|
||||
/* app_context: */ u"XYZÀabc",
|
||||
/* expected del */ U"A"
|
||||
},
|
||||
|
||||
{
|
||||
"BacktrackECombCirc2CharsToCombineAsNfc",
|
||||
/* app context pre transform: */ u"abce\u0302",
|
||||
/* cached context post transform: */ u"abce\u0323\u0302",
|
||||
/* action del, output: */ 1, U"\u0323\u0302",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 2, U"ệ",
|
||||
/* app_context: */ u"abcệ",
|
||||
/* expected del */ U"e\u0302"
|
||||
},
|
||||
|
||||
{
|
||||
"OneBackspaceForNfdConvertsIntoOneCharInNfcAndRecombine",
|
||||
/* app context pre transform: */ u"abcê",
|
||||
/* cached context post transform: */ u"abce\u0323\u0302",
|
||||
/* action del, output: */ 1, U"\u0323\u0302", // NFD input; delete 1: \u0302
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"ệ", // NFC output; delete 1: ê
|
||||
/* app_context: */ u"abcệ",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// a\u0300 should not be normalized because it is not otherwise impacted by
|
||||
// the action.
|
||||
{
|
||||
"AvoidEditingTooFarBackInContextWhenFindingNormalizationBoundary",
|
||||
/* app context pre transform: */ u"a\u0300bcê",
|
||||
/* cached context post transform: */ u"a\u0300bce\u0323\u0302",
|
||||
/* action del, output: */ 1, U"\u0323\u0302", // NFD input; delete 1: \u0302
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"ệ", // NFC output; delete 1: ê
|
||||
/* app_context: */ u"a\u0300bcệ",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// If we don't reach a normalization boundary, we still should continue to work
|
||||
{
|
||||
"NormalizableLettersAtStartOfContext",
|
||||
/* app context pre transform: */ u"\u0300",
|
||||
/* cached context post transform: */ u"\u0323\u0300\u0302",
|
||||
/* action del, output: */ 1, U"\u0323\u0300\u0302", // NFD input;
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"\u0323\u0300\u0302", // NFC output is still decomposed because there is no base
|
||||
/* app_context: */ u"\u0323\u0300\u0302",
|
||||
/* expected del */ U"\u0300"
|
||||
},
|
||||
|
||||
// Modifies the base as well as diacritic
|
||||
|
||||
{
|
||||
"TwoBackspacesForNfdConvertsIntoOneCharInNfcAndRecombine",
|
||||
/* app context pre transform: */ u"abcê",
|
||||
/* cached context post transform: */ u"abca\u0323\u0302",
|
||||
/* action del, output: */ 2, U"a\u0323\u0302", // NFD input; delete 2: e\u0302
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"ậ", // NFC output; delete 1: ê
|
||||
/* app_context: */ u"abcậ",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// surrogate pair tests
|
||||
|
||||
{
|
||||
"SurrogatePairInContext",
|
||||
/* app context pre transform: */ u"abc\U0001F607ê",
|
||||
/* cached context post transform: */ u"abc\U0001F607a\u0323\u0302",
|
||||
/* action del, output: */ 2, U"a\u0323\u0302",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"ậ",
|
||||
/* app_context: */ u"abc\U0001F607ậ",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
{
|
||||
"SurrogatePairInOutput",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abc\U0001F607",
|
||||
/* action del, output: */ 0, U"\U0001F607",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"\U0001F607",
|
||||
/* app_context: */ u"abc\U0001F607",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"SurrogatePairsInBothContextAndOutput",
|
||||
/* app context pre transform: */ u"a\U0001F607bcê",
|
||||
/* cached context post transform: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* action del, output: */ 2, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
/* app_context: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* expected del */ U"ê"
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(KeymanCore, GetActionApiTest, testing::ValuesIn(values), GenerateTestName);
|
||||
INSTANTIATE_TEST_SUITE_P(KeymanCore, GetActionApiTest, testing::ValuesIn(actionsTestData), GenerateTestName);
|
||||
|
|
|
|||
|
|
@ -15,68 +15,15 @@
|
|||
#include "context.hpp"
|
||||
|
||||
#include "../helpers/core_test_helpers.h"
|
||||
#include "./actions_test_data.h"
|
||||
|
||||
struct TestData {
|
||||
const char* test_name;
|
||||
|
||||
/**
|
||||
* the app context stored in the state, _before_ transform is applied -- NFU
|
||||
*/
|
||||
const km_core_cu *initial_app_context;
|
||||
|
||||
/**
|
||||
* cached context _after_ actions have been applied -- guaranteed NFD
|
||||
* (essentially, this is initial_cached_context -
|
||||
* actions_code_points_to_delete + actions_output) - no markers supported
|
||||
*/
|
||||
const km_core_cu *final_cached_context_string;
|
||||
|
||||
/**
|
||||
* cached context _after_ actions have been applied -- guaranteed NFD
|
||||
* (essentially, this is initial_cached_context -
|
||||
* actions_code_points_to_delete + actions_output) - markers supported
|
||||
*/
|
||||
const km_core_context_item *final_cached_context_items;
|
||||
|
||||
/**
|
||||
* number of NFD code points that the keyboard processor has asked to remove in its actions
|
||||
*/
|
||||
int actions_code_points_to_delete;
|
||||
|
||||
/**
|
||||
* NFD string that the keyboard processor has asked to insert in its actions
|
||||
*/
|
||||
const std::u32string actions_output;
|
||||
|
||||
/**
|
||||
* expected: NFU code points to ask app to remove
|
||||
*/
|
||||
const unsigned int expected_delete;
|
||||
|
||||
/**
|
||||
* expected: adjusted NFC output to insert into the app
|
||||
*/
|
||||
const std::u32string expected_output;
|
||||
|
||||
/**
|
||||
* expected: NFU adjusted final app context, which will be NFC from the
|
||||
* boundary of the transform, but will not have been modified prior to that.
|
||||
* Should match char-for-char what the app ends up with in its text buffer.
|
||||
*/
|
||||
const km_core_cu *expected_final_app_context;
|
||||
};
|
||||
|
||||
std::string GenerateTestName(const testing::TestParamInfo<TestData>& info) {
|
||||
return info.param.test_name;
|
||||
}
|
||||
|
||||
class ActionsNormalizeApiTest : public testing::TestWithParam<TestData> {
|
||||
class ActionsNormalizeApiTest : public testing::TestWithParam<ActionsTestData> {
|
||||
protected:
|
||||
km_core_keyboard * test_kb = nullptr;
|
||||
km_core_state * test_state = nullptr;
|
||||
km_core_actions test_actions = {0};
|
||||
|
||||
void Initialize(TestData const& data) {
|
||||
void Initialize(ActionsTestData const& data) {
|
||||
km::core::path path = km::core::path::join(test_dir, "..", "ldml", "fixtures", "keyboards", "17.0", "k_001_tiny.kmx");
|
||||
auto blob = km::tests::load_kmx_file(path.native().c_str());
|
||||
ASSERT_STATUS_OK(km_core_keyboard_load_from_blob(path.stem().c_str(), blob.data(), blob.size(), &test_kb));
|
||||
|
|
@ -143,271 +90,4 @@ TEST_P(ActionsNormalizeApiTest, TestActionsNormalize) {
|
|||
ASSERT_NO_FATAL_FAILURE(km::tests::compare_context(km_core_state_app_context(test_state), data.expected_final_app_context));
|
||||
}
|
||||
|
||||
const km_core_context_item items_1[] = { //u"a\U0001F607b\uFFFF\u0008\u0001ca\U0001F60E",
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0061 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x1F607 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0062 } },
|
||||
{ KM_CORE_CT_MARKER, {0,}, { 0x1 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0063 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0061 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x1F60E } },
|
||||
KM_CORE_CONTEXT_ITEM_END
|
||||
};
|
||||
|
||||
const km_core_context_item items_2[] = { //u"a\U0001F607bca\U0001F60E\uFFFF\u0008\u0001",
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0061 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x1F607 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0062 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0063 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0061 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x1F60E } },
|
||||
{ KM_CORE_CT_MARKER, {0,}, { 0x1 } },
|
||||
KM_CORE_CONTEXT_ITEM_END
|
||||
};
|
||||
|
||||
const km_core_context_item items_11067[] = {
|
||||
{ KM_CORE_CT_CHAR, {0,}, { U'𐒻' } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { U'𐒷' } },
|
||||
KM_CORE_CONTEXT_ITEM_END
|
||||
};
|
||||
|
||||
const TestData values[] = {
|
||||
// Null boundary tests
|
||||
{
|
||||
"Noop",
|
||||
/* app context pre transform: */ u"",
|
||||
/* cached context post transform: */ u"",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"",
|
||||
/* app_context: */ u""
|
||||
},
|
||||
|
||||
{
|
||||
"NoOutput",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abc",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"",
|
||||
/* app_context: */ u"abc"
|
||||
},
|
||||
|
||||
{
|
||||
"NoContext",
|
||||
/* app context pre transform: */ u"",
|
||||
/* cached context post transform: */ u"def",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"def",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"def",
|
||||
/* app_context: */ u"def"
|
||||
},
|
||||
|
||||
// Simple tests -- no deletions involved
|
||||
|
||||
{
|
||||
"NoNormalization",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcdef",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"def",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"def",
|
||||
/* app_context: */ u"abcdef"
|
||||
},
|
||||
|
||||
{
|
||||
"OutputToNfcBasic",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcde\u0300f",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"de\u0300f",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"dèf",
|
||||
/* app_context: */ u"abcdèf"
|
||||
},
|
||||
|
||||
{
|
||||
"OutputToNfcHefty",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcA\u0300" u"e\u0316\u0301" u"\u0073\u0323\u0307" u"\u0041\u030a" u"\U000114B9\U000114B0",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"A\u0300" U"e\u0316\u0301" U"\u0073\u0323\u0307" U"\u0041\u030a" U"\U000114B9\U000114B0",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"À" U"é̖" U"\u1e69" U"\u00c5" U"\U000114BC",
|
||||
/* app_context: */ u"abcÀé̖\u1e69\u00c5\U000114BC"
|
||||
},
|
||||
|
||||
// Interaction with input context when not on normalization boundary
|
||||
|
||||
{
|
||||
"BacktrackOneCharacterToCombineAsNfc",
|
||||
/* app context pre transform: */ u"XYZA",
|
||||
/* cached context post transform: */ u"XYZA\u0300abc",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"\u0300abc",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"Àabc",
|
||||
/* app_context: */ u"XYZÀabc"
|
||||
},
|
||||
|
||||
{
|
||||
"BacktrackEcombCirc2CharsToCombineAsNfc",
|
||||
/* app context pre transform: */ u"abce\u0302",
|
||||
/* cached context post transform: */ u"abce\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"\u0323\u0302",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 2, U"ệ",
|
||||
/* app_context: */ u"abcệ"
|
||||
},
|
||||
|
||||
{
|
||||
"OneBackspaceToDeleteLastNfdCharacter15487",
|
||||
/* app context pre transform: */ u"abcê", // NFC
|
||||
/* cached context post transform: */ u"abce",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"", // NFD input; delete 1: \u0302
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"e", // NFC output; delete 1: e
|
||||
/* app_context: */ u"abce"
|
||||
},
|
||||
|
||||
{
|
||||
"OneBackspaceForNfdConvertsIntoOneCharInNfcAndRecombine",
|
||||
/* app context pre transform: */ u"abcê",
|
||||
/* cached context post transform: */ u"abce\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"\u0323\u0302", // NFD input; delete 1: \u0302
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"ệ", // NFC output; delete 1: ê
|
||||
/* app_context: */ u"abcệ"
|
||||
},
|
||||
|
||||
// a\u0300 should not be normalized because it is not otherwise impacted by
|
||||
// the action.
|
||||
{
|
||||
"AvoidEditingTooFarBackInContextWhenFindingNormalizationBoundary",
|
||||
/* app context pre transform: */ u"a\u0300bcê",
|
||||
/* cached context post transform: */ u"a\u0300bce\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"\u0323\u0302", // NFD input; delete 1: \u0302
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"ệ", // NFC output; delete 1: ê
|
||||
/* app_context: */ u"a\u0300bcệ"
|
||||
},
|
||||
|
||||
// If we don't reach a normalization boundary, we still should continue to work
|
||||
{
|
||||
"NormalizableLettersAtStartOfContext",
|
||||
/* app context pre transform: */ u"\u0300",
|
||||
/* cached context post transform: */ u"\u0323\u0300\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"\u0323\u0300\u0302", // NFD input;
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"\u0323\u0300\u0302", // NFC output is still decomposed because there is no base
|
||||
/* app_context: */ u"\u0323\u0300\u0302"
|
||||
},
|
||||
|
||||
// #15505 - normalization of Bengali characters
|
||||
{
|
||||
"BengaliNormalizationOfU09C7U09D7U09CC",
|
||||
/* app context pre transform: */ u"\u0995\u09C7",
|
||||
/* cached context post transform: */ u"\u0995\u09C7\u09D7",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"\u09D7",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"\u09CC",
|
||||
/* app_context: */ u"\u0995\u09CC"
|
||||
},
|
||||
|
||||
// Modifies the base as well as diacritic
|
||||
|
||||
{
|
||||
"TwoBackspacesForNfdConvertsIntoOneCharInNfcAndRecombine",
|
||||
/* app context pre transform: */ u"abcê",
|
||||
/* cached context post transform: */ u"abca\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 2, U"a\u0323\u0302", // NFD input; delete 2: e\u0302
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"ậ", // NFC output; delete 1: ê
|
||||
/* app_context: */ u"abcậ"
|
||||
},
|
||||
|
||||
// surrogate pair tests
|
||||
|
||||
{
|
||||
"SurrogatePairInContext",
|
||||
/* app context pre transform: */ u"abc\U0001F607ê",
|
||||
/* cached context post transform: */ u"abc\U0001F607a\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 2, U"a\u0323\u0302",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"ậ",
|
||||
/* app_context: */ u"abc\U0001F607ậ"
|
||||
},
|
||||
|
||||
{
|
||||
"SurrogatePairInOutput",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abc\U0001F607",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"\U0001F607",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"\U0001F607",
|
||||
/* app_context: */ u"abc\U0001F607"
|
||||
},
|
||||
|
||||
{
|
||||
"SurrogatePairsInBothContextAndOutput",
|
||||
/* app context pre transform: */ u"a\U0001F607bcê",
|
||||
/* cached context post transform: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 2, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
/* app_context: */ u"a\U0001F607bca\U0001F60E"
|
||||
},
|
||||
|
||||
// Marker tests
|
||||
|
||||
{
|
||||
"AMarkerInTheCachedContextShouldNotShowUpInAppContext",
|
||||
/* app context pre transform: */ u"a\U0001F607bcê",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* cached context post transform: */ &items_1[0],
|
||||
|
||||
/* action del, output: */ 2, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
/* app_context: */ u"a\U0001F607bca\U0001F60E"
|
||||
},
|
||||
|
||||
{
|
||||
"AMarkerInTheModifiedSectionOfCachedContextShouldNotShowUpInAppContext",
|
||||
/* app context pre transform: */ u"a\U0001F607bcê",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* cached context post transform: */ &items_2[0],
|
||||
/* action del, output: */ 2, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
/* app_context: */ u"a\U0001F607bca\U0001F60E"
|
||||
},
|
||||
|
||||
// regression #11067
|
||||
{
|
||||
"ANonBmpCharInContext11067",
|
||||
/* app context pre transform: */ u"𐒻",
|
||||
/* cached context post transform: */ u"𐒻𐒷",
|
||||
/* cached context post transform: */ &items_11067[0],
|
||||
/* action del, output: */ 0, U"𐒻𐒷",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"𐒻𐒷",
|
||||
/* app_context: */ u"𐒻𐒷"
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(KeymanCore, ActionsNormalizeApiTest, testing::ValuesIn(values), GenerateTestName);
|
||||
INSTANTIATE_TEST_SUITE_P(KeymanCore, ActionsNormalizeApiTest, testing::ValuesIn(actionsTestData), GenerateTestName);
|
||||
|
|
|
|||
306
core/tests/unit/api/actions_test_data.cpp
Normal file
306
core/tests/unit/api/actions_test_data.cpp
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
|
||||
#include "./actions_test_data.h"
|
||||
|
||||
const km_core_context_item items_1[] = { //u"a\U0001F607b\uFFFF\u0008\u0001ca\U0001F60E",
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0061 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x1F607 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0062 } },
|
||||
{ KM_CORE_CT_MARKER, {0,}, { 0x1 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0063 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0061 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x1F60E } },
|
||||
KM_CORE_CONTEXT_ITEM_END
|
||||
};
|
||||
|
||||
const km_core_context_item items_2[] = { //u"a\U0001F607bca\U0001F60E\uFFFF\u0008\u0001",
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0061 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x1F607 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0062 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0063 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x0061 } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { 0x1F60E } },
|
||||
{ KM_CORE_CT_MARKER, {0,}, { 0x1 } },
|
||||
KM_CORE_CONTEXT_ITEM_END
|
||||
};
|
||||
|
||||
const km_core_context_item items_11067[] = {
|
||||
{ KM_CORE_CT_CHAR, {0,}, { U'𐒻' } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { U'𐒷' } },
|
||||
KM_CORE_CONTEXT_ITEM_END
|
||||
};
|
||||
|
||||
const std::vector<ActionsTestData> actionsTestData = {
|
||||
// Null boundary tests
|
||||
|
||||
{
|
||||
"Noop",
|
||||
/* app context pre transform: */ u"",
|
||||
/* cached context post transform: */ u"",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 0, U"",
|
||||
/* expected app_context: */ u"",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"NoOutput",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abc",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 0, U"",
|
||||
/* expected app_context: */ u"abc",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"NoContext",
|
||||
/* app context pre transform: */ u"",
|
||||
/* cached context post transform: */ u"def",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"def",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 0, U"def",
|
||||
/* expected app_context: */ u"def",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
// Simple tests -- no deletions involved
|
||||
|
||||
{
|
||||
"NoNormalization",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcdef",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"def",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 0, U"def",
|
||||
/* expected app_context: */ u"abcdef",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"OutputToNfcBasic",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcde\u0300f",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"de\u0300f",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 0, U"dèf",
|
||||
/* expected app_context: */ u"abcdèf",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"OutputToNfcHefty",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcA\u0300" u"e\u0316\u0301" u"\u0073\u0323\u0307" u"\u0041\u030a" u"\U000114B9\U000114B0",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"A\u0300" U"e\u0316\u0301" U"\u0073\u0323\u0307" U"\u0041\u030a" U"\U000114B9\U000114B0",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 0, U"À" U"é̖" U"\u1e69" U"\u00c5" U"\U000114BC",
|
||||
/* expected app_context: */ u"abcÀé̖\u1e69\u00c5\U000114BC",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
// Interaction with input context when not on normalization boundary
|
||||
|
||||
{
|
||||
"BacktrackOneCharacterToCombineAsNfc",
|
||||
/* app context pre transform: */ u"XYZA",
|
||||
/* cached context post transform: */ u"XYZA\u0300abc",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"\u0300abc",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"Àabc",
|
||||
/* expected app_context: */ u"XYZÀabc",
|
||||
/* expected del */ U"A"
|
||||
},
|
||||
|
||||
{
|
||||
"BacktrackECombCirc2CharsToCombineAsNfc",
|
||||
/* app context pre transform: */ u"abce\u0302",
|
||||
/* cached context post transform: */ u"abce\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"\u0323\u0302",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 2, U"ệ",
|
||||
/* expected app_context: */ u"abcệ",
|
||||
/* expected del */ U"e\u0302"
|
||||
},
|
||||
|
||||
{
|
||||
"OneBackspaceToDeleteLastNfdCharacter15487",
|
||||
/* app context pre transform: */ u"abcê", // NFC
|
||||
/* cached context post transform: */ u"abce",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"", // NFD input; delete 1: \u0302
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"e", // NFC output; delete 1: e
|
||||
/* expected app_context: */ u"abce",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
{
|
||||
"OneBackspaceToDeleteLastNfdCharacterWithNfdAppContext15487",
|
||||
/* app context pre transform: */ u"abce\u0302", // NFD
|
||||
/* cached context post transform: */ u"abce",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"", // NFD input; delete 1: \u0302
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"", // NFC output; delete 1: e
|
||||
/* expected app_context: */ u"abce",
|
||||
/* expected del */ U"\u0302"
|
||||
},
|
||||
|
||||
{
|
||||
"OneBackspaceForNfdConvertsIntoOneCharInNfcAndRecombine",
|
||||
/* app context pre transform: */ u"abcê",
|
||||
/* cached context post transform: */ u"abce\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"\u0323\u0302", // NFD input; delete 1: \u0302
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"ệ", // NFC output; delete 1: ê
|
||||
/* expected app_context: */ u"abcệ",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// a\u0300 should not be normalized because it is not otherwise impacted by
|
||||
// the action.
|
||||
{
|
||||
"AvoidEditingTooFarBackInContextWhenFindingNormalizationBoundary",
|
||||
/* app context pre transform: */ u"a\u0300bcê",
|
||||
/* cached context post transform: */ u"a\u0300bce\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"\u0323\u0302", // NFD input; delete 1: \u0302
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"ệ", // NFC output; delete 1: ê
|
||||
/* expected app_context: */ u"a\u0300bcệ",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// If we don't reach a normalization boundary, we still should continue to work
|
||||
{
|
||||
"NormalizableLettersAtStartOfContext",
|
||||
/* app context pre transform: */ u"\u0300",
|
||||
/* cached context post transform: */ u"\u0323\u0300\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"\u0323\u0300\u0302", // NFD input;
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"\u0323\u0300\u0302", // NFC output is still decomposed because there is no base
|
||||
/* expected app_context: */ u"\u0323\u0300\u0302",
|
||||
/* expected del */ U"\u0300"
|
||||
},
|
||||
|
||||
// #15505 - normalization of Bengali characters
|
||||
{
|
||||
"BengaliNormalizationOfU09C7U09D7U09CC",
|
||||
/* app context pre transform: */ u"\u0995\u09C7",
|
||||
/* cached context post transform: */ u"\u0995\u09C7\u09D7",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"\u09D7",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"\u09CC",
|
||||
/* expected app_context: */ u"\u0995\u09CC",
|
||||
/* expected del */ U"\u09C7"
|
||||
},
|
||||
|
||||
// Modifies the base as well as diacritic
|
||||
|
||||
{
|
||||
"TwoBackspacesForNfdConvertsIntoOneCharInNfcAndRecombine",
|
||||
/* app context pre transform: */ u"abcê",
|
||||
/* cached context post transform: */ u"abca\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 2, U"a\u0323\u0302", // NFD input; delete 2: e\u0302
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"ậ", // NFC output; delete 1: ê
|
||||
/* expected app_context: */ u"abcậ",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// surrogate pair tests
|
||||
|
||||
{
|
||||
"SurrogatePairInContext",
|
||||
/* app context pre transform: */ u"abc\U0001F607ê",
|
||||
/* cached context post transform: */ u"abc\U0001F607a\u0323\u0302",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 2, U"a\u0323\u0302",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"ậ",
|
||||
/* expected app_context: */ u"abc\U0001F607ậ",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
{
|
||||
"SurrogatePairInOutput",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abc\U0001F607",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"\U0001F607",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 0, U"\U0001F607",
|
||||
/* expected app_context: */ u"abc\U0001F607",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
"SurrogatePairsInBothContextAndOutput",
|
||||
/* app context pre transform: */ u"a\U0001F607bcê",
|
||||
/* cached context post transform: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 2, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"a\U0001F60E",
|
||||
/* expected app_context: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// Marker tests
|
||||
|
||||
{
|
||||
"AMarkerInTheCachedContextShouldNotShowUpInAppContext",
|
||||
/* app context pre transform: */ u"a\U0001F607bcê",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* cached context post transform: */ &items_1[0],
|
||||
|
||||
/* action del, output: */ 2, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"a\U0001F60E",
|
||||
/* expected app_context: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
{
|
||||
"AMarkerInTheModifiedSectionOfCachedContextShouldNotShowUpInAppContext",
|
||||
/* app context pre transform: */ u"a\U0001F607bcê",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* cached context post transform: */ &items_2[0],
|
||||
/* action del, output: */ 2, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"a\U0001F60E",
|
||||
/* expected app_context: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// regression #11067
|
||||
{
|
||||
"ANonBmpCharInContext11067",
|
||||
/* app context pre transform: */ u"𐒻",
|
||||
/* cached context post transform: */ u"𐒻𐒷",
|
||||
/* cached context post transform: */ &items_11067[0],
|
||||
/* action del, output: */ 0, U"𐒻𐒷",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"𐒻𐒷",
|
||||
/* expected app_context: */ u"𐒻𐒷",
|
||||
/* expected del: */ U"\x104BB"
|
||||
}
|
||||
};
|
||||
|
||||
std::string GenerateTestName(const testing::TestParamInfo<ActionsTestData>& info) {
|
||||
return info.param.test_name;
|
||||
}
|
||||
64
core/tests/unit/api/actions_test_data.h
Normal file
64
core/tests/unit/api/actions_test_data.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <gtest/gtest.h>
|
||||
#include "keyman_core.h"
|
||||
|
||||
struct ActionsTestData {
|
||||
const char* test_name;
|
||||
|
||||
/**
|
||||
* the app context stored in the state, _before_ transform is applied -- NFU
|
||||
*/
|
||||
const km_core_cu *initial_app_context;
|
||||
|
||||
/**
|
||||
* cached context _after_ actions have been applied -- guaranteed NFD
|
||||
* (essentially, this is initial_cached_context -
|
||||
* actions_code_points_to_delete + actions_output) - no markers supported
|
||||
*/
|
||||
const km_core_cu *final_cached_context_string;
|
||||
|
||||
/**
|
||||
* cached context _after_ actions have been applied -- guaranteed NFD
|
||||
* (essentially, this is initial_cached_context -
|
||||
* actions_code_points_to_delete + actions_output) - markers supported
|
||||
*/
|
||||
const km_core_context_item *final_cached_context_items;
|
||||
|
||||
/**
|
||||
* number of NFD code points that the keyboard processor has asked to remove in its actions
|
||||
*/
|
||||
int actions_code_points_to_delete;
|
||||
|
||||
/**
|
||||
* NFD string that the keyboard processor has asked to insert in its actions
|
||||
*/
|
||||
const std::u32string actions_output;
|
||||
|
||||
/**
|
||||
* expected: NFU code points to ask app to remove
|
||||
*/
|
||||
const unsigned int expected_delete;
|
||||
|
||||
/**
|
||||
* expected: adjusted NFC output to insert into the app
|
||||
*/
|
||||
const std::u32string expected_output;
|
||||
|
||||
/**
|
||||
* expected: NFU adjusted final app context, which will be NFC from the
|
||||
* boundary of the transform, but will not have been modified prior to that.
|
||||
* Should match char-for-char what the app ends up with in its text buffer.
|
||||
*/
|
||||
const km_core_cu *expected_final_app_context;
|
||||
|
||||
/**
|
||||
* expected: the characters deleted from the context
|
||||
*/
|
||||
const std::u32string expected_deleted_context;
|
||||
};
|
||||
|
||||
extern const std::vector<ActionsTestData> actionsTestData;
|
||||
|
||||
std::string GenerateTestName(const testing::TestParamInfo<ActionsTestData>& info);
|
||||
|
|
@ -15,72 +15,15 @@
|
|||
#include "context.hpp"
|
||||
|
||||
#include "../helpers/core_test_helpers.h"
|
||||
#include "./actions_test_data.h"
|
||||
|
||||
// TODO-WEB-CORE: merge with actions_normalize.tests.cpp? These are identical;
|
||||
// note that actions_get_api and actions_set_api data are subtly different,
|
||||
// opportunity to merge those too?
|
||||
|
||||
struct TestData {
|
||||
const char* test_name;
|
||||
|
||||
/**
|
||||
* the app context stored in the state, _before_ transform is applied -- NFU
|
||||
*/
|
||||
const km_core_cu *initial_app_context;
|
||||
|
||||
/**
|
||||
* cached context _after_ actions have been applied -- guaranteed NFD
|
||||
* (essentially, this is initial_cached_context -
|
||||
* actions_code_points_to_delete + actions_output) - no markers supported
|
||||
*/
|
||||
const km_core_cu *final_cached_context_string;
|
||||
|
||||
/**
|
||||
* cached context _after_ actions have been applied -- guaranteed NFD
|
||||
* (essentially, this is initial_cached_context -
|
||||
* actions_code_points_to_delete + actions_output) - markers supported
|
||||
*/
|
||||
const km_core_context_item *final_cached_context_items;
|
||||
|
||||
/**
|
||||
* number of NFD code points that the keyboard processor has asked to remove in its actions
|
||||
*/
|
||||
int actions_code_points_to_delete;
|
||||
|
||||
/**
|
||||
* NFD string that the keyboard processor has asked to insert in its actions
|
||||
*/
|
||||
const std::u32string actions_output;
|
||||
|
||||
/**
|
||||
* expected: NFU code points to ask app to remove
|
||||
*/
|
||||
const unsigned int expected_delete;
|
||||
|
||||
/**
|
||||
* expected: adjusted NFC output to insert into the app
|
||||
*/
|
||||
const std::u32string expected_output;
|
||||
|
||||
/**
|
||||
* expected: NFU adjusted final app context, which will be NFC from the
|
||||
* boundary of the transform, but will not have been modified prior to that.
|
||||
* Should match char-for-char what the app ends up with in its text buffer.
|
||||
*/
|
||||
const km_core_cu *expected_final_app_context;
|
||||
};
|
||||
|
||||
std::string GenerateTestName(const testing::TestParamInfo<TestData>& info) {
|
||||
return info.param.test_name;
|
||||
}
|
||||
|
||||
class ActionsUpdateAppContextNfuApiTest : public testing::TestWithParam<TestData> {
|
||||
class ActionsUpdateAppContextNfuApiTest : public testing::TestWithParam<ActionsTestData> {
|
||||
protected:
|
||||
km_core_keyboard * test_kb = nullptr;
|
||||
km_core_state * test_state = nullptr;
|
||||
km_core_actions test_actions = {0};
|
||||
|
||||
void Initialize(TestData const& data) {
|
||||
void Initialize(ActionsTestData const& data) {
|
||||
km::core::path path = km::core::path::join(test_dir, "..", "ldml", "fixtures", "keyboards", "17.0", "k_001_tiny.kmx");
|
||||
auto blob = km::tests::load_kmx_file(path.native().c_str());
|
||||
ASSERT_STATUS_OK(km_core_keyboard_load_from_blob(path.stem().c_str(), blob.data(), blob.size(), &test_kb));
|
||||
|
|
@ -172,7 +115,23 @@ const km_core_context_item items_2[] = { //u"a\U0001F607bca\U0001F60E\uFFFF\u000
|
|||
KM_CORE_CONTEXT_ITEM_END
|
||||
};
|
||||
|
||||
const TestData values[] = {
|
||||
const km_core_context_item items_11067[] = {
|
||||
{ KM_CORE_CT_CHAR, {0,}, { U'𐒻' } },
|
||||
{ KM_CORE_CT_CHAR, {0,}, { U'𐒷' } },
|
||||
KM_CORE_CONTEXT_ITEM_END
|
||||
};
|
||||
|
||||
/**
|
||||
* Test cases for non-normalized app context update. These look superficially
|
||||
* similar to the data in `actionsTestData`, but diverge when taking into
|
||||
* account normalization of output. Several normalization-related tests in
|
||||
* `actionsTestData` are therefore also currently excluded here.
|
||||
*
|
||||
* @todo: (low priority) `actionsTestData` and `actionsTestDataNFU` could be
|
||||
* combined with additional entries for each NFU result.
|
||||
*/
|
||||
|
||||
const std::vector<ActionsTestData> actionsTestDataNFU = {
|
||||
// Null boundary tests
|
||||
|
||||
{
|
||||
|
|
@ -182,8 +141,9 @@ const TestData values[] = {
|
|||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"",
|
||||
/* app_context: */ u""
|
||||
/* expected action del, output: */ 0, U"",
|
||||
/* expected app_context: */ u"",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
|
|
@ -193,8 +153,9 @@ const TestData values[] = {
|
|||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"",
|
||||
/* app_context: */ u"abc"
|
||||
/* expected action del, output: */ 0, U"",
|
||||
/* expected app_context: */ u"abc",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
|
|
@ -204,10 +165,26 @@ const TestData values[] = {
|
|||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"def",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"def",
|
||||
/* app_context: */ u"def"
|
||||
/* expected action del, output: */ 0, U"def",
|
||||
/* expected app_context: */ u"def",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
// Simple tests -- no deletions involved
|
||||
|
||||
{
|
||||
"NoNormalization",
|
||||
/* app context pre transform: */ u"abc",
|
||||
/* cached context post transform: */ u"abcdef",
|
||||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"def",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 0, U"def",
|
||||
/* expected app_context: */ u"abcdef",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
|
||||
// surrogate pair tests
|
||||
|
||||
{
|
||||
|
|
@ -217,8 +194,9 @@ const TestData values[] = {
|
|||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"a\u0323\u0302",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"a\u0323\u0302",
|
||||
/* app_context: */ u"abc\U0001F607a\u0323\u0302"
|
||||
/* expected action del, output: */ 1, U"a\u0323\u0302",
|
||||
/* expected app_context: */ u"abc\U0001F607a\u0323\u0302",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
{
|
||||
|
|
@ -228,8 +206,9 @@ const TestData values[] = {
|
|||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 0, U"\U0001F607",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 0, U"\U0001F607",
|
||||
/* app_context: */ u"abc\U0001F607"
|
||||
/* expected action del, output: */ 0, U"\U0001F607",
|
||||
/* expected app_context: */ u"abc\U0001F607",
|
||||
/* expected del */ U""
|
||||
},
|
||||
|
||||
{
|
||||
|
|
@ -239,8 +218,9 @@ const TestData values[] = {
|
|||
/* cached context post transform: */ nullptr,
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
/* app_context: */ u"a\U0001F607bca\U0001F60E"
|
||||
/* expected action del, output: */ 1, U"a\U0001F60E",
|
||||
/* expected app_context: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// Marker tests
|
||||
|
|
@ -252,8 +232,9 @@ const TestData values[] = {
|
|||
/* cached context post transform: */ &items_1[0],
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
/* app_context: */ u"a\U0001F607bca\U0001F60E"
|
||||
/* expected action del, output: */ 1, U"a\U0001F60E",
|
||||
/* expected app_context: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
{
|
||||
|
|
@ -263,9 +244,23 @@ const TestData values[] = {
|
|||
/* cached context post transform: */ &items_2[0],
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
// ---- results ----
|
||||
/* action del, output: */ 1, U"a\U0001F60E",
|
||||
/* app_context: */ u"a\U0001F607bca\U0001F60E"
|
||||
/* expected action del, output: */ 1, U"a\U0001F60E",
|
||||
/* expected app_context: */ u"a\U0001F607bca\U0001F60E",
|
||||
/* expected del */ U"ê"
|
||||
},
|
||||
|
||||
// regression #11067
|
||||
{
|
||||
"ANonBmpCharInContext11067",
|
||||
/* app context pre transform: */ u"𐒻",
|
||||
/* cached context post transform: */ u"𐒻𐒷",
|
||||
/* cached context post transform: */ &items_11067[0],
|
||||
/* action del, output: */ 1, U"𐒻𐒷",
|
||||
// ---- results ----
|
||||
/* expected action del, output: */ 1, U"𐒻𐒷",
|
||||
/* expected app_context: */ u"𐒻𐒷",
|
||||
/* expected del: */ U"\x104BB"
|
||||
}
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(KeymanCore, ActionsUpdateAppContextNfuApiTest, testing::ValuesIn(values), GenerateTestName);
|
||||
INSTANTIATE_TEST_SUITE_P(KeymanCore, ActionsUpdateAppContextNfuApiTest, testing::ValuesIn(actionsTestDataNFU), GenerateTestName);
|
||||
|
|
|
|||
|
|
@ -1352,23 +1352,23 @@ TEST(XStringTests, TestU32stringToU16string) {
|
|||
|
||||
TEST(XStringTests, TestIsValid) {
|
||||
// valid
|
||||
ASSERT_EQ(Uni_IsValid(0x0000), true);
|
||||
ASSERT_EQ(Uni_IsValid(0x0127), true);
|
||||
ASSERT_EQ(Uni_IsValid(U'🙀'), true);
|
||||
ASSERT_TRUE(Uni_IsValid(0x0000));
|
||||
ASSERT_TRUE(Uni_IsValid(0x0127));
|
||||
ASSERT_TRUE(Uni_IsValid(U'🙀'));
|
||||
|
||||
// invalid
|
||||
ASSERT_EQ(Uni_IsValid(0xDECAFBAD), false); // out of range
|
||||
ASSERT_EQ(Uni_IsValid(0x566D4128), false);
|
||||
ASSERT_EQ(Uni_IsValid(0xFFFF), false); // nonchar
|
||||
ASSERT_EQ(Uni_IsValid(0xFFFE), false); // nonchar
|
||||
ASSERT_EQ(Uni_IsValid(0x10FFFF), false); // nonchar
|
||||
ASSERT_EQ(Uni_IsValid(0x10FFFE), false); // nonchar
|
||||
ASSERT_EQ(Uni_IsValid(0x01FFFF), false); // nonchar
|
||||
ASSERT_EQ(Uni_IsValid(0x01FFFE), false); // nonchar
|
||||
ASSERT_EQ(Uni_IsValid(0x02FFFF), false); // nonchar
|
||||
ASSERT_EQ(Uni_IsValid(0x02FFFE), false); // nonchar
|
||||
ASSERT_EQ(Uni_IsValid(0xFDD1), false); // nonchar
|
||||
ASSERT_EQ(Uni_IsValid(0xFDD0), false); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0xDECAFBAD)); // out of range
|
||||
ASSERT_FALSE(Uni_IsValid(0x566D4128));
|
||||
ASSERT_FALSE(Uni_IsValid(0xFFFF)); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0xFFFE)); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0x10FFFF)); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0x10FFFE)); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0x01FFFF)); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0x01FFFE)); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0x02FFFF)); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0x02FFFE)); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0xFDD1)); // nonchar
|
||||
ASSERT_FALSE(Uni_IsValid(0xFDD0)); // nonchar
|
||||
|
||||
|
||||
// positive range test
|
||||
|
|
|
|||
|
|
@ -40,15 +40,15 @@ tests = [
|
|||
['debug-api-tests', 'debug_api.tests.cpp'],
|
||||
['kmx_xstring-tests', 'kmx_xstring.tests.cpp'],
|
||||
['kmx_context-tests', 'kmx_context.tests.cpp'],
|
||||
['actions_normalize-tests', 'actions_normalize.tests.cpp'],
|
||||
['actions_normalize-tests', ['actions_normalize.tests.cpp', 'actions_test_data.cpp']],
|
||||
|
||||
# renamed to avoid heuristic that causes "update" in a filename to require
|
||||
# elevation on Windows! this could also be avoided by adding a manifest
|
||||
# resource to each executable (e.g. with mt.exe)
|
||||
# https://learn.microsoft.com/en-us/windows/security/application-security/application-control/user-account-control/architecture#installer-detection-technology
|
||||
['actions_updatx_app_context_nfu-tests', 'actions_update_app_context_nfu.tests.cpp'],
|
||||
['actions_updatx_app_context_nfu-tests', ['actions_update_app_context_nfu.tests.cpp', 'actions_test_data.cpp']],
|
||||
|
||||
['actions_get_api-tests', 'actions_get_api.tests.cpp'],
|
||||
['actions_get_api-tests', ['actions_get_api.tests.cpp', 'actions_test_data.cpp']],
|
||||
['km_core_keyboard_api-tests', 'km_core_keyboard_api.tests.cpp'],
|
||||
['km_core_process_event-tests', 'km_core_process_event.tests.cpp'],
|
||||
['key_list-tests', 'kmx_key_list.tests.cpp'],
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ class StateContextApiTests : public testing::Test {
|
|||
protected:
|
||||
km_core_keyboard *test_kb = nullptr;
|
||||
km_core_state *test_state = nullptr;
|
||||
km_core_context_item *citems = nullptr;
|
||||
|
||||
void Initialize(const char *keyboard, const km_core_cu *context, bool setup_app_context = true) {
|
||||
km::core::path path = km::core::path(test_dir / ".." / "kmx" / keyboard);
|
||||
|
|
@ -36,18 +35,20 @@ protected:
|
|||
ASSERT_STATUS_OK(km_core_keyboard_load_from_blob(path.stem().c_str(), blob.data(), blob.size(), &test_kb));
|
||||
}
|
||||
ASSERT_STATUS_OK(km_core_state_create(test_kb, test_empty_env_opts, &test_state));
|
||||
ASSERT_STATUS_OK(context_items_from_utf16(context, &citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
|
||||
km_core_context_item *context_items = nullptr;
|
||||
ASSERT_STATUS_OK(context_items_from_utf16(context, &context_items));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), context_items));
|
||||
if (setup_app_context) {
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_app_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_app_context(test_state), context_items));
|
||||
}
|
||||
if (context_items) {
|
||||
km_core_context_items_dispose(context_items);
|
||||
context_items = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if (citems) {
|
||||
km_core_context_items_dispose(citems);
|
||||
citems = nullptr;
|
||||
}
|
||||
if (test_state) {
|
||||
km_core_state_dispose(test_state);
|
||||
test_state = nullptr;
|
||||
|
|
@ -57,57 +58,63 @@ protected:
|
|||
test_kb = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void assert_identical_context(km_core_cu const *expected_context) {
|
||||
size_t buf_size;
|
||||
ASSERT_STATUS_OK(km_core_context_get(km_core_state_context(test_state), &citems));
|
||||
ASSERT_STATUS_OK(context_items_to_utf16(citems, nullptr, &buf_size));
|
||||
km_core_cu *actual_context = new km_core_cu[buf_size];
|
||||
ASSERT_STATUS_OK(context_items_to_utf16(citems, actual_context, &buf_size));
|
||||
ASSERT_EQ(std::u16string(expected_context), actual_context);
|
||||
delete[] actual_context;
|
||||
}
|
||||
|
||||
void assert_different_context(km_core_cu const *expected_context) {
|
||||
size_t buf_size;
|
||||
ASSERT_STATUS_OK(km_core_context_get(km_core_state_context(test_state), &citems));
|
||||
ASSERT_STATUS_OK(context_items_to_utf16(citems, nullptr, &buf_size));
|
||||
km_core_cu *actual_context = new km_core_cu[buf_size];
|
||||
ASSERT_STATUS_OK(context_items_to_utf16(citems, actual_context, &buf_size));
|
||||
ASSERT_NE(std::u16string(expected_context), actual_context);
|
||||
delete[] actual_context;
|
||||
}
|
||||
};
|
||||
|
||||
void assert_identical_context(const km_core_context *actual_context, km_core_cu const *expected_context) {
|
||||
km_core_context_item *actual_context_items;
|
||||
size_t buf_size;
|
||||
ASSERT_STATUS_OK(km_core_context_get(actual_context, &actual_context_items));
|
||||
ASSERT_STATUS_OK(context_items_to_utf16(actual_context_items, nullptr, &buf_size));
|
||||
km_core_cu *actual_context_cu = new km_core_cu[buf_size];
|
||||
ASSERT_STATUS_OK(context_items_to_utf16(actual_context_items, actual_context_cu, &buf_size));
|
||||
km_core_context_items_dispose(actual_context_items);
|
||||
|
||||
void assert_identical_context_with_markers(const km_core_context *context, const km_core_context_item *citems) {
|
||||
km_core_context_item *citems_new;
|
||||
ASSERT_STATUS_OK(km_core_context_get(context, &citems_new));
|
||||
for (int i = 0; citems[i].type || citems_new[i].type; i++) {
|
||||
ASSERT_EQ(citems_new[i].type, citems[i].type) << "Unexpected type:";
|
||||
if (citems[i].type == KM_CORE_CT_CHAR) {
|
||||
ASSERT_EQ(citems_new[i].character, citems[i].character) << "Unexpected character:";
|
||||
} else {
|
||||
ASSERT_EQ(citems_new[i].marker, citems[i].marker) << "Unexpected marker:";
|
||||
}
|
||||
}
|
||||
km_core_context_items_dispose(citems_new);
|
||||
ASSERT_EQ(actual_context_cu, std::u16string(expected_context));
|
||||
delete[] actual_context_cu;
|
||||
}
|
||||
|
||||
// citems contains markers, but we will skip over them
|
||||
void assert_identical_context_without_markers(const km_core_context *context, const km_core_context_item *citems) {
|
||||
km_core_context_item *citems_new;
|
||||
ASSERT_STATUS_OK(km_core_context_get(context, &citems_new));
|
||||
for (int i = 0, i_new = 0; citems[i].type || citems_new[i_new].type; i++) {
|
||||
if (citems[i].type == KM_CORE_CT_CHAR) {
|
||||
ASSERT_EQ(citems_new[i_new].type, citems[i].type) << "Unexpected type:";
|
||||
ASSERT_EQ(citems_new[i_new].character, citems[i].character) << "Unexpected character:";
|
||||
i_new++;
|
||||
} else if(citems[i].type == KM_CORE_CT_END) {
|
||||
ASSERT_EQ(citems_new[i_new].type, citems[i].type) << "Unexpected type:";
|
||||
void assert_different_context(const km_core_context *actual_context, km_core_cu const *expected_context) {
|
||||
km_core_context_item *actual_context_items;
|
||||
size_t buf_size;
|
||||
ASSERT_STATUS_OK(km_core_context_get(actual_context, &actual_context_items));
|
||||
ASSERT_STATUS_OK(context_items_to_utf16(actual_context_items, nullptr, &buf_size));
|
||||
km_core_cu *actual_context_cu = new km_core_cu[buf_size];
|
||||
ASSERT_STATUS_OK(context_items_to_utf16(actual_context_items, actual_context_cu, &buf_size));
|
||||
km_core_context_items_dispose(actual_context_items);
|
||||
|
||||
ASSERT_NE(actual_context_cu, std::u16string(expected_context));
|
||||
delete[] actual_context_cu;
|
||||
}
|
||||
|
||||
|
||||
void assert_identical_context_with_markers(const km_core_context *actual_context, const km_core_context_item *expected_context_items) {
|
||||
km_core_context_item *actual_context_items;
|
||||
ASSERT_STATUS_OK(km_core_context_get(actual_context, &actual_context_items));
|
||||
for (int i = 0; expected_context_items[i].type || actual_context_items[i].type; i++) {
|
||||
ASSERT_EQ(actual_context_items[i].type, expected_context_items[i].type) << "Unexpected type:";
|
||||
if (expected_context_items[i].type == KM_CORE_CT_CHAR) {
|
||||
ASSERT_EQ(actual_context_items[i].character, expected_context_items[i].character) << "Unexpected character:";
|
||||
} else {
|
||||
ASSERT_EQ(actual_context_items[i].marker, expected_context_items[i].marker) << "Unexpected marker:";
|
||||
}
|
||||
}
|
||||
km_core_context_items_dispose(citems_new);
|
||||
km_core_context_items_dispose(actual_context_items);
|
||||
}
|
||||
|
||||
// expected_context_items contains markers, but we will skip over them
|
||||
void assert_identical_context_without_markers(const km_core_context *actual_context, const km_core_context_item *expected_context_items) {
|
||||
km_core_context_item *actual_context_items;
|
||||
ASSERT_STATUS_OK(km_core_context_get(actual_context, &actual_context_items));
|
||||
for (int i = 0, i_new = 0; expected_context_items[i].type || actual_context_items[i_new].type; i++) {
|
||||
if (expected_context_items[i].type == KM_CORE_CT_CHAR) {
|
||||
ASSERT_EQ(actual_context_items[i_new].type, expected_context_items[i].type) << "Unexpected type:";
|
||||
ASSERT_EQ(actual_context_items[i_new].character, expected_context_items[i].character) << "Unexpected character:";
|
||||
i_new++;
|
||||
} else if(expected_context_items[i].type == KM_CORE_CT_END) {
|
||||
ASSERT_EQ(actual_context_items[i_new].type, expected_context_items[i].type) << "Unexpected type:";
|
||||
}
|
||||
}
|
||||
km_core_context_items_dispose(actual_context_items);
|
||||
}
|
||||
|
||||
// Scenarios from #10100:
|
||||
|
|
@ -118,7 +125,7 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededIdenticalContext) {
|
|||
km_core_cu const *new_app_context = u"This is a test";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context, false));
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UNCHANGED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), cached_context));
|
||||
}
|
||||
|
||||
// 1a. cached context has markers and is identical to app context
|
||||
|
|
@ -127,17 +134,17 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededIdenticalContextAndMarkers) {
|
|||
km_core_cu const *new_app_context = u"123";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
|
||||
km_core_context_item const citems[] = {
|
||||
km_core_context_item const expected_context_items[] = {
|
||||
{KM_CORE_CT_MARKER, {0}, {5}}, {KM_CORE_CT_CHAR, {0}, {'1'}}, {KM_CORE_CT_MARKER, {0}, {1}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'2'}}, {KM_CORE_CT_MARKER, {0}, {2}}, {KM_CORE_CT_CHAR, {0}, {'3'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {3}}, {KM_CORE_CT_MARKER, {0}, {4}}, KM_CORE_CONTEXT_ITEM_END};
|
||||
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), expected_context_items));
|
||||
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UNCHANGED);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_context_items));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_context_items));
|
||||
}
|
||||
|
||||
// 2. cached context same length as app context but content is different
|
||||
|
|
@ -146,8 +153,8 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededDifferentContext) {
|
|||
km_core_cu const *new_app_context = u"This is a test";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(km_core_state_context(test_state), cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), new_app_context));
|
||||
}
|
||||
|
||||
// 3. cached context is shorter than app context, but content is same as far as it goes
|
||||
|
|
@ -156,8 +163,8 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededAppContextIsLonger) {
|
|||
km_core_cu const *new_app_context = u"Longer This is a test";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(km_core_state_context(test_state), cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), new_app_context));
|
||||
}
|
||||
|
||||
// 3a. cached context has markers and is shorter than app context,
|
||||
|
|
@ -167,22 +174,22 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededCachedContextShorterAndMarker
|
|||
km_core_cu const *new_app_context = u"0123";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
|
||||
km_core_context_item const citems[] = {
|
||||
km_core_context_item const initial_context_items[] = {
|
||||
{KM_CORE_CT_MARKER, {0}, {5}}, {KM_CORE_CT_CHAR, {0}, {'1'}}, {KM_CORE_CT_MARKER, {0}, {1}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'2'}}, {KM_CORE_CT_MARKER, {0}, {2}}, {KM_CORE_CT_CHAR, {0}, {'3'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {3}}, {KM_CORE_CT_MARKER, {0}, {4}}, KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), initial_context_items));
|
||||
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
|
||||
km_core_context_item const expected_citems[] = {
|
||||
km_core_context_item const expected_context_items[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {'0'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {5}}, {KM_CORE_CT_CHAR, {0}, {'1'}}, {KM_CORE_CT_MARKER, {0}, {1}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'2'}}, {KM_CORE_CT_MARKER, {0}, {2}}, {KM_CORE_CT_CHAR, {0}, {'3'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {3}}, {KM_CORE_CT_MARKER, {0}, {4}}, KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_context_items));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_context_items));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), new_app_context));
|
||||
}
|
||||
|
||||
TEST_F(StateContextApiTests, TestContextSetIfNeededCachedContextShorterAndMarkersNfu) {
|
||||
|
|
@ -190,22 +197,22 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededCachedContextShorterAndMarker
|
|||
km_core_cu const *new_app_context = u"abcệ";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("/a/dummy/keyboard.mock", cached_context));
|
||||
|
||||
km_core_context_item const citems[] = {
|
||||
km_core_context_item const initial_context_items[] = {
|
||||
{KM_CORE_CT_MARKER, {0}, {1}}, {KM_CORE_CT_CHAR, {0}, {'b'}}, {KM_CORE_CT_MARKER, {0}, {2}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'c'}}, {KM_CORE_CT_MARKER, {0}, {3}}, {KM_CORE_CT_MARKER, {0}, {4}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'e'}}, {KM_CORE_CT_CHAR, {0}, {u'\u0323'}},
|
||||
{KM_CORE_CT_CHAR, {0}, {u'\u0302'}}, KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), initial_context_items));
|
||||
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
|
||||
km_core_context_item const expected_citems[] = {
|
||||
km_core_context_item const expected_context_items[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {'a'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {1}}, {KM_CORE_CT_CHAR, {0}, {'b'}}, {KM_CORE_CT_MARKER, {0}, {2}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'c'}}, {KM_CORE_CT_MARKER, {0}, {3}}, {KM_CORE_CT_MARKER, {0}, {4}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'e'}}, {KM_CORE_CT_CHAR, {0}, {u'\u0323'}},
|
||||
{KM_CORE_CT_CHAR, {0}, {u'\u0302'}}, KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_context_items));
|
||||
km_core_context_item const expected_app_citems[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {'a'}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'b'}},
|
||||
|
|
@ -221,8 +228,8 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededCachedContextCleared) {
|
|||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
km_core_state_context_clear(test_state);
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(km_core_state_context(test_state), cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), new_app_context));
|
||||
}
|
||||
|
||||
// 5. cached context is longer than app context, but content is same as far as it goes
|
||||
|
|
@ -231,8 +238,8 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededAppContextIsShorter) {
|
|||
km_core_cu const *new_app_context = u"is a test";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(km_core_state_context(test_state), cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), new_app_context));
|
||||
}
|
||||
|
||||
// 5a. cached context has markers and is longer than app context, but
|
||||
|
|
@ -242,21 +249,21 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededCachedContextLongerAndMarkers
|
|||
km_core_cu const *new_app_context = u"123";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
|
||||
km_core_context_item const citems[] = {
|
||||
km_core_context_item const initial_context_items[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {'0'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {5}}, {KM_CORE_CT_CHAR, {0}, {'1'}}, {KM_CORE_CT_MARKER, {0}, {1}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'2'}}, {KM_CORE_CT_MARKER, {0}, {2}}, {KM_CORE_CT_CHAR, {0}, {'3'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {3}}, {KM_CORE_CT_MARKER, {0}, {4}}, KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), initial_context_items));
|
||||
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
|
||||
km_core_context_item const expected_citems[] = {
|
||||
km_core_context_item const expected_context_items[] = {
|
||||
{KM_CORE_CT_MARKER, {0}, {5}}, {KM_CORE_CT_CHAR, {0}, {'1'}}, {KM_CORE_CT_MARKER, {0}, {1}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'2'}}, {KM_CORE_CT_MARKER, {0}, {2}}, {KM_CORE_CT_CHAR, {0}, {'3'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {3}}, {KM_CORE_CT_MARKER, {0}, {4}}, KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_context_items));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_context_items));
|
||||
}
|
||||
|
||||
TEST_F(StateContextApiTests, TestContextSetIfNeededCachedContextLongerAndMarkersNfu) {
|
||||
|
|
@ -264,22 +271,22 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededCachedContextLongerAndMarkers
|
|||
km_core_cu const *new_app_context = u"bcệ";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("/a/dummy/keyboard.mock", cached_context));
|
||||
|
||||
km_core_context_item const citems[] = {
|
||||
km_core_context_item const initial_context_items[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {'a'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {1}}, {KM_CORE_CT_CHAR, {0}, {'b'}}, {KM_CORE_CT_MARKER, {0}, {2}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'c'}}, {KM_CORE_CT_MARKER, {0}, {3}}, {KM_CORE_CT_MARKER, {0}, {4}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'e'}}, {KM_CORE_CT_CHAR, {0}, {u'\u0323'}},
|
||||
{KM_CORE_CT_CHAR, {0}, {u'\u0302'}}, KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), initial_context_items));
|
||||
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
|
||||
km_core_context_item const expected_citems[] = {
|
||||
km_core_context_item const expected_context_items[] = {
|
||||
{KM_CORE_CT_MARKER, {0}, {1}}, {KM_CORE_CT_CHAR, {0}, {'b'}}, {KM_CORE_CT_MARKER, {0}, {2}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'c'}}, {KM_CORE_CT_MARKER, {0}, {3}}, {KM_CORE_CT_MARKER, {0}, {4}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'e'}}, {KM_CORE_CT_CHAR, {0}, {u'\u0323'}},
|
||||
{KM_CORE_CT_CHAR, {0}, {u'\u0302'}}, KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_context_items));
|
||||
|
||||
km_core_context_item const expected_app_citems[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {'b'}},
|
||||
|
|
@ -295,8 +302,8 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededApplicationContextEmpty) {
|
|||
km_core_cu const *new_app_context = u"";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(km_core_state_context(test_state), cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), new_app_context));
|
||||
}
|
||||
|
||||
// 7. surrogate pairs in context
|
||||
|
|
@ -305,7 +312,7 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsUnchanged) {
|
|||
km_core_cu const *new_app_context = u"a\U00010100";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UNCHANGED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), new_app_context));
|
||||
}
|
||||
|
||||
TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsAppContextLonger) {
|
||||
|
|
@ -313,7 +320,7 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsAppContextLonge
|
|||
km_core_cu const *new_app_context = u"xa\U00010100";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), new_app_context));
|
||||
}
|
||||
|
||||
TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsCachedContextLonger) {
|
||||
|
|
@ -321,7 +328,7 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsCachedContextLo
|
|||
km_core_cu const *new_app_context = u"a\U00010100";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), new_app_context));
|
||||
}
|
||||
|
||||
TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsUnchangedAndMarkers) {
|
||||
|
|
@ -329,16 +336,16 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsUnchangedAndMar
|
|||
km_core_cu const *new_app_context = u"a\U00010100";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
|
||||
km_core_context_item const citems[] = {
|
||||
km_core_context_item const expected_context_items[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {'a'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {5}},
|
||||
{KM_CORE_CT_CHAR, {0}, {0x10100}},
|
||||
KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), expected_context_items));
|
||||
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UNCHANGED);
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_context_items));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_context_items));
|
||||
}
|
||||
|
||||
TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsAppContextLongerAndMarkers) {
|
||||
|
|
@ -346,23 +353,23 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsAppContextLonge
|
|||
km_core_cu const *new_app_context = u"\U00010200a\U00010100";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
|
||||
km_core_context_item const citems[] = {
|
||||
km_core_context_item const initial_context_items[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {'a'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {5}},
|
||||
{KM_CORE_CT_CHAR, {0}, {0x10100}},
|
||||
KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), initial_context_items));
|
||||
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
km_core_context_item const expected_citems[] = {
|
||||
km_core_context_item const expected_context_items[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {0x10200}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'a'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {5}},
|
||||
{KM_CORE_CT_CHAR, {0}, {0x10100}},
|
||||
KM_CORE_CONTEXT_ITEM_END};
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_context_items));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_context_items));
|
||||
}
|
||||
|
||||
TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsCachedContextLongerAndMarkers) {
|
||||
|
|
@ -370,23 +377,23 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsCachedContextLo
|
|||
km_core_cu const *new_app_context = u"a\U00010100";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
|
||||
km_core_context_item const citems[] = {
|
||||
km_core_context_item const initial_context_items[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {0x10200}},
|
||||
{KM_CORE_CT_CHAR, {0}, {'a'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {5}},
|
||||
{KM_CORE_CT_CHAR, {0}, {0x10100}},
|
||||
KM_CORE_CONTEXT_ITEM_END};
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), initial_context_items));
|
||||
|
||||
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, new_app_context), KM_CORE_CONTEXT_STATUS_UPDATED);
|
||||
km_core_context_item const expected_citems[] = {
|
||||
km_core_context_item const expected_context_items[] = {
|
||||
{KM_CORE_CT_CHAR, {0}, {'a'}},
|
||||
{KM_CORE_CT_MARKER, {0}, {5}},
|
||||
{KM_CORE_CT_CHAR, {0}, {0x10100}},
|
||||
KM_CORE_CONTEXT_ITEM_END};
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_citems));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_with_markers(km_core_state_context(test_state), expected_context_items));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context_without_markers(km_core_state_app_context(test_state), expected_context_items));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -394,8 +401,8 @@ TEST_F(StateContextApiTests, TestContextClear) {
|
|||
km_core_cu const *cached_context = u"This is a test";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
ASSERT_STATUS_OK(km_core_state_context_clear(test_state));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(u""));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_different_context(km_core_state_context(test_state), cached_context));
|
||||
ASSERT_NO_FATAL_FAILURE(assert_identical_context(km_core_state_context(test_state), u""));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
|
@ -413,7 +420,7 @@ TEST_F(StateContextApiTests, TestContextDebugVarious) {
|
|||
km_core_cu const *cached_context = u"123\U0001F923";
|
||||
ASSERT_NO_FATAL_FAILURE(Initialize("k_0000___null_keyboard.kmx", cached_context));
|
||||
|
||||
km_core_context_item const citems[] = {
|
||||
km_core_context_item const expected_context_items[] = {
|
||||
{ KM_CORE_CT_MARKER, {0}, { 5 } },
|
||||
{ KM_CORE_CT_CHAR, {0}, { '1' } },
|
||||
{ KM_CORE_CT_MARKER, {0}, { 1 } },
|
||||
|
|
@ -426,7 +433,7 @@ TEST_F(StateContextApiTests, TestContextDebugVarious) {
|
|||
KM_CORE_CONTEXT_ITEM_END
|
||||
};
|
||||
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), citems));
|
||||
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), expected_context_items));
|
||||
|
||||
auto str = km_core_state_context_debug(test_state, KM_CORE_DEBUG_CONTEXT_CACHED);
|
||||
// std::cout << str << std::endl;
|
||||
|
|
|
|||
|
|
@ -77,7 +77,6 @@ void debug_items_equal(
|
|||
}
|
||||
}
|
||||
|
||||
// TODO-WEB-CORE: avoid cout; instead use google test reporting once all tests are google test
|
||||
void compare_debug_items(
|
||||
km_core_state const * state,
|
||||
std::initializer_list<km_core_state_debug_item> const & expected
|
||||
|
|
@ -86,21 +85,21 @@ void compare_debug_items(
|
|||
auto act = km_core_state_debug_items(state, &n);
|
||||
|
||||
for (auto &rhs: expected) {
|
||||
if ((int)--n < 0) {
|
||||
std::cout << "expected longer than actual" << std::endl;
|
||||
if(n == 0) {
|
||||
print_debug_item("next expected item:", rhs);
|
||||
FAIL();
|
||||
ASSERT_NE(n, 0) << "expected longer than actual";
|
||||
}
|
||||
|
||||
n--;
|
||||
|
||||
bool result;
|
||||
ASSERT_NO_FATAL_FAILURE(debug_items_equal(*act++, rhs, result));
|
||||
ASSERT_TRUE(result);
|
||||
}
|
||||
|
||||
if(n != 0) {
|
||||
std::cout << "actual longer than expected" << std::endl;
|
||||
print_debug_item("next actual item:", *act);
|
||||
FAIL();
|
||||
ASSERT_EQ(n, 0) << "actual longer than expected";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,13 +104,13 @@ TEST(KMXPlusTest, VkeysHandledCorrectly) {
|
|||
bool found = false;
|
||||
ASSERT_EQ(vk.lookup(km::tests::get_vk(
|
||||
"K_F"), 0, found), u"");
|
||||
ASSERT_EQ(found, true); // K_F found, but empty string (gap)
|
||||
ASSERT_TRUE(found); // K_F found, but empty string (gap)
|
||||
ASSERT_EQ(vk.lookup(km::tests::get_vk(
|
||||
"K_ENTER"), 0, found), u"");
|
||||
ASSERT_EQ(found, false); // K_ENTER not found, empty string
|
||||
ASSERT_FALSE(found); // K_ENTER not found, empty string
|
||||
ASSERT_EQ(vk.lookup(km::tests::get_vk(
|
||||
"K_A"), 0, found), u"K_A-0");
|
||||
ASSERT_EQ(found, true); // expect
|
||||
ASSERT_TRUE(found); // expect
|
||||
ASSERT_EQ(vk.lookup(km::tests::get_vk(
|
||||
"K_A"), LCTRLFLAG, found), u"K_A-LCTRLFLAG");
|
||||
ASSERT_EQ(vk.lookup(km::tests::get_vk(
|
||||
|
|
@ -173,13 +173,13 @@ TEST(KMXPlusTest, UsetHandledCorrectly) {
|
|||
};
|
||||
|
||||
SimpleUSet u0(&r[0], 2);
|
||||
ASSERT_EQ(u0.contains(0x62), true); // b
|
||||
ASSERT_EQ(u0.contains(0x41), false); // A
|
||||
ASSERT_EQ(u0.contains(0x127), true); // ħ
|
||||
ASSERT_TRUE(u0.contains(0x62)); // b
|
||||
ASSERT_FALSE(u0.contains(0x41)); // A
|
||||
ASSERT_TRUE(u0.contains(0x127)); // ħ
|
||||
|
||||
SimpleUSet uempty;
|
||||
ASSERT_EQ(uempty.contains(0x62), false);
|
||||
ASSERT_EQ(uempty.contains(0x127), false);
|
||||
ASSERT_FALSE(uempty.contains(0x62));
|
||||
ASSERT_FALSE(uempty.contains(0x127));
|
||||
}
|
||||
|
||||
/** tests of the COMP_KMXPLUS_STRS::valid_string() */
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
* Keyman is copyright (C) SIL International. MIT License.
|
||||
*
|
||||
* Keyman Core - Helper to load LDML keyboard test definitions
|
||||
*
|
||||
* Note that this file is superficially similar to kmx_test_source.cpp, but the
|
||||
* parsing and use diverges far enough that they cannot be easily merged.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue