Merge branch 'chore/developer/ldml-test-file-reader-error-handler' into refactor/core/api-documentation
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled

This commit is contained in:
Marc Durdin 2026-05-06 21:48:55 +10:00 • committed by GitHub
commit a8888ca7c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 58 additions and 59 deletions

View file

@ -66,7 +66,7 @@ KmxTestSource::parse_source_string(std::string const &s, std::u16string& result)
std::string s1 = s.substr(p - s.begin(), 8);
v = std::stoul(s1, &n, 16);
// Allow deadkey_number (U+0001) characters and onward
if(!(v >= 0x0001 && v <= 0x10FFFF)) {
if(v < 0x0001 || v > 0x10FFFF) {
return false;
}
p += n - 1;

View file

@ -132,8 +132,6 @@ TEST_P(GetActionApiTest, TestActionsApi) {
auto data = GetParam();
ASSERT_NO_FATAL_FAILURE(Initialize(data));
// setup(initial_app_context, final_cached_context, actions_code_points_to_delete, actions_output);
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;

View file

@ -26,14 +26,14 @@ class DebugApiTests : public testing::Test {
protected:
km_core_keyboard * test_kb = nullptr;
km_core_state * test_state = nullptr;
km_core_context_item * citems = nullptr;
km_core_context_item * context_items = nullptr;
void Initialize(const char *keyboard) {
km::core::path path = km::core::path(test_dir / ".." / "kmx" / keyboard);
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(context_items_from_utf16(u"Hello 😁", &citems));
ASSERT_STATUS_OK(context_items_from_utf16(u"Hello 😁", &context_items));
// Pre-test sanity: ensure debugging is disabled
ASSERT_EQ(km_core_state_debug_get(test_state), 0);
@ -43,14 +43,14 @@ protected:
km_core_state_debug_item{KM_CORE_DEBUG_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_app_context(test_state), citems));
ASSERT_STATUS_OK(km_core_context_set(km_core_state_context(test_state), context_items));
ASSERT_STATUS_OK(km_core_context_set(km_core_state_app_context(test_state), context_items));
}
void TearDown() override {
if(citems) {
km_core_context_items_dispose(citems);
citems = nullptr;
if(context_items) {
km_core_context_items_dispose(context_items);
context_items = nullptr;
}
if(test_state) {
km_core_state_dispose(test_state);

View file

@ -16,14 +16,13 @@
#include "../helpers/core_test_helpers.h"
using namespace km::core::kmx;
/**
* This test will test the infrastructure around the external event processing
* The functions tested are:
* - km_core_event with the event KM_CORE_EVENT_KEYBOARD_ACTIVATED
*/
using namespace km::core::kmx;
TEST(ExternalEventTests, TestExternalEvent) {
km_core_keyboard * test_kb = nullptr;

View file

@ -29,6 +29,7 @@ protected:
auto blob = km::tests::load_kmx_file(path.native().c_str());
const auto mock_extension = ".mock";
if (strlen(keyboard) > strlen(mock_extension) && strcmp(keyboard + strlen(keyboard) - strlen(mock_extension), mock_extension) == 0) {
// mocked keyboard load
km::core::abstract_processor* kp = new km::core::mock_processor(keyboard);
test_kb = static_cast<km_core_keyboard*>(kp);
} else {
@ -57,24 +58,24 @@ protected:
}
}
void is_identical_context(km_core_cu const *cached_context) {
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 *new_cached_context = new km_core_cu[buf_size];
ASSERT_STATUS_OK(context_items_to_utf16(citems, new_cached_context, &buf_size));
ASSERT_EQ(std::u16string(cached_context), new_cached_context);
delete[] new_cached_context;
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 is_different_context(km_core_cu const *cached_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 *new_cached_context = new km_core_cu[buf_size];
ASSERT_STATUS_OK(context_items_to_utf16(citems, new_cached_context, &buf_size));
ASSERT_NE(std::u16string(cached_context), new_cached_context);
delete[] new_cached_context;
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;
}
};
@ -117,7 +118,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(is_identical_context(cached_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(cached_context));
}
// 1a. cached context has markers and is identical to app context
@ -145,8 +146,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(is_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(is_identical_context(new_app_context));
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
}
// 3. cached context is shorter than app context, but content is same as far as it goes
@ -155,8 +156,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(is_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(is_identical_context(new_app_context));
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
}
// 3a. cached context has markers and is shorter than app context,
@ -181,7 +182,7 @@ TEST_F(StateContextApiTests, TestContextSetIfNeededCachedContextShorterAndMarker
{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(is_identical_context(new_app_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
}
TEST_F(StateContextApiTests, TestContextSetIfNeededCachedContextShorterAndMarkersNfu) {
@ -220,8 +221,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(is_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(is_identical_context(new_app_context));
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
}
// 5. cached context is longer than app context, but content is same as far as it goes
@ -230,8 +231,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(is_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(is_identical_context(new_app_context));
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
}
// 5a. cached context has markers and is longer than app context, but
@ -294,8 +295,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(is_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(is_identical_context(new_app_context));
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
}
// 7. surrogate pairs in context
@ -304,7 +305,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(is_identical_context(new_app_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
}
TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsAppContextLonger) {
@ -312,7 +313,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(is_identical_context(new_app_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
}
TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsCachedContextLonger) {
@ -320,7 +321,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(is_identical_context(new_app_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(new_app_context));
}
TEST_F(StateContextApiTests, TestContextSetIfNeededSurrogatePairsUnchangedAndMarkers) {
@ -393,8 +394,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(is_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(is_identical_context(u""));
ASSERT_NO_FATAL_FAILURE(assert_different_context(cached_context));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(u""));
}
//-------------------------------------------------------------------------------------

View file

@ -64,7 +64,7 @@ bool action_items(
}
}
if(n != 0) {
if(n > 0) {
std::cout << "actual longer than expected" << std::endl;
km::tests::print_action_item("next actual item:", *act);
return false;

View file

@ -20,6 +20,7 @@ main(int argc, char **argv) {
#ifdef __EMSCRIPTEN__
if(!get_wasm_file_path(km::core::path(argv[0]).parent(), test_dir)) {
// not a fully qualified path
std::cout << "Error: argv[0] did not give a fully qualified path!" << std::endl;
return 1;
}
#else

View file

@ -51,22 +51,22 @@ protected:
km_core_cu_dispose(context);
}
void is_identical_context(km_core_cu const *cached_context, km_core_debug_context_type context_type) {
void assert_identical_context(km_core_cu const *cached_context, km_core_debug_context_type context_type) {
size_t buf_size;
km_core_context_item * citems = nullptr;
km_core_context_item * context_items = nullptr;
debug_context(context_type);
if(context_type == KM_CORE_DEBUG_CONTEXT_APP) {
ASSERT_STATUS_OK(km_core_context_get(km_core_state_app_context(test_state), &citems));
ASSERT_STATUS_OK(km_core_context_get(km_core_state_app_context(test_state), &context_items));
} else {
ASSERT_STATUS_OK(km_core_context_get(km_core_state_context(test_state), &citems));
ASSERT_STATUS_OK(km_core_context_get(km_core_state_context(test_state), &context_items));
}
ASSERT_STATUS_OK(context_items_to_utf16(citems, nullptr, &buf_size));
ASSERT_STATUS_OK(context_items_to_utf16(context_items, nullptr, &buf_size));
km_core_cu* new_cached_context = new km_core_cu[buf_size];
ASSERT_STATUS_OK(context_items_to_utf16(citems, new_cached_context, &buf_size));
ASSERT_STATUS_OK(context_items_to_utf16(context_items, new_cached_context, &buf_size));
km_core_context_items_dispose(citems);
km_core_context_items_dispose(context_items);
ASSERT_EQ(std::u16string(cached_context), new_cached_context);
delete[] new_cached_context;
@ -77,8 +77,8 @@ TEST_F(ContextNormalizationTests, TestContextNormalizationAlreadyNfd) {
km_core_cu const *app_context_nfd = u"A\u0300";
ASSERT_NO_FATAL_FAILURE(Initialize("k_001_tiny.kmx"));
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, app_context_nfd), KM_CORE_CONTEXT_STATUS_UPDATED);
ASSERT_NO_FATAL_FAILURE(is_identical_context(app_context_nfd, KM_CORE_DEBUG_CONTEXT_APP));
ASSERT_NO_FATAL_FAILURE(is_identical_context(app_context_nfd, KM_CORE_DEBUG_CONTEXT_CACHED));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(app_context_nfd, KM_CORE_DEBUG_CONTEXT_APP));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(app_context_nfd, KM_CORE_DEBUG_CONTEXT_CACHED));
}
TEST_F(ContextNormalizationTests, TestContextNormalizationBasic) {
@ -86,8 +86,8 @@ TEST_F(ContextNormalizationTests, TestContextNormalizationBasic) {
km_core_cu const *cached_context = u"This is a test A\u0300";
ASSERT_NO_FATAL_FAILURE(Initialize("k_001_tiny.kmx"));
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, application_context), KM_CORE_CONTEXT_STATUS_UPDATED);
ASSERT_NO_FATAL_FAILURE(is_identical_context(application_context, KM_CORE_DEBUG_CONTEXT_APP));
ASSERT_NO_FATAL_FAILURE(is_identical_context(cached_context, KM_CORE_DEBUG_CONTEXT_CACHED));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(application_context, KM_CORE_DEBUG_CONTEXT_APP));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(cached_context, KM_CORE_DEBUG_CONTEXT_CACHED));
}
TEST_F(ContextNormalizationTests, TestContextNormalizationHefty) {
@ -96,8 +96,8 @@ TEST_F(ContextNormalizationTests, TestContextNormalizationHefty) {
km_core_cu const *cached_context = u"A\u0300" u"e\u0316\u0301" u"\u0073\u0323\u0307" u"\u0041\u030a" u"\U000114B9\U000114B0";
ASSERT_NO_FATAL_FAILURE(Initialize("k_001_tiny.kmx"));
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, application_context), KM_CORE_CONTEXT_STATUS_UPDATED);
ASSERT_NO_FATAL_FAILURE(is_identical_context(application_context, KM_CORE_DEBUG_CONTEXT_APP));
ASSERT_NO_FATAL_FAILURE(is_identical_context(cached_context, KM_CORE_DEBUG_CONTEXT_CACHED));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(application_context, KM_CORE_DEBUG_CONTEXT_APP));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(cached_context, KM_CORE_DEBUG_CONTEXT_CACHED));
}
@ -110,8 +110,8 @@ TEST_F(ContextNormalizationTests, TestContextNormalizationInvalidUnicode) {
km_core_cu const cached_context[] = { 0xDC01, 0x0020, 0x0020, 0xFFFF, 0x0000 };
ASSERT_NO_FATAL_FAILURE(Initialize("k_001_tiny.kmx"));
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, application_context), KM_CORE_CONTEXT_STATUS_UPDATED);
ASSERT_NO_FATAL_FAILURE(is_identical_context(application_context, KM_CORE_DEBUG_CONTEXT_APP));
ASSERT_NO_FATAL_FAILURE(is_identical_context(cached_context, KM_CORE_DEBUG_CONTEXT_CACHED));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(application_context, KM_CORE_DEBUG_CONTEXT_APP));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(cached_context, KM_CORE_DEBUG_CONTEXT_CACHED));
}
TEST_F(ContextNormalizationTests, TestContextNormalizationLoneTrailingSurrogate) {
@ -120,6 +120,6 @@ TEST_F(ContextNormalizationTests, TestContextNormalizationLoneTrailingSurrogate)
km_core_cu const cached_context[] = /* skipped*/ { 0x0020, 0x0020, 0x0000 };
ASSERT_NO_FATAL_FAILURE(Initialize("k_001_tiny.kmx"));
ASSERT_EQ(km_core_state_context_set_if_needed(test_state, application_context), KM_CORE_CONTEXT_STATUS_UPDATED);
ASSERT_NO_FATAL_FAILURE(is_identical_context(application_context+1, KM_CORE_DEBUG_CONTEXT_APP)); // first code unit is skipped
ASSERT_NO_FATAL_FAILURE(is_identical_context(cached_context, KM_CORE_DEBUG_CONTEXT_CACHED));
ASSERT_NO_FATAL_FAILURE(assert_identical_context(application_context+1, KM_CORE_DEBUG_CONTEXT_APP)); // first code unit is skipped
ASSERT_NO_FATAL_FAILURE(assert_identical_context(cached_context, KM_CORE_DEBUG_CONTEXT_CACHED));
}

View file

@ -86,4 +86,4 @@ builder_run_action configure do_configure
builder_run_action build do_build
builder_run_action build-fixtures do_build_fixtures
builder_run_action api api-extractor run --local --verbose
builder_run_action test typescript_run_eslint_mocha_tests 90
builder_run_action test typescript_run_eslint_mocha_tests 85