feat(windows): Add unit tests for process actions

This commit is contained in:
Ross 2021-08-27 14:18:14 +10:00
parent a4801373db
commit 0663fcbeb7
5 changed files with 217 additions and 0 deletions

View file

@ -86,6 +86,7 @@ BOOL LoadlpKeyboardCore(int i)
if (_td->lpActiveKeyboard == &_td->lpKeyboards[i]) _td->lpActiveKeyboard = NULL; // I822 TSF not working
if (_td->lpKeyboards[i].lpCoreKeyboardState) {
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboardCore: a keyboard km_kbp_state exits without matching keyboard - disposing of state");
km_kbp_state_dispose(_td->lpKeyboards[i].lpCoreKeyboardState);
_td->lpKeyboards[i].lpCoreKeyboardState = NULL;
}
@ -111,6 +112,8 @@ BOOL LoadlpKeyboardCore(int i)
if (err_status != KM_KBP_STATUS_OK) {
SendDebugMessageFormat(
0, sdmLoad, 0, "LoadlpKeyboardCore: km_kbp_state_create failed with error status [%d]", err_status);
// Dispose of the keyboard to leave us in a consitent state
ReleaseKeyboardMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboard);
return FALSE;
}

View file

@ -583,6 +583,8 @@ extern "C" BOOL _declspec(dllexport) WINAPI Keyman_ForceKeyboard(PCSTR FileName
if (err_status != KM_KBP_STATUS_OK) {
SendDebugMessageFormat(
0, sdmGlobal, 0, "Keyman_ForceKeyboard Core: km_kbp_state_create failed with error status [%d]", err_status);
// Dispose of the keyboard to leave us in a consitent state
ReleaseKeyboardMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboard);
return FALSE;
}
LoadKeyboardOptionsREGCore(_td->lpActiveKeyboard, _td->lpActiveKeyboard->lpCoreKeyboardState);

View file

@ -59,6 +59,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="appinttests.cpp" />
<ClCompile Include="kmprocessactionstests.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>

View file

@ -0,0 +1,209 @@
#include "pch.h"
#include "kmprocessactions.cpp"
// Test the Process Actions private functions
// Note: The following actions are not tested KM_KBP_IT_ALERT, KM_KBP_IT_PERSIST_OPT, KM_KBP_IT_EMIT_KEYSTROKE
// KM_KBP_IT_CHAR - processUnicodeChar
TEST(AITIP, processUnicodeChartest) {
Globals_InitProcess();
WCHAR callbuf[MAXCONTEXT];
AITIP testApp;
WCHAR *expectedContext = L"A";
const km_kbp_action_item *actionItem;
km_kbp_action_item itemAddChar = {
KM_KBP_IT_CHAR,
{
0,
},
{'A'}};
processUnicodeChar(&testApp, &itemAddChar);
WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT);
EXPECT_STREQ(contextBuf, expectedContext);
km_kbp_usv testSurrogateChar = Uni_SurrogateToUTF32(0xD801, 0xDC37); //𐐷';
km_kbp_action_item itemAddChar2 = {
KM_KBP_IT_CHAR,
{
0,
},
{testSurrogateChar}};
WCHAR expectedStringSurrogate[] = {'A', 0xD801, 0xDC37, 0};
processUnicodeChar(&testApp, &itemAddChar2);
contextBuf = testApp.ContextBufMax(MAXCONTEXT);
EXPECT_STREQ(contextBuf, &expectedStringSurrogate[0]);
UninitialiseProcess(FALSE);
Globals_UninitProcess();
}
// KM_KBP_IT_MARKER - processMarker Deadkey
TEST(AITIP, processMarkertest) {
Globals_InitProcess();
WCHAR callbuf[MAXCONTEXT];
AITIP testApp;
WCHAR expectedContext[] = {UC_SENTINEL, CODE_DEADKEY, 2, 0};
const km_kbp_action_item *actionItem;
uintptr_t marker = 2;
km_kbp_action_item itemAddMarker = {
KM_KBP_IT_MARKER,
{
0,
},
{marker}};
processMarker(&testApp, &itemAddMarker);
WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT);
EXPECT_STREQ(contextBuf, expectedContext);
UninitialiseProcess(FALSE);
Globals_UninitProcess();
}
// KM_KBP_IT_BACK - processBack
// First test processing a backspace for a deadkey
TEST(AITIP, processBackDeadkeytest) {
Globals_InitProcess();
Globals_InitThread();
WCHAR callbuf[MAXCONTEXT];
AITIP testApp;
WCHAR expectedContext[] = {'A', 0};
km_kbp_action_item itemAddChar = {
KM_KBP_IT_CHAR,
{
0,
},
{'A'}};
processUnicodeChar(&testApp, &itemAddChar);
uintptr_t marker = 2;
km_kbp_action_item itemAddMarker = {
KM_KBP_IT_MARKER,
{
0,
},
{marker}};
processMarker(&testApp, &itemAddMarker);
km_kbp_action_item itemBackSpace = {KM_KBP_IT_BACK};
itemBackSpace.backspace.expected_type = KM_KBP_IT_MARKER;
itemBackSpace.backspace.expected_value = marker;
processBack(&testApp, &itemBackSpace);
WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT);
EXPECT_STREQ(contextBuf, expectedContext);
UninitialiseProcess(FALSE);
Globals_UninitProcess();
}
// KM_KBP_IT_BACK - processBack
// Press Backspace for a normal character
// Also test for Unknown Character
TEST(AITIP, processBackCharactertest) {
Globals_InitProcess();
Globals_InitThread();
WCHAR callbuf[MAXCONTEXT];
AITIP testApp;
WCHAR expectedContext[] = {'A', 0};
WCHAR expectedContextFinal[] = {0};
km_kbp_action_item itemAddChar = {
KM_KBP_IT_CHAR,
{
0,
},
{'A'}};
processUnicodeChar(&testApp, &itemAddChar);
itemAddChar.character = 'B';
processUnicodeChar(&testApp, &itemAddChar);
km_kbp_action_item itemBackSpace = {KM_KBP_IT_BACK};
itemBackSpace.backspace.expected_type = KM_KBP_IT_CHAR;
itemBackSpace.backspace.expected_value = 'B';
// backspace
processBack(&testApp, &itemBackSpace);
WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT);
EXPECT_STREQ(contextBuf, expectedContext);
// backspace for unknown it should backspace a character
itemBackSpace.type = KM_KBP_BT_UNKNOWN;
processBack(&testApp, &itemBackSpace);
contextBuf = testApp.ContextBufMax(MAXCONTEXT);
EXPECT_STREQ(contextBuf, expectedContextFinal);
UninitialiseProcess(FALSE);
Globals_UninitProcess();
}
// KM_KBP_IT_BACK - processBack
// Press Backspace for a character doesn't match expected character
// Note currently we don't check for a character match this should be updated
TEST(AITIP, processBackUnexpectedChartest) {
Globals_InitProcess();
Globals_InitThread();
WCHAR callbuf[MAXCONTEXT];
AITIP testApp;
WCHAR expectedContext[] = {'A', 0};
km_kbp_action_item itemAddChar = {
KM_KBP_IT_CHAR,
{
0,
},
{'A'}};
processUnicodeChar(&testApp, &itemAddChar);
itemAddChar.character = 'C';
processUnicodeChar(&testApp, &itemAddChar);
km_kbp_action_item itemBackSpace = {KM_KBP_IT_BACK};
itemBackSpace.backspace.expected_type = KM_KBP_IT_CHAR;
itemBackSpace.backspace.expected_value = 'B';
// backspace
processBack(&testApp, &itemBackSpace);
WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT);
EXPECT_STREQ(contextBuf, expectedContext);
UninitialiseProcess(FALSE);
Globals_UninitProcess();
}
// KM_KBP_IT_INVALIDATE_CONTEXT - processInvalidateContext
TEST(AITIP, processInvalidateContextTest) {
Globals_InitProcess();
Globals_InitThread();
WCHAR callbuf[MAXCONTEXT];
AITIP testApp;
WCHAR expectedContext[] = {0};
km_kbp_action_item itemAddChar = {
KM_KBP_IT_CHAR,
{
0,
},
{'A'}};
processUnicodeChar(&testApp, &itemAddChar);
itemAddChar.character = 'B';
processUnicodeChar(&testApp, &itemAddChar);
// A keyboard a state is need to test processInvalidateContext
km_kbp_option_item test_env_opts[] = {{u"hello", u"world", 0}, KM_KBP_OPTIONS_END};
km_kbp_keyboard *testKB = nullptr;
km_kbp_state *testState = nullptr, *test_clone = nullptr;
km_kbp_path_name dummyPath = L"dummyActions.mock";
km_kbp_status err_status = km_kbp_keyboard_load(dummyPath, &testKB);
EXPECT_EQ(km_kbp_keyboard_load(dummyPath, &testKB), KM_KBP_STATUS_OK);
EXPECT_EQ(km_kbp_state_create(testKB, test_env_opts, &testState), KM_KBP_STATUS_OK);
processInvalidateContext(&testApp,testState);
WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT);
EXPECT_STREQ(contextBuf, expectedContext);
// dispose keyboard
km_kbp_state_dispose(testState);
km_kbp_keyboard_dispose(testKB);
UninitialiseProcess(FALSE);
Globals_UninitProcess();
}

View file

@ -196,6 +196,8 @@ char* Debug_UnicodeString(PWSTR s, int x = 0);
BOOL ShouldDebug_1(); // TSDMState state);
// On failed condition it will always log "message" and return "retValue"
// it will also assert if a debugger is attached for a debug build.
#define DebugAssertRetValue(condition, message, retValue) \
{ \
if (!(condition)) { \