mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-30 12:17:41 +00:00
The compiler has always been very ambiguous on which characters were accepted in group and store names, even to the point of accepting things like comma in a store name, which would then make it impossible to reference in an `index` statement! This commit clarifies the allowable characters in an identifier. While it would have been possible to use UAX#31 for this, that would have extended the requirements for this change substantially, and may have caused us more trouble with legacy keyboards. Given kmcmplib is end-of-life (see epic/ng-compiler), I have chosen a lower friction approach. There are certainly other characters that could be excluded, but in general I have chosen to exclude only those that will definitely be problematic. The set of allowable characters for deadkeys has actually been expanded in this release to match the store and group name rules. It is expected that there may be some impacted keyboards, but addressing this change will be relatively straightforward, so I consider this to be an acceptable back-compatibility trade-off, see https://github.com/keymanapp/keyman/wiki/Principles-of-Keyman-Code-Changes#4-source-backward-compatibility-keyboard-model-and-package-source-file-formats-should-be-backward-compatible Fixes: #14604 Test-bot: skip Build-bot: skip build:developer
2266 lines
101 KiB
C++
2266 lines
101 KiB
C++
#include <gtest/gtest.h>
|
|
#include <km_u16.h>
|
|
#include "../include/kmcompx.h"
|
|
#include "../include/kmcmplibapi.h"
|
|
#include "../src/compfile.h"
|
|
#include "../src/CompilerErrors.h"
|
|
#include "../src/virtualcharkeys.h"
|
|
#include "../../common/include/kmn_compiler_errors.h"
|
|
#include "../../../../common/include/km_types.h"
|
|
#include "../../../../common/include/kmx_file.h"
|
|
|
|
PKMX_WCHAR strtowstr(PKMX_STR in);
|
|
PKMX_STR wstrtostr(PKMX_WCHAR in);
|
|
KMX_BOOL ProcessBeginLine(PFILE_KEYBOARD fk, PKMX_WCHAR p);
|
|
KMX_DWORD ValidateMatchNomatchOutput(PKMX_WCHAR p);
|
|
KMX_BOOL IsValidKeyboardVersion(KMX_WCHAR *dpString);
|
|
PKMX_WCHAR GetDelimitedString(PKMX_WCHAR *p, KMX_WCHAR const * Delimiters, KMX_WORD Flags);
|
|
int LineTokenType(PKMX_WCHAR *str);
|
|
KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_WCHAR const * token,
|
|
PKMX_WCHAR output, int max, int offset, PKMX_WCHAR *newp, int isUnicode
|
|
);
|
|
KMX_DWORD ProcessEthnologueStore(PKMX_WCHAR p);
|
|
KMX_DWORD GetRHS(PFILE_KEYBOARD fk, PKMX_WCHAR p, PKMX_WCHAR buf, int bufsize, int offset, int IsUnicode);
|
|
bool isIntegerWstring(PKMX_WCHAR p);
|
|
bool hasPreamble(std::u16string result);
|
|
KMX_DWORD ProcessKeyLineImpl(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_BOOL IsUnicode, PKMX_WCHAR pklIn, PKMX_WCHAR pklKey, PKMX_WCHAR pklOut);
|
|
extern bool UTF16TempFromUTF8(KMX_BYTE* infile, int sz, KMX_BYTE** tempfile, int* sz16);
|
|
extern bool isValidUtf8(KMX_BYTE* str, int sz);
|
|
|
|
namespace kmcmp {
|
|
extern int nErrors;
|
|
extern int currentLine;
|
|
extern int ErrChr;
|
|
extern std::string messageFilename;
|
|
extern int BeginLine[4];
|
|
extern int CompileTarget;
|
|
extern KMX_BOOL FMnemonicLayout;
|
|
}
|
|
|
|
class CompilerTest : public testing::Test {
|
|
protected:
|
|
FILE_KEYBOARD fileKeyboard;
|
|
|
|
CompilerTest() {}
|
|
~CompilerTest() override {}
|
|
void SetUp() override {
|
|
initGlobals();
|
|
initFileKeyboard(fileKeyboard);
|
|
}
|
|
void TearDown() override {
|
|
deleteFileKeyboard(fileKeyboard);
|
|
}
|
|
|
|
void initGlobals() {
|
|
kmcmp::msgproc = msgproc_collect;
|
|
msgproc_errors.clear();
|
|
kmcmp::nErrors = 0;
|
|
kmcmp::currentLine = 0;
|
|
kmcmp::ErrChr = 0;
|
|
kmcmp::messageFilename = "";
|
|
kmcmp::BeginLine[BEGIN_ANSI] = -1;
|
|
kmcmp::BeginLine[BEGIN_UNICODE] = -1;
|
|
kmcmp::BeginLine[BEGIN_NEWCONTEXT] = -1;
|
|
kmcmp::BeginLine[BEGIN_POSTKEYSTROKE] = -1;
|
|
kmcmp::CompileTarget = CKF_KEYMAN;
|
|
kmcmp::FMnemonicLayout = FALSE;
|
|
}
|
|
|
|
void initFileKeyboard(FILE_KEYBOARD &fk) {
|
|
fk.KeyboardID = 0;
|
|
fk.version = VERSION_90;
|
|
fk.dpStoreArray = nullptr;
|
|
fk.dpGroupArray = nullptr;
|
|
fk.cxStoreArray = 0;
|
|
fk.cxGroupArray = 0;
|
|
fk.StartGroup[0] = 0;
|
|
fk.StartGroup[1] = 0;
|
|
fk.dwHotKey = 0;
|
|
fk.szName[0] = u'\0';
|
|
fk.szLanguageName[0] = u'\0';
|
|
fk.szCopyright[0] = u'\0';
|
|
fk.szMessage[0] = u'\0';
|
|
fk.lpBitmap = nullptr;
|
|
fk.dwBitmapSize = 0;
|
|
fk.dwFlags = 0;
|
|
fk.currentGroup = 0;
|
|
fk.currentStore = 0;
|
|
fk.cxDeadKeyArray = 0;
|
|
fk.dpDeadKeyArray = nullptr;
|
|
fk.cxVKDictionary = 0;
|
|
fk.dpVKDictionary = nullptr;
|
|
fk.extra = nullptr;
|
|
}
|
|
|
|
void initFileStoreArray(FILE_KEYBOARD &fk, std::vector<const KMX_WCHAR*> names) {
|
|
fk.dpStoreArray = new FILE_STORE[100];
|
|
fk.cxStoreArray = names.size();
|
|
|
|
for (KMX_DWORD i=0; i<fk.cxStoreArray; i++) {
|
|
fk.dpStoreArray[i].dwSystemID = 0;
|
|
u16cpy(fk.dpStoreArray[i].szName, names[i]);
|
|
fk.dpStoreArray[i].dpString = nullptr;
|
|
fk.dpStoreArray[i].fIsStore = FALSE;
|
|
fk.dpStoreArray[i].fIsReserved = FALSE;
|
|
fk.dpStoreArray[i].fIsOption = FALSE;
|
|
fk.dpStoreArray[i].fIsDebug = FALSE;
|
|
fk.dpStoreArray[i].fIsCall = FALSE;
|
|
}
|
|
}
|
|
|
|
void initFileGroupArray(FILE_KEYBOARD &fk, std::vector<const KMX_WCHAR*> names) {
|
|
fk.dpGroupArray = new FILE_GROUP[100];
|
|
fk.cxGroupArray = names.size();
|
|
|
|
for (KMX_DWORD i=0; i<fk.cxGroupArray; i++) {
|
|
u16cpy(fk.dpGroupArray[i].szName, names[i]);
|
|
fk.dpGroupArray[i].cxKeyArray = 0;
|
|
fk.dpGroupArray[i].dpKeyArray = nullptr;
|
|
fk.dpGroupArray[i].dpMatch = nullptr;
|
|
fk.dpGroupArray[i].dpNoMatch = nullptr;
|
|
fk.dpGroupArray[i].fUsingKeys = FALSE;
|
|
fk.dpGroupArray[i].fReadOnly = FALSE;
|
|
fk.dpGroupArray[i].Line = 0;
|
|
}
|
|
}
|
|
|
|
void initVKDictionary(FILE_KEYBOARD &fk, std::vector<const KMX_WCHAR*> names) {
|
|
fk.dpVKDictionary = new FILE_VKDICTIONARY[10];
|
|
fk.cxVKDictionary = names.size();
|
|
|
|
for (KMX_DWORD i=0; i<fk.cxVKDictionary; i++) {
|
|
u16cpy(fk.dpVKDictionary[i].szName, names[i]);
|
|
}
|
|
}
|
|
|
|
void deleteFileKeyboard(FILE_KEYBOARD &fk) {
|
|
if (fk.dpStoreArray) { delete[] fk.dpStoreArray; }
|
|
if (fk.dpGroupArray) { delete[] fk.dpGroupArray; }
|
|
if (fk.lpBitmap) { delete fk.lpBitmap; }
|
|
if (fk.dpDeadKeyArray) { delete[] fk.dpDeadKeyArray; }
|
|
if (fk.dpVKDictionary) { delete fk.dpVKDictionary; }
|
|
if (fk.extra) { delete fk.extra; }
|
|
}
|
|
|
|
public:
|
|
static std::vector<KMCMP_COMPILER_RESULT_MESSAGE> msgproc_errors;
|
|
|
|
static void msgproc_collect(const KMCMP_COMPILER_RESULT_MESSAGE &message, void* context) {
|
|
msgproc_errors.push_back(message);
|
|
}
|
|
};
|
|
|
|
std::vector<KMCMP_COMPILER_RESULT_MESSAGE> CompilerTest::msgproc_errors;
|
|
|
|
TEST_F(CompilerTest, strtowstr_test) {
|
|
EXPECT_EQ(0, u16cmp(u"hello", strtowstr((PKMX_STR)"hello")));
|
|
EXPECT_EQ(0, u16cmp(u"", strtowstr((PKMX_STR)"")));
|
|
};
|
|
|
|
TEST_F(CompilerTest, wstrtostr_test) {
|
|
EXPECT_EQ(0, strcmp("hello", wstrtostr((PKMX_WCHAR)u"hello")));
|
|
EXPECT_EQ(0, strcmp("", wstrtostr((PKMX_WCHAR)u"")));
|
|
};
|
|
|
|
TEST_F(CompilerTest, ReportCompilerMessage_test) {
|
|
kmcmp::msgproc = msgproc_collect;
|
|
kmcmp::currentLine = 42;
|
|
std::vector<std::string> params{"parameter"};
|
|
kmcmp::messageFilename = "filename";
|
|
kmcmp::ErrChr = 0;
|
|
|
|
// SevFatal
|
|
EXPECT_EQ(0, kmcmp::nErrors);
|
|
EXPECT_EQ(SevFatal, KmnCompilerMessages::FATAL_CannotCreateTempfile & SevFatal);
|
|
ReportCompilerMessage(KmnCompilerMessages::FATAL_CannotCreateTempfile, params);
|
|
EXPECT_EQ(1, kmcmp::nErrors);
|
|
EXPECT_EQ(KmnCompilerMessages::FATAL_CannotCreateTempfile, msgproc_errors[0].errorCode);
|
|
EXPECT_EQ(kmcmp::currentLine, msgproc_errors[0].lineNumber);
|
|
EXPECT_EQ(kmcmp::ErrChr, msgproc_errors[0].columnNumber);
|
|
EXPECT_TRUE(msgproc_errors[0].filename == kmcmp::messageFilename);
|
|
EXPECT_TRUE(msgproc_errors[0].parameters == params);
|
|
|
|
// SevError
|
|
EXPECT_EQ(SevError, KmnCompilerMessages::ERROR_InvalidLayoutLine & SevError);
|
|
ReportCompilerMessage(KmnCompilerMessages::ERROR_InvalidLayoutLine);
|
|
EXPECT_EQ(2, kmcmp::nErrors);
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidLayoutLine, msgproc_errors[1].errorCode);
|
|
|
|
// SevWarn
|
|
EXPECT_EQ(SevWarn, KmnCompilerMessages::WARN_ReservedCharacter & SevWarn);
|
|
ReportCompilerMessage(KmnCompilerMessages::WARN_ReservedCharacter);
|
|
EXPECT_EQ(2, kmcmp::nErrors);
|
|
EXPECT_EQ(KmnCompilerMessages::WARN_ReservedCharacter, msgproc_errors[2].errorCode);
|
|
|
|
// SevHint
|
|
EXPECT_EQ(SevHint, KmnCompilerMessages::HINT_NonUnicodeFile & SevHint);
|
|
ReportCompilerMessage(KmnCompilerMessages::HINT_NonUnicodeFile);
|
|
EXPECT_EQ(2, kmcmp::nErrors);
|
|
EXPECT_EQ(KmnCompilerMessages::HINT_NonUnicodeFile, msgproc_errors[3].errorCode);
|
|
|
|
// SevInfo
|
|
EXPECT_EQ(SevInfo, KmnCompilerMessages::INFO_MinimumCoreEngineVersion & SevInfo);
|
|
ReportCompilerMessage(KmnCompilerMessages::INFO_MinimumCoreEngineVersion);
|
|
EXPECT_EQ(2, kmcmp::nErrors);
|
|
EXPECT_EQ(KmnCompilerMessages::INFO_MinimumCoreEngineVersion, msgproc_errors[4].errorCode);
|
|
};
|
|
|
|
TEST_F(CompilerTest, ProcessBeginLine_test) {
|
|
KMX_WCHAR str[LINESIZE];
|
|
|
|
// KmnCompilerMessages::ERROR_NoTokensFound
|
|
msgproc_errors.clear();
|
|
u16cpy(str, u"");
|
|
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
|
EXPECT_EQ(1, msgproc_errors.size());
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, msgproc_errors[0].errorCode);
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidToken
|
|
msgproc_errors.clear();
|
|
u16cpy(str, u"abc >");
|
|
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
|
EXPECT_EQ(1, msgproc_errors.size());
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, msgproc_errors[0].errorCode);
|
|
|
|
// KmnCompilerMessages::ERROR_RepeatedBegin, BEGIN_UNICODE
|
|
msgproc_errors.clear();
|
|
kmcmp::BeginLine[BEGIN_UNICODE] = 0; // not -1
|
|
u16cpy(str, u" unicode>");
|
|
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
|
EXPECT_EQ(1, msgproc_errors.size());
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_RepeatedBegin, msgproc_errors[0].errorCode);
|
|
kmcmp::BeginLine[BEGIN_UNICODE] = -1;
|
|
|
|
// KmnCompilerMessages::ERROR_RepeatedBegin, BEGIN_ANSI
|
|
msgproc_errors.clear();
|
|
kmcmp::BeginLine[BEGIN_ANSI] = 0; // not -1
|
|
u16cpy(str, u" ansi>");
|
|
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
|
EXPECT_EQ(1, msgproc_errors.size());
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_RepeatedBegin, msgproc_errors[0].errorCode);
|
|
kmcmp::BeginLine[BEGIN_ANSI] = -1;
|
|
|
|
// KmnCompilerMessages::ERROR_RepeatedBegin, BEGIN_NEWCONTEXT
|
|
msgproc_errors.clear();
|
|
kmcmp::BeginLine[BEGIN_NEWCONTEXT] = 0; // not -1
|
|
u16cpy(str, u" newContext>");
|
|
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
|
EXPECT_EQ(1, msgproc_errors.size());
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_RepeatedBegin, msgproc_errors[0].errorCode);
|
|
kmcmp::BeginLine[BEGIN_NEWCONTEXT] = -1;
|
|
|
|
// KmnCompilerMessages::ERROR_RepeatedBegin, BEGIN_POSTKEYSTROKE
|
|
msgproc_errors.clear();
|
|
kmcmp::BeginLine[BEGIN_POSTKEYSTROKE] = 0; // not -1
|
|
u16cpy(str, u" postKeystroke>");
|
|
EXPECT_EQ(FALSE, ProcessBeginLine(&fileKeyboard, str));
|
|
EXPECT_EQ(1, msgproc_errors.size());
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_RepeatedBegin, msgproc_errors[0].errorCode);
|
|
kmcmp::BeginLine[BEGIN_POSTKEYSTROKE] = -1;
|
|
};
|
|
|
|
TEST_F(CompilerTest, ValidateMatchNomatchOutput_test) {
|
|
EXPECT_EQ(STATUS_Success, ValidateMatchNomatchOutput(NULL));
|
|
EXPECT_EQ(STATUS_Success, ValidateMatchNomatchOutput((PKMX_WCHAR)u""));
|
|
const KMX_WCHAR context[] = { 'a', 'b', 'c', UC_SENTINEL, CODE_CONTEXT, 'd', 'e', 'f', 0 };
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_ContextAndIndexInvalidInMatchNomatch, ValidateMatchNomatchOutput((PKMX_WCHAR)context));
|
|
const KMX_WCHAR contextex[] = { 'a', 'b', 'c', UC_SENTINEL, CODE_CONTEXTEX, 'd', 'e', 'f', 0 };
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_ContextAndIndexInvalidInMatchNomatch, ValidateMatchNomatchOutput((PKMX_WCHAR)contextex));
|
|
const KMX_WCHAR index[] = { 'a', 'b', 'c', UC_SENTINEL, CODE_INDEX, 'd', 'e', 'f', 0 };
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_ContextAndIndexInvalidInMatchNomatch, ValidateMatchNomatchOutput((PKMX_WCHAR)index));
|
|
const KMX_WCHAR sentinel[] = { 'a', 'b', 'c', UC_SENTINEL, 'd', 'e', 'f', 0 };
|
|
EXPECT_EQ(STATUS_Success, ValidateMatchNomatchOutput((PKMX_WCHAR)sentinel));
|
|
};
|
|
|
|
// KMX_BOOL ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str)
|
|
// KMX_BOOL ProcessGroupLine(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
|
// int kmcmp::cmpkeys(const void *key, const void *elem)
|
|
// KMX_BOOL ProcessGroupFinish(PFILE_KEYBOARD fk)
|
|
// KMX_BOOL ProcessStoreLine(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
|
// bool resizeStoreArray(PFILE_KEYBOARD fk)
|
|
// bool resizeKeyArray(PFILE_GROUP gp, int increment)
|
|
// KMX_BOOL AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, const KMX_WCHAR * str, KMX_DWORD *dwStoreID)
|
|
// KMX_DWORD AddDebugStore(PFILE_KEYBOARD fk, KMX_WCHAR const * str)
|
|
// KMX_BOOL ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE sp)
|
|
// int GetCompileTargetsFromTargetsStore(const KMX_WCHAR* store)
|
|
|
|
TEST_F(CompilerTest, IsValidKeyboardVersion_test) {
|
|
EXPECT_FALSE(IsValidKeyboardVersion((KMX_WCHAR *)u""));
|
|
EXPECT_FALSE(IsValidKeyboardVersion((KMX_WCHAR *)u" "));
|
|
EXPECT_FALSE(IsValidKeyboardVersion((KMX_WCHAR *)u"\t"));
|
|
EXPECT_FALSE(IsValidKeyboardVersion((KMX_WCHAR *)u" 1.1"));
|
|
EXPECT_TRUE(IsValidKeyboardVersion((KMX_WCHAR *)u"1.1"));
|
|
EXPECT_TRUE(IsValidKeyboardVersion((KMX_WCHAR *)u"1.0"));
|
|
EXPECT_FALSE(IsValidKeyboardVersion((KMX_WCHAR *)u"1."));
|
|
EXPECT_TRUE(IsValidKeyboardVersion((KMX_WCHAR *)u"1.2.3"));
|
|
EXPECT_FALSE(IsValidKeyboardVersion((KMX_WCHAR *)u"a"));
|
|
EXPECT_FALSE(IsValidKeyboardVersion((KMX_WCHAR *)u"1.a"));
|
|
};
|
|
|
|
// KMX_DWORD kmcmp::AddCompilerVersionStore(PFILE_KEYBOARD fk)
|
|
// KMX_DWORD CheckStatementOffsets(PFILE_KEYBOARD fk, PFILE_GROUP gp, PKMX_WCHAR context, PKMX_WCHAR output, PKMX_WCHAR key)
|
|
// void CheckContextStatementPositions(PKMX_WCHAR context)
|
|
// KMX_DWORD CheckUseStatementsInOutput(PKMX_WCHAR output)
|
|
// KMX_DWORD CheckVirtualKeysInOutput(PKMX_WCHAR output)
|
|
// KMX_DWORD InjectContextToReadonlyOutput(PKMX_WCHAR pklOut)
|
|
// KMX_DWORD CheckOutputIsReadonly(const PFILE_KEYBOARD fk, const PKMX_WCHAR output)
|
|
// KMX_DWORD ProcessKeyLine(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_BOOL IsUnicode)
|
|
|
|
TEST_F(CompilerTest, ProcessKeyLineImpl_test) {
|
|
initFileGroupArray(fileKeyboard, {u"a"});
|
|
fileKeyboard.dpGroupArray[0].fUsingKeys = TRUE;
|
|
|
|
PKMX_WCHAR pklIn, pklKey, pklOut;
|
|
KMX_WCHAR str[128];
|
|
|
|
pklIn = new KMX_WCHAR[GLOBAL_BUFSIZE];
|
|
pklKey = new KMX_WCHAR[GLOBAL_BUFSIZE];
|
|
pklOut = new KMX_WCHAR[GLOBAL_BUFSIZE];
|
|
|
|
// #11643: non-BMP characters do not makes sense for key codes
|
|
u16cpy(str, u"+ 'A' > 'test'\n"); // baseline
|
|
EXPECT_EQ(STATUS_Success, ProcessKeyLineImpl(&fileKeyboard, str, TRUE, pklIn, pklKey, pklOut));
|
|
|
|
u16cpy(str, u"+ '\U00010000' > 'test'\n"); // surrogate pair
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_NonBMPCharactersNotSupportedInKeySection, ProcessKeyLineImpl(&fileKeyboard, str, TRUE, pklIn, pklKey, pklOut));
|
|
|
|
delete[] pklIn;
|
|
delete[] pklKey;
|
|
delete[] pklOut;
|
|
|
|
// TODO: other tests for this function
|
|
|
|
}
|
|
|
|
// KMX_DWORD ExpandKp_ReplaceIndex(PFILE_KEYBOARD fk, PFILE_KEY k, KMX_DWORD keyIndex, int nAnyIndex)
|
|
// KMX_DWORD ExpandKp(PFILE_KEYBOARD fk, PFILE_KEY kpp, KMX_DWORD storeIndex)
|
|
|
|
TEST_F(CompilerTest, GetDelimitedString_test) {
|
|
KMX_WCHAR str[LINESIZE];
|
|
PKMX_WCHAR p = str;
|
|
PKMX_WCHAR q = nullptr;
|
|
|
|
// no open delimiter, cut spaces after open and before close delimiter
|
|
u16cpy(str, u"");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_FALSE(q);
|
|
|
|
// no close delimiter, cut spaces after open and before close delimiter
|
|
u16cpy(str, u"(");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_FALSE(q);
|
|
|
|
// no argument, cut spaces after open and before close delimiter
|
|
u16cpy(str, u"()");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(1, p-str); // deleted close delimiter
|
|
|
|
// no argument, single space, no flags
|
|
u16cpy(str, u"( )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", 0x00);
|
|
EXPECT_EQ(0, u16cmp(u" ", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(2, p-str); // deleted close delimiter
|
|
|
|
// no argument, single space, cut spaces after open delimiter
|
|
u16cpy(str, u"( )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD);
|
|
EXPECT_EQ(0, u16cmp(u"", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(2, p-str); // deleted close delimiter
|
|
|
|
// no argument, single space, cut spaces before close delimiter
|
|
u16cpy(str, u"( )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(2, p-str); // deleted close delimiter
|
|
|
|
// no argument, single space, cut spaces after open and before close delimiter
|
|
u16cpy(str, u"( )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(2, p-str); // deleted close delimiter
|
|
|
|
// no argument, two spaces, no flags
|
|
u16cpy(str, u"( )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", 0x00);
|
|
EXPECT_EQ(0, u16cmp(u" ", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(3, p-str); // deleted close delimiter
|
|
|
|
// no argument, two spaces, cut spaces after open delimiter
|
|
u16cpy(str, u"( )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD);
|
|
EXPECT_EQ(0, u16cmp(u"", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(3, p-str); // deleted close delimiter
|
|
|
|
// no argument, two spaces, cut spaces before close delimiter
|
|
u16cpy(str, u"( )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(3, p-str); // deleted close delimiter
|
|
|
|
// no argument, two spaces, cut spaces after open and before close delimiter
|
|
u16cpy(str, u"( )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(3, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"(b)");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(2, p-str); // deleted close delimiter
|
|
|
|
// multi-character argument, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"(abc)");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"abc", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(4, p-str); // deleted close delimiter
|
|
|
|
// multi-word argument, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"(abc def)");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"abc def", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(8, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, leading single space, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u" (b)");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(3, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, leading double space, cut open and close delimiter, valid
|
|
u16cpy(str, u" (b)");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(4, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, space before argument, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"( b)");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(3, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, space before argument, no flags, valid
|
|
u16cpy(str, u"( b)");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", 0x00);
|
|
EXPECT_EQ(0, u16cmp(u" b", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(3, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, double space before argument, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"( b)");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(4, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, double space before argument, no flags, valid
|
|
u16cpy(str, u"( b)");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", 0x00);
|
|
EXPECT_EQ(0, u16cmp(u" b", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(4, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, space after argument, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"(b )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(3, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, space after argument, no flags, valid
|
|
u16cpy(str, u"(b )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", 0x00);
|
|
EXPECT_EQ(0, u16cmp(u"b ", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(3, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, two spaces after argument, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"(b )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(4, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, two spaces after argument, no flags, valid
|
|
u16cpy(str, u"(b )");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", 0x00);
|
|
EXPECT_EQ(0, u16cmp(u"b ", q));
|
|
EXPECT_FALSE(*p);
|
|
EXPECT_EQ(4, p-str); // deleted close delimiter
|
|
|
|
// single-character argument, space after close delimiter, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"(b) ");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_EQ(' ', *p);
|
|
EXPECT_EQ(3, p-str); // space after the close delimiter
|
|
|
|
// single-character argument, two spaces after close delimiter, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"(b) ");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_EQ(' ', *p);
|
|
EXPECT_EQ(4, p-str); // last space after the close delimiter
|
|
|
|
// single-character argument, two spaces after argument and two spaces after close delimiter,
|
|
// cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"(b ) ");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_EQ(' ', *p);
|
|
EXPECT_EQ(6, p-str); // last space after the close delimiter
|
|
|
|
// single-character argument, two spaces after argument and two spaces after close delimiter, no flags, valid
|
|
u16cpy(str, u"(b ) ");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", 0x00);
|
|
EXPECT_EQ(0, u16cmp(u"b ", q));
|
|
EXPECT_EQ(' ', *p);
|
|
EXPECT_EQ(6, p-str); // last space after the close delimiter
|
|
|
|
// single-character argument, two spaces and text after close delimiter, cut spaces after open and before close delimiter, valid
|
|
u16cpy(str, u"(b) def");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_EQ('d', *p);
|
|
EXPECT_EQ(5, p-str); // first text character after the close delimiter
|
|
|
|
// single-character argument, two spaces and text after close delimiter, no flags, valid
|
|
u16cpy(str, u"(b) def");
|
|
p = str;
|
|
q = GetDelimitedString(&p, u"()", 0x00);
|
|
EXPECT_EQ(0, u16cmp(u"b", q));
|
|
EXPECT_EQ('d', *p);
|
|
EXPECT_EQ(5, p-str); // first text character after the close delimiter
|
|
}
|
|
|
|
// LinePrefixType GetLinePrefixType(PKMX_WCHAR *p)
|
|
|
|
TEST_F(CompilerTest, LineTokenType_test) {
|
|
KMX_WCHAR str[LINESIZE];
|
|
PKMX_WCHAR p = nullptr;
|
|
|
|
// T_BLANK, lptOther, empty string
|
|
u16cpy(str, u"");
|
|
p = str;
|
|
EXPECT_EQ(T_BLANK, LineTokenType(&p));
|
|
|
|
// T_BLANK, lptOther, one space
|
|
u16cpy(str, u" ");
|
|
p = str;
|
|
EXPECT_EQ(T_BLANK, LineTokenType(&p));
|
|
|
|
// T_BLANK, mismatched prefix, CKF_KEYMAN, lptKeymanWebOnly
|
|
u16cpy(str, u"$keymanweb:");
|
|
p = str;
|
|
kmcmp::CompileTarget = CKF_KEYMAN;
|
|
EXPECT_EQ(T_BLANK, LineTokenType(&p));
|
|
|
|
// T_BLANK, mismatched prefix, CKF_KEYMANWEB, lptKeymanOnly
|
|
u16cpy(str, u"$keymanonly:");
|
|
p = str;
|
|
kmcmp::CompileTarget = CKF_KEYMANWEB;
|
|
EXPECT_EQ(T_BLANK, LineTokenType(&p));
|
|
|
|
// T_BLANK, nothing after prefix
|
|
u16cpy(str, u"$keyman:");
|
|
p = str;
|
|
kmcmp::CompileTarget = CKF_KEYMAN;
|
|
EXPECT_EQ(T_BLANK, LineTokenType(&p));
|
|
|
|
// T_STORE (=T_W_START)
|
|
u16cpy(str, u"store(b)");
|
|
p = str;
|
|
EXPECT_EQ(T_STORE, LineTokenType(&p));
|
|
EXPECT_EQ(u16len(u"store"), p - str);
|
|
EXPECT_TRUE(!u16cmp(p, u"(b)"));
|
|
|
|
// T_BITMAPS (=T_W_END)
|
|
u16cpy(str, u"bitmaps \"b\"");
|
|
p = str;
|
|
EXPECT_EQ(T_BITMAPS, LineTokenType(&p));
|
|
EXPECT_EQ(u16len(u"bitmaps "), p - str);
|
|
EXPECT_TRUE(!u16cmp(p, u"\"b\""));
|
|
|
|
// T_STORE, preceeded by one space
|
|
u16cpy(str, u" store(b)");
|
|
p = str;
|
|
EXPECT_EQ(T_STORE, LineTokenType(&p));
|
|
EXPECT_EQ(u16len(u" store"), p - str);
|
|
EXPECT_TRUE(!u16cmp(p, u"(b)"));
|
|
|
|
// T_STORE, preceeded by two spaces
|
|
u16cpy(str, u" store(b)");
|
|
p = str;
|
|
EXPECT_EQ(T_STORE, LineTokenType(&p));
|
|
EXPECT_EQ(u16len(u" store"), p - str);
|
|
EXPECT_TRUE(!u16cmp(p, u"(b)"));
|
|
|
|
// T_STORE, followed by one space
|
|
u16cpy(str, u"store (b)");
|
|
p = str;
|
|
EXPECT_EQ(T_STORE, LineTokenType(&p));
|
|
EXPECT_EQ(u16len(u"store "), p - str);
|
|
EXPECT_TRUE(!u16cmp(p, u"(b)"));
|
|
|
|
// T_STORE, followed by two spaces
|
|
u16cpy(str, u"store (b)");
|
|
p = str;
|
|
EXPECT_EQ(T_STORE, LineTokenType(&p));
|
|
EXPECT_EQ(u16len(u"store "), p - str);
|
|
EXPECT_TRUE(!u16cmp(p, u"(b)"));
|
|
|
|
// T_COMMENT
|
|
u16cpy(str, u"c ");
|
|
p = str;
|
|
EXPECT_EQ(T_COMMENT, LineTokenType(&p));
|
|
EXPECT_EQ(0, p - str);
|
|
|
|
// comment without following space ... potential bug, but ReadLine() currently ensures following space
|
|
u16cpy(str, u"c");
|
|
p = str;
|
|
EXPECT_EQ(T_UNKNOWN, LineTokenType(&p));
|
|
EXPECT_EQ(0, p - str);
|
|
|
|
// T_KEYTOKEY
|
|
u16cpy(str, u"abc");
|
|
p = str;
|
|
EXPECT_EQ(T_KEYTOKEY, LineTokenType(&p));
|
|
EXPECT_EQ(0, p - str);
|
|
|
|
// T_UNKNOWN
|
|
u16cpy(str, u"z");
|
|
p = str;
|
|
EXPECT_EQ(T_UNKNOWN, LineTokenType(&p));
|
|
EXPECT_EQ(0, p - str);
|
|
}
|
|
|
|
// KMX_BOOL StrValidChrs(PKMX_WCHAR q, KMX_WCHAR const * chrs)
|
|
// KMX_DWORD GetXString(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_WCHAR const * token,
|
|
// PKMX_WCHAR output, int max, int offset, PKMX_WCHAR *newp, int /*isVKey*/, int isUnicode
|
|
// )
|
|
|
|
TEST_F(CompilerTest, GetXStringImpl_test) {
|
|
KMX_WCHAR tstr[128];
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
KMX_WCHAR token[128];
|
|
|
|
// KmnCompilerMessages::FATAL_BufferOverflow, max=0
|
|
EXPECT_EQ(KmnCompilerMessages::FATAL_BufferOverflow, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 0, 0, &newp, FALSE));
|
|
|
|
// STATUS_Success, no token
|
|
u16cpy(str, u"");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_NoTokensFound, empty
|
|
u16cpy(str, u"");
|
|
u16cpy(token, u"c");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, GetXStringImpl(tstr, &fileKeyboard, str,token, output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_NoTokensFound, whitespace
|
|
u16cpy(str, u" ");
|
|
u16cpy(token, u"c");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, GetXStringImpl(tstr, &fileKeyboard, str, token, output, 80, 0, &newp, FALSE));
|
|
}
|
|
|
|
// tests strings starting with 'x' or 'd'
|
|
TEST_F(CompilerTest, GetXStringImpl_type_xd_test) {
|
|
KMX_WCHAR tstr[128];
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
|
|
// hex 32-bit
|
|
u16cpy(str, u"x10330"); // Gothic A
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_GothicA[] = { 0xD800, 0xDF30, 0 }; // see UTF32ToUTF16
|
|
EXPECT_EQ(0, u16cmp(tstr_GothicA, tstr));
|
|
|
|
// decimal 8-bit
|
|
u16cpy(str, u"d18");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(u"\u0012", tstr));
|
|
|
|
// hex capital 8-bit
|
|
u16cpy(str, u"X12");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(u"\u0012", tstr));
|
|
|
|
// hex 32-bit, KmnCompilerMessages::ERROR_InvalidCharacter
|
|
u16cpy(str, u"x110000");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCharacter, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// dk, valid
|
|
u16cpy(str, u"dk(A)");
|
|
EXPECT_EQ(0, (int)fileKeyboard.cxDeadKeyArray);
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_dk_valid[] = { UC_SENTINEL, CODE_DEADKEY, 1, 0 }; // setup deadkeys
|
|
EXPECT_EQ(0, u16cmp(tstr_dk_valid, tstr));
|
|
fileKeyboard.cxDeadKeyArray = 0;
|
|
|
|
// deadkey, valid
|
|
u16cpy(str, u"deadkey(A)");
|
|
EXPECT_EQ(0, (int)fileKeyboard.cxDeadKeyArray);
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_deadkey_valid[] = { UC_SENTINEL, CODE_DEADKEY, 1, 0 }; // setup deadkeys
|
|
EXPECT_EQ(0, u16cmp(tstr_deadkey_valid, tstr));
|
|
fileKeyboard.cxDeadKeyArray = 0;
|
|
|
|
// deadkey, valid
|
|
u16cpy(str, u"deadkey(%)");
|
|
EXPECT_EQ(0, (int)fileKeyboard.cxDeadKeyArray);
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_deadkey_valid_pct[] = { UC_SENTINEL, CODE_DEADKEY, 1, 0 }; // setup deadkeys
|
|
EXPECT_EQ(0, u16cmp(tstr_deadkey_valid_pct, tstr));
|
|
fileKeyboard.cxDeadKeyArray = 0;
|
|
|
|
// dk, KmnCompilerMessages::ERROR_InvalidDeadkey, bad character
|
|
u16cpy(str, u"dk(,)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// dk, KmnCompilerMessages::ERROR_InvalidDeadkey, no delimiters => NULL
|
|
u16cpy(str, u"dk");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// dk, KmnCompilerMessages::ERROR_InvalidDeadkey, no close delimiter => NULL
|
|
u16cpy(str, u"dk(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// dk, KmnCompilerMessages::ERROR_InvalidDeadkey, empty delimiters => empty string
|
|
u16cpy(str, u"dk()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidDeadkey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
}
|
|
|
|
// tests strings starting with double quote
|
|
TEST_F(CompilerTest, GetXStringImpl_type_double_quote_test) {
|
|
KMX_WCHAR tstr[128];
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
|
|
// valid
|
|
u16cpy(str, u"\"abc\"");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(u"abc", tstr));
|
|
|
|
// KmnCompilerMessages::ERROR_UnterminatedString
|
|
u16cpy(str, u"\"abc");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_UnterminatedString, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_ExtendedStringTooLong
|
|
u16cpy(str, u"\"abc\"");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_ExtendedStringTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 2, 0, &newp, FALSE)); // max reduced to force error
|
|
}
|
|
|
|
// tests strings starting with single quote
|
|
TEST_F(CompilerTest, GetXStringImpl_type_single_quote_test) {
|
|
KMX_WCHAR tstr[128];
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
|
|
// valid
|
|
u16cpy(str, u"\'abc\'");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(u"abc", tstr));
|
|
|
|
// KmnCompilerMessages::ERROR_UnterminatedString
|
|
u16cpy(str, u"\'abc");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_UnterminatedString, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_ExtendedStringTooLong
|
|
u16cpy(str, u"\'abc\'");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_ExtendedStringTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 2, 0, &newp, FALSE)); // max reduced to force error
|
|
}
|
|
|
|
// tests strings starting with 'a'
|
|
TEST_F(CompilerTest, GetXStringImpl_type_a_test) {
|
|
KMX_WCHAR tstr[128];
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
initFileStoreArray(fileKeyboard, {u"a", u"b", u"c"});
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidToken
|
|
u16cpy(str, u"abc");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidAny, no delimiters => NULL
|
|
u16cpy(str, u"any");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidAny, no close delimiter => NULL
|
|
u16cpy(str, u"any(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidAny, empty delimiters => empty string
|
|
u16cpy(str, u"any()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidAny, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
u16cpy(str, u"any( )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_StoreDoesNotExist
|
|
u16cpy(str, u"any(d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_StoreDoesNotExist, space before store
|
|
u16cpy(str, u"any( d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_StoreDoesNotExist, space after store
|
|
u16cpy(str, u"any(d )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_ZeroLengthString
|
|
u16cpy(str, u"any(b)");
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"";
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_ZeroLengthString, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// valid
|
|
u16cpy(str, u"any(b)");
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_any_valid[] = { UC_SENTINEL, CODE_ANY, 2, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_any_valid, tstr));
|
|
|
|
// space before store, valid
|
|
u16cpy(str, u"any( b)");
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_any_valid, tstr));
|
|
|
|
// space after store, valid (see #11937, #11938)
|
|
u16cpy(str, u"any(b )");
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_any_valid, tstr));
|
|
}
|
|
|
|
// tests strings starting with 'b'
|
|
TEST_F(CompilerTest, GetXStringImpl_type_b_test) {
|
|
KMX_WCHAR tstr[128];
|
|
fileKeyboard.version = VERSION_90;
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidToken
|
|
u16cpy(str, u"bcd");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// beep, valid
|
|
u16cpy(str, u"beep");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_beep_valid[] = { UC_SENTINEL, CODE_BEEP, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_beep_valid, tstr));
|
|
|
|
// baselayout, KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores
|
|
fileKeyboard.version = VERSION_80;
|
|
fileKeyboard.dwFlags = 0u;
|
|
u16cpy(str, u"baselayout");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
fileKeyboard.version = VERSION_90;
|
|
|
|
// baselayout, no delimiters => NULL
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"baselayout");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// baselayout, no close delimiter => NULL
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"baselayout(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// baselayout, empty delimiters => empty string
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"baselayout()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// baselayout, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"baselayout( )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// baselayout, KmnCompilerMessages::ERROR_InvalidToken from process_baselayout
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"baselayout(abc)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// baselayout, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
fileKeyboard.cxStoreArray = 0;
|
|
fileKeyboard.dpStoreArray = nullptr;
|
|
u16cpy(str, u"baselayout(beep)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_baselayout_valid[] = { UC_SENTINEL, CODE_IFSYSTEMSTORE, TSS_BASELAYOUT+1, 2, 1, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_baselayout_valid, tstr));
|
|
|
|
// baselayout, space before argument, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
fileKeyboard.cxStoreArray = 0;
|
|
fileKeyboard.dpStoreArray = nullptr;
|
|
u16cpy(str, u"baselayout( beep)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_baselayout_valid, tstr));
|
|
|
|
// baselayout, space after argument, valid (see #11937, #11938)
|
|
fileKeyboard.version = VERSION_90;
|
|
fileKeyboard.cxStoreArray = 0;
|
|
fileKeyboard.dpStoreArray = nullptr;
|
|
u16cpy(str, u"baselayout(beep )");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_baselayout_valid, tstr));
|
|
}
|
|
|
|
// tests strings starting with 'i'
|
|
TEST_F(CompilerTest, GetXStringImpl_type_i_test) {
|
|
KMX_WCHAR tstr[128];
|
|
fileKeyboard.version = VERSION_80;
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
initFileStoreArray(fileKeyboard, {u"a", u"b", u"c"});
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidToken
|
|
u16cpy(str, u"ijk");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// if, KmnCompilerMessages::ERROR_80FeatureOnly
|
|
fileKeyboard.version = VERSION_70;
|
|
fileKeyboard.dwFlags = 0u;
|
|
u16cpy(str, u"if");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_80FeatureOnly, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
fileKeyboard.version = VERSION_80;
|
|
|
|
// if, no delimiters => NULL
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"if");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// if, no close delimiter => NULL
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"if(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// if, empty delimiters => empty string
|
|
fileKeyboard.version = VERSION_80;
|
|
fileKeyboard.dwFlags = 0u;
|
|
u16cpy(str, u"if()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// if, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
fileKeyboard.version = VERSION_80;
|
|
fileKeyboard.dwFlags = 0u;
|
|
u16cpy(str, u"if( )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// if, invalid
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"if(abc)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIf, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// if, KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"if(&BITMAP=)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_90FeatureOnly_IfSystemStores, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// if, KmnCompilerMessages::ERROR_IfSystemStore_NotFound
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"if(&abc=)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_IfSystemStore_NotFound, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// if, system store, equal, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
fileKeyboard.cxStoreArray = 3u;
|
|
u16cpy(str, u"if(&BITMAP=beep)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_if_equal_system_store_valid[] = { UC_SENTINEL, CODE_IFSYSTEMSTORE, 2, 2, 4, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_if_equal_system_store_valid, tstr));
|
|
|
|
// if, system store, not equal, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
fileKeyboard.cxStoreArray = 3u;
|
|
u16cpy(str, u"if(&BITMAP!=beep)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_if_not_equal_system_store_valid[] = { UC_SENTINEL, CODE_IFSYSTEMSTORE, 2, 1, 4, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_if_not_equal_system_store_valid, tstr));
|
|
|
|
// if, option, KmnCompilerMessages::ERROR_StoreDoesNotExist
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"if(d=beep)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// if, option, equal, valid
|
|
fileKeyboard.version = VERSION_80;
|
|
fileKeyboard.cxStoreArray = 3u;
|
|
fileKeyboard.dpStoreArray[1].fIsOption = TRUE;
|
|
u16cpy(str, u"if(b=beep)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_if_option_valid[] = { UC_SENTINEL, CODE_IFOPT, 2, 2, 4, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_if_option_valid, tstr));
|
|
|
|
// if, option, equal, space before assign, valid
|
|
fileKeyboard.version = VERSION_80;
|
|
fileKeyboard.cxStoreArray = 3u;
|
|
fileKeyboard.dpStoreArray[1].fIsOption = TRUE;
|
|
u16cpy(str, u"if(b =beep)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_if_option_valid, tstr));
|
|
|
|
// if, option, equal, space before rhs, valid
|
|
fileKeyboard.version = VERSION_80;
|
|
fileKeyboard.cxStoreArray = 3u;
|
|
fileKeyboard.dpStoreArray[1].fIsOption = TRUE;
|
|
u16cpy(str, u"if(b= beep)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_if_option_valid, tstr));
|
|
|
|
// if, option, equal, space after rhs, valid (see #11937, #11938)
|
|
fileKeyboard.version = VERSION_80;
|
|
fileKeyboard.cxStoreArray = 3u;
|
|
fileKeyboard.dpStoreArray[1].fIsOption = TRUE;
|
|
u16cpy(str, u"if(b=beep )");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_if_option_valid, tstr));
|
|
|
|
delete[] fileKeyboard.dpStoreArray;
|
|
initFileStoreArray(fileKeyboard, {u"a", u"b", u"c"});
|
|
fileKeyboard.dpStoreArray[1].fIsStore = TRUE;
|
|
|
|
// index, no delimiters => NULL
|
|
u16cpy(str, u"index");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, no close delimiter => NULL
|
|
u16cpy(str, u"index(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, empty delimiters => empty string
|
|
u16cpy(str, u"index()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
u16cpy(str, u"index( )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, no comma or space
|
|
u16cpy(str, u"index(b)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, no comma, space before store
|
|
u16cpy(str, u"index( b)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, no comma, space after store
|
|
u16cpy(str, u"index(b )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, KmnCompilerMessages::ERROR_StoreDoesNotExist
|
|
u16cpy(str, u"index(d,4)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, comma, offset=0
|
|
u16cpy(str, u"index(b,0)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, comma, negative offset
|
|
u16cpy(str, u"index(b,-1)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, comma, valid
|
|
u16cpy(str, u"index(b,4)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_index_valid[] = { UC_SENTINEL, CODE_INDEX, 2, 4, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_index_valid, tstr));
|
|
|
|
// index, space before store, comma, valid
|
|
u16cpy(str, u"index( b,4)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_index_valid, tstr));
|
|
|
|
// index, space after store, comma, valid
|
|
u16cpy(str, u"index(b ,4)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_index_valid, tstr));
|
|
|
|
// index, comma and space, valid
|
|
u16cpy(str, u"index(b, 4)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_index_valid, tstr));
|
|
|
|
// index, comma, space after offset, valid
|
|
u16cpy(str, u"index(b,4 )");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_index_valid, tstr));
|
|
|
|
// index, space, KmnCompilerMessages::ERROR_StoreDoesNotExist (see issue #11833)
|
|
u16cpy(str, u"index(b 4)"); // store name appears to be 'b 4'
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, two commas and extra parameter, KmnCompilerMessages::ERROR_InvalidIndex
|
|
u16cpy(str, u"index(b,4,5)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, two-digit offset, valid
|
|
u16cpy(str, u"index(b,42)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_index_two_digit_valid[] = { UC_SENTINEL, CODE_INDEX, 2, 42, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_index_two_digit_valid, tstr));
|
|
|
|
// index, comma, non-digit offset, KmnCompilerMessages::ERROR_InvalidIndex
|
|
u16cpy(str, u"index(b,g)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, comma, no offset, KmnCompilerMessages::ERROR_InvalidIndex
|
|
u16cpy(str, u"index(b,)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, space and comma, no offset, KmnCompilerMessages::ERROR_InvalidIndex
|
|
u16cpy(str, u"index(b ,)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// index, comma, no offset but space, KmnCompilerMessages::ERROR_InvalidIndex
|
|
u16cpy(str, u"index(b, )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidIndex, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
}
|
|
|
|
// tests strings starting with 'o'
|
|
TEST_F(CompilerTest, GetXStringImpl_type_o_test) {
|
|
KMX_WCHAR tstr[128];
|
|
fileKeyboard.version = VERSION_80;
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
initFileStoreArray(fileKeyboard, {u"a", u"b", u"c"});
|
|
fileKeyboard.dpStoreArray[1].fIsStore = TRUE;
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidToken
|
|
u16cpy(str, u"opq");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// outs, no delimiters => NULL
|
|
u16cpy(str, u"outs");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// outs, no close delimiter => NULL
|
|
u16cpy(str, u"outs(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// outs, empty delimiters => empty string
|
|
u16cpy(str, u"outs()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// outs, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
u16cpy(str, u"outs( )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidOuts, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// outs, KmnCompilerMessages::ERROR_StoreDoesNotExist
|
|
u16cpy(str, u"outs(d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// outs, KmnCompilerMessages::ERROR_StoreDoesNotExist, space before store
|
|
u16cpy(str, u"outs( d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// outs, KmnCompilerMessages::ERROR_StoreDoesNotExist, space after store
|
|
u16cpy(str, u"outs(d )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// outs, KmnCompilerMessages::ERROR_OutsTooLong
|
|
PKMX_WCHAR dpString = (PKMX_WCHAR)u"abc";
|
|
fileKeyboard.dpStoreArray[1].dpString = dpString; // length 4 => max should be > 4, otherwise a ERROR_OutsTooLong is emitted
|
|
int max = u16len(dpString) + 1; // 4, including terminating '\0'
|
|
u16cpy(str, u"outs(b)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_OutsTooLong, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, max, 0, &newp, FALSE)); // max reduced to force error
|
|
|
|
// outs, valid
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc";
|
|
u16cpy(str, u"outs(b)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_outs_valid[] = { 'a', 'b', 'c', 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_outs_valid, tstr));
|
|
|
|
// outs, space before store, valid
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc";
|
|
u16cpy(str, u"outs( b)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_outs_valid, tstr));
|
|
|
|
// outs, space after store, valid (see #11937, #11938)
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc";
|
|
u16cpy(str, u"outs(b )");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_outs_valid, tstr));
|
|
}
|
|
|
|
// tests strings starting with 'c'
|
|
TEST_F(CompilerTest, GetXStringImpl_type_c_test) {
|
|
KMX_WCHAR tstr[128];
|
|
fileKeyboard.version = VERSION_60;
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
initFileStoreArray(fileKeyboard, {u"a", u"b", u"c"});
|
|
fileKeyboard.dpStoreArray[1].fIsCall = TRUE;
|
|
fileKeyboard.dpStoreArray[1].dwSystemID = TSS_NONE;
|
|
|
|
// are comments stripped before this point?
|
|
// if so, why the test on whitespace after 'c'?
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"cde");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// context, no offset, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_context_no_offset_valid[] = { UC_SENTINEL, CODE_CONTEXT, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_context_no_offset_valid, tstr));
|
|
|
|
// context, KmnCompilerMessages::ERROR_InvalidToken, no close delimiter => NULL
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// context, empty delimiters => empty string, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context()");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_context_empty_offset_valid[] = { UC_SENTINEL, CODE_CONTEXT, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_context_empty_offset_valid, tstr));
|
|
|
|
// context, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context( )");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// context, offset, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context(1)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_context_offset_valid[] = { UC_SENTINEL, CODE_CONTEXTEX, 1, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_context_offset_valid, tstr));
|
|
|
|
// context, ERROR_ContextExHasInvalidOffset, offset < 1
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context(0)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_ContextExHasInvalidOffset, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// context, large offset < 0xF000, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context(61439)"); //0xF000 - 1
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_context_large_offset_valid[] = { UC_SENTINEL, CODE_CONTEXTEX, 61439, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_context_large_offset_valid, tstr));
|
|
|
|
// context, KmnCompilerMessages::ERROR_ContextExHasInvalidOffset, too large offset == 0xF000
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context(61440)"); //0xF000
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_ContextExHasInvalidOffset, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// context, KmnCompilerMessages::ERROR_60FeatureOnly_Contextn
|
|
fileKeyboard.version = VERSION_50;
|
|
u16cpy(str, u"context(1)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_60FeatureOnly_Contextn, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// context, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context(1)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_context_valid[] = { UC_SENTINEL, CODE_CONTEXTEX, 1, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_context_valid, tstr));
|
|
|
|
// context, space before offset, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context( 1)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_context_valid, tstr));
|
|
|
|
// context, space after offset, valid (see #11937, #11938)
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"context(1 )");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_context_valid, tstr));
|
|
|
|
// clearcontext, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"clearcontext");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_clearcontext_valid[] = { UC_SENTINEL, CODE_CLEARCONTEXT, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_clearcontext_valid, tstr));
|
|
|
|
// call, KmnCompilerMessages::ERROR_501FeatureOnly_Call
|
|
fileKeyboard.version = VERSION_50;
|
|
u16cpy(str, u"call");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_501FeatureOnly_Call, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// call, no delimiters => NULL
|
|
fileKeyboard.version = VERSION_501;
|
|
u16cpy(str, u"call");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// call, no close delimiter => NULL
|
|
fileKeyboard.version = VERSION_501;
|
|
u16cpy(str, u"call(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// call, empty delimiters => empty string
|
|
fileKeyboard.version = VERSION_501;
|
|
u16cpy(str, u"call()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// call, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
fileKeyboard.version = VERSION_501;
|
|
u16cpy(str, u"call( )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// call, KmnCompilerMessages::ERROR_StoreDoesNotExist
|
|
fileKeyboard.version = VERSION_501;
|
|
u16cpy(str, u"call(d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// call, KmnCompilerMessages::ERROR_StoreDoesNotExist, space before store
|
|
fileKeyboard.version = VERSION_501;
|
|
u16cpy(str, u"call( d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// call, KmnCompilerMessages::ERROR_StoreDoesNotExist, space after store
|
|
fileKeyboard.version = VERSION_501;
|
|
u16cpy(str, u"call(d )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// call, KmnCompilerMessages::ERROR_InvalidCall
|
|
fileKeyboard.version = VERSION_501;
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"*"; // cause IsValidCallStore() to fail
|
|
u16cpy(str, u"call(b)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCall, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// call, valid
|
|
fileKeyboard.version = VERSION_501;
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"a.dll:A";
|
|
fileKeyboard.dpStoreArray[1].dwSystemID = TSS_NONE;
|
|
u16cpy(str, u"call(b)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_call_valid[] = { UC_SENTINEL, CODE_CALL, 2, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_call_valid, tstr));
|
|
EXPECT_EQ(TSS_CALLDEFINITION, fileKeyboard.dpStoreArray[1].dwSystemID);
|
|
|
|
// call, space before store, valid
|
|
fileKeyboard.version = VERSION_501;
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"a.dll:A";
|
|
fileKeyboard.dpStoreArray[1].dwSystemID = TSS_NONE;
|
|
u16cpy(str, u"call( b)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_call_valid, tstr));
|
|
EXPECT_EQ(TSS_CALLDEFINITION, fileKeyboard.dpStoreArray[1].dwSystemID);
|
|
|
|
// call, space after store, valid (see #11937, #11938)
|
|
fileKeyboard.version = VERSION_501;
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"a.dll:A";
|
|
fileKeyboard.dpStoreArray[1].dwSystemID = TSS_NONE;
|
|
u16cpy(str, u"call(b )");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_call_valid, tstr));
|
|
EXPECT_EQ(TSS_CALLDEFINITION, fileKeyboard.dpStoreArray[1].dwSystemID);
|
|
}
|
|
|
|
// tests strings starting with 'n'
|
|
TEST_F(CompilerTest, GetXStringImpl_type_n_test) {
|
|
KMX_WCHAR tstr[128];
|
|
fileKeyboard.version = VERSION_70;
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
initFileStoreArray(fileKeyboard, {u"a", u"b", u"c"});
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"nmo");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// notany, KmnCompilerMessages::ERROR_70FeatureOnly
|
|
fileKeyboard.version = VERSION_60;
|
|
u16cpy(str, u"notany");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_70FeatureOnly, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// notany, no delimiters => NULL
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// notany, no close delimiter => NULL
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// notany, empty delimiters => empty string
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// notany, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany( )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidAny, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// notany, KmnCompilerMessages::ERROR_StoreDoesNotExist
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany(d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// notany, KmnCompilerMessages::ERROR_StoreDoesNotExist, space before store
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany( d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// notany, KmnCompilerMessages::ERROR_StoreDoesNotExist, space after store
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany(d )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// notany, valid
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany(b)");
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_notany_valid[] = { UC_SENTINEL, CODE_NOTANY, 2, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_notany_valid, tstr));
|
|
|
|
// notany, valid, empty store
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany(b)");
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u""; // empty
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_notany_valid, tstr));
|
|
|
|
// notany, space before store, valid
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany( b)");
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_notany_valid, tstr));
|
|
|
|
// notany, space after store, valid (see #11937, #11938)
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"notany(b )");
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_notany_valid, tstr));
|
|
|
|
// null
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"nul");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_null_valid[] = { UC_SENTINEL, CODE_NUL, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_null_valid, tstr));
|
|
}
|
|
|
|
// tests strings starting with 'u'
|
|
TEST_F(CompilerTest, GetXStringImpl_type_u_test) {
|
|
KMX_WCHAR tstr[128];
|
|
fileKeyboard.version = VERSION_90;
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
initFileGroupArray(fileKeyboard, {u"a", u"b", u"c"});
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidToken
|
|
u16cpy(str, u"uvw");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// unicode, n1 and n2, valid
|
|
u16cpy(str, u"u+10330"); // Gothic A
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, TRUE));
|
|
const KMX_WCHAR tstr_unicode_valid[] = { 0xD800, 0xDF30, 0 }; // see UTF32ToUTF16
|
|
EXPECT_EQ(0, u16cmp(tstr_unicode_valid, tstr));
|
|
EXPECT_EQ(0, msgproc_errors.size());
|
|
|
|
// unicode, ERROR_InvalidValue
|
|
u16cpy(str, u"u+10330z"); // Gothic A, unexpected character 'z'
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidValue, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, TRUE));
|
|
|
|
// unicode, space after, valid
|
|
u16cpy(str, u"u+10330 "); // Gothic A
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, TRUE));
|
|
EXPECT_EQ(0, u16cmp(tstr_unicode_valid, tstr));
|
|
EXPECT_EQ(0, msgproc_errors.size());
|
|
|
|
// unicode, KmnCompilerMessages::ERROR_InvalidCharacter
|
|
u16cpy(str, u"u+110000");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidCharacter, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, TRUE));
|
|
|
|
// unicode, n1 only, valid
|
|
u16cpy(str, u"u+0061"); // a
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, TRUE));
|
|
const KMX_WCHAR tstr_unicode_n1_only_valid[] = { 0x0061, 0 }; // see UTF32ToUTF16
|
|
EXPECT_EQ(0, u16cmp(tstr_unicode_n1_only_valid, tstr));
|
|
EXPECT_EQ(0, msgproc_errors.size());
|
|
|
|
// unicode, n1 and n2, valid, KmnCompilerMessages::WARN_UnicodeInANSIGroup
|
|
u16cpy(str, u"u+10330"); // Gothic A
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_unicode_valid, tstr));
|
|
EXPECT_EQ(1, msgproc_errors.size());
|
|
EXPECT_EQ(KmnCompilerMessages::WARN_UnicodeInANSIGroup, msgproc_errors[0].errorCode);
|
|
|
|
// use, no delimiters => NULL
|
|
u16cpy(str, u"use");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidUse, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// use, no close delimiter => NULL
|
|
u16cpy(str, u"use(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidUse, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// use, empty delimiters => empty string
|
|
u16cpy(str, u"use()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidUse, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// use, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
u16cpy(str, u"use( )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidUse, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// use, KmnCompilerMessages::ERROR_GroupDoesNotExist
|
|
u16cpy(str, u"use(d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_GroupDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// use, KmnCompilerMessages::ERROR_GroupDoesNotExist, space before store
|
|
u16cpy(str, u"use( d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_GroupDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// use, KmnCompilerMessages::ERROR_GroupDoesNotExist, space after store
|
|
u16cpy(str, u"use(d )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_GroupDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// use, valid
|
|
u16cpy(str, u"use(b)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_use_valid[] = { UC_SENTINEL, CODE_USE, 2, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_use_valid, tstr));
|
|
|
|
// use, space before group, valid
|
|
u16cpy(str, u"use( b)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_use_valid, tstr));
|
|
|
|
// use, space after group, valid (see #11937, #11938)
|
|
u16cpy(str, u"use(b )");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_use_valid, tstr));
|
|
}
|
|
|
|
// tests strings starting with 'r'
|
|
TEST_F(CompilerTest, GetXStringImpl_type_r_test) {
|
|
KMX_WCHAR tstr[128];
|
|
fileKeyboard.version = VERSION_80;
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
initFileStoreArray(fileKeyboard, {u"a", u"b", u"c"});
|
|
|
|
// KmnCompilerMessages::ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"rst");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// reset, KmnCompilerMessages::ERROR_80FeatureOnly
|
|
fileKeyboard.version = VERSION_70;
|
|
u16cpy(str, u"reset");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_80FeatureOnly, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// reset, no delimiters => NULL
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidReset, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// reset, no close delimiter => NULL
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset(");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidReset, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// reset, empty delimiters => empty string
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset()");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidReset, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// reset, space in delimiters (see #11814, #11937, #11910, #11894, #11938)
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset( )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidReset, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// reset, KmnCompilerMessages::ERROR_StoreDoesNotExist
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset(d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// reset, KmnCompilerMessages::ERROR_StoreDoesNotExist, space before store
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset( d)");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// reset, KmnCompilerMessages::ERROR_StoreDoesNotExist, space after store
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset(d )");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_StoreDoesNotExist, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// reset, valid
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset(b)");
|
|
fileKeyboard.dpStoreArray[1].dpString = (PKMX_WCHAR)u"abc"; // non-empty
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_reset_valid[] = { UC_SENTINEL, CODE_RESETOPT, 2, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_reset_valid, tstr));
|
|
|
|
// reset, space before store, valid
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset( b)");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_reset_valid, tstr));
|
|
|
|
// reset, space after store, valid (see #11937, #11938)
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"reset(b )");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_reset_valid, tstr));
|
|
|
|
// return, valid
|
|
u16cpy(str, u"return");
|
|
u16cpy(output, u"XXXXX");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 4, 0, &newp, FALSE));
|
|
const KMX_WCHAR tstr_return_valid[] = { UC_SENTINEL, CODE_RETURN, 0 };
|
|
const KMX_WCHAR output_return_valid[] = { UC_SENTINEL, CODE_RETURN, 0, 0, 'X' };
|
|
EXPECT_EQ(0, u16cmp(tstr_return_valid, tstr));
|
|
EXPECT_EQ(0, u16cmp(output_return_valid, output));
|
|
}
|
|
|
|
// tests strings starting with '['
|
|
TEST_F(CompilerTest, GetXStringImpl_type_osb_test) {
|
|
kmcmp::msgproc = msgproc_collect;
|
|
KMX_WCHAR tstr[128];
|
|
fileKeyboard.version = VERSION_90;
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR output[GLOBAL_BUFSIZE];
|
|
PKMX_WCHAR newp = nullptr;
|
|
initVKDictionary(fileKeyboard, {u"abc", u"def", u"ghi"});
|
|
|
|
// virtual key, empty, KmnCompilerMessages::ERROR_InvalidToken
|
|
u16cpy(str, u"[]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual key, single space, KmnCompilerMessages::ERROR_InvalidToken
|
|
u16cpy(str, u"[ ]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual key, in VKeyNames, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[K_A]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
KMX_WCHAR sFlag = ISVIRTUALKEY;
|
|
KMX_WCHAR tstr_virtual_key_valid[] = { UC_SENTINEL, CODE_EXTENDED, sFlag, 65, UC_SENTINEL_EXTENDEDEND, 0 };
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
|
|
// virtual key, space before, in VKeyNames, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[ K_A]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
|
|
// virtual key, space after, in VKeyNames, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[K_A ]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
|
|
// virtual key, in VKeyNames, valid with modifiers
|
|
std::map<const KMX_WCHAR*, const KMX_WCHAR> m_mod{
|
|
// str sFlag
|
|
{u"[NCAPS K_A]", ISVIRTUALKEY | NOTCAPITALFLAG },
|
|
{u"[LALT K_A]", ISVIRTUALKEY | LALTFLAG },
|
|
{u"[LCTRL K_A]", ISVIRTUALKEY | LCTRLFLAG },
|
|
{u"[RALT K_A]", ISVIRTUALKEY | RALTFLAG },
|
|
{u"[RCTRL K_A]", ISVIRTUALKEY | RCTRLFLAG },
|
|
{u"[ALT K_A]", ISVIRTUALKEY | K_ALTFLAG },
|
|
{u"[CTRL K_A]", ISVIRTUALKEY | K_CTRLFLAG },
|
|
{u"[CAPS K_A]", ISVIRTUALKEY | CAPITALFLAG },
|
|
{u"[SHIFT K_A]", ISVIRTUALKEY | K_SHIFTFLAG },
|
|
{u"[CTRL ALT K_A]", ISVIRTUALKEY | K_CTRLFLAG | K_ALTFLAG },
|
|
{u"[LCTRL LALT K_A]", ISVIRTUALKEY | LCTRLFLAG | LALTFLAG }, // no mixed modifiers warning
|
|
{u"[RCTRL RALT K_A]", ISVIRTUALKEY | RCTRLFLAG | RALTFLAG }, // no mixed modifiers warning
|
|
};
|
|
|
|
fileKeyboard.version = VERSION_90;
|
|
for (auto i = m_mod.begin(); i != m_mod.end(); i++) {
|
|
u16cpy(str, i->first);
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = i->second;
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(0, msgproc_errors.size());
|
|
}
|
|
|
|
// virtual key, in VKeyNames, with modifiers, KmnCompilerMessages::WARN_MixingLeftAndRightModifiers
|
|
std::map<const KMX_WCHAR*, const KMX_WCHAR> m_mixed{
|
|
// str sFlag
|
|
{u"[LCTRL RALT K_A]", ISVIRTUALKEY | LCTRLFLAG | RALTFLAG },
|
|
{u"[RCTRL LALT K_A]", ISVIRTUALKEY | RCTRLFLAG | LALTFLAG },
|
|
};
|
|
|
|
fileKeyboard.version = VERSION_90;
|
|
for (auto i = m_mixed.begin(); i != m_mixed.end(); i++) {
|
|
u16cpy(str, i->first);
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = i->second;
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(KmnCompilerMessages::WARN_MixingLeftAndRightModifiers, msgproc_errors.back().errorCode);
|
|
}
|
|
msgproc_errors.clear();
|
|
|
|
// virtual key, in VKeyNames, with modifiers, chiral modifiers version bump
|
|
std::map<const KMX_WCHAR*, const KMX_WCHAR> m_chiral{
|
|
// str sFlag
|
|
{u"[LCTRL K_A]", ISVIRTUALKEY | LCTRLFLAG },
|
|
{u"[LALT K_A]", ISVIRTUALKEY | LALTFLAG },
|
|
{u"[RCTRL K_A]", ISVIRTUALKEY | RCTRLFLAG },
|
|
{u"[RALT K_A]", ISVIRTUALKEY | RALTFLAG },
|
|
{u"[CAPS K_A]", ISVIRTUALKEY | CAPITALFLAG },
|
|
{u"[NCAPS K_A]", ISVIRTUALKEY | NOTCAPITALFLAG },
|
|
};
|
|
|
|
kmcmp::CompileTarget = CKF_KEYMANWEB;
|
|
fileKeyboard.dwFlags = KF_AUTOMATICVERSION;
|
|
for (auto i = m_chiral.begin(); i != m_chiral.end(); i++) {
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, i->first);
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = i->second;
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(VERSION_100, fileKeyboard.version);
|
|
EXPECT_EQ(0, msgproc_errors.size());
|
|
}
|
|
kmcmp::CompileTarget = CKF_KEYMAN;
|
|
fileKeyboard.dwFlags = 0;
|
|
|
|
// virtual key, modifiers only (no key portion), KmnCompilerMessages::ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[CTRL ALT]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual key, modifiers only (no key portion), space after, KmnCompilerMessages::ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[CTRL ALT ]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual key, in VKeyNames, no space between modifier and key portion, ERROR_InvalidToken (see #12307)
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[CTRLK_A]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual key, in VKeyNames, no space between modifiers, ERROR_InvalidToken (see #12307)
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[CTRLALT K_A]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual key, '_' between modifier and key portion', ERROR_InvalidToken (see #12307)
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[CTRL_K_A]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, single quote, ERROR_60FeatureOnly_VirtualCharKey
|
|
fileKeyboard.version = VERSION_50;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"[']");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_60FeatureOnly_VirtualCharKey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, double quote, ERROR_60FeatureOnly_VirtualCharKey
|
|
fileKeyboard.version = VERSION_50;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"[\"]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_60FeatureOnly_VirtualCharKey, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, unmatched single quote, ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"['");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, unmatched single quote, ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"[']");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, unmatched double quote, ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"[\"");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, unmatched double quote, ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"[\"]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, unmatched single quote ('\n'), ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"['\n");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, empty single quotes, ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"['']");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, empty double quotes, ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"[\"\"]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual char key, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"['A']");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY | VIRTUALCHARKEY;
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(0, msgproc_errors.size());
|
|
|
|
// virtual char key, space before, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"[ 'A']");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY | VIRTUALCHARKEY;
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(0, msgproc_errors.size());
|
|
|
|
// virtual char key, space after, valid
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
u16cpy(str, u"['A' ]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY | VIRTUALCHARKEY;
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(0, msgproc_errors.size());
|
|
|
|
// virtual char key, FMnemonicLayout not set, WARN_VirtualCharKeyWithPositionalLayout
|
|
fileKeyboard.version = VERSION_60;
|
|
kmcmp::FMnemonicLayout = FALSE;
|
|
u16cpy(str, u"['A']");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY | VIRTUALCHARKEY;
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(1, msgproc_errors.size());
|
|
EXPECT_EQ(KmnCompilerMessages::WARN_VirtualCharKeyWithPositionalLayout, msgproc_errors[0].errorCode);
|
|
msgproc_errors.clear();
|
|
|
|
// virtual key, custom name, long, but not too long name, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX]"); // SZMAX_VKDICTIONARYNAME - 1
|
|
EXPECT_EQ(SZMAX_VKDICTIONARYNAME - 1 + 2, u16len(str));
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY;
|
|
tstr_virtual_key_valid[3] = 259; // VK__MAX + 4
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
tstr_virtual_key_valid[3] = 65;
|
|
fileKeyboard.cxVKDictionary = 3;
|
|
fileKeyboard.dpVKDictionary[3].szName[0] = 0;
|
|
|
|
// virtual key, custom name, name too long, ERROR_InvalidToken
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX]"); // SZMAX_VKDICTIONARYNAME
|
|
EXPECT_EQ(SZMAX_VKDICTIONARYNAME + 2, u16len(str));
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual key, custom name, version too low, ERROR_InvalidToken (this should be ERROR_90FeatureOnlyVirtualKeyDictionary)
|
|
fileKeyboard.version = VERSION_80;
|
|
u16cpy(str, u"[abc]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
|
|
// virtual key, custom name, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[jkl]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY;
|
|
tstr_virtual_key_valid[3] = 259; // VK__MAX + 4
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(0, u16cmp(u"jkl", fileKeyboard.dpVKDictionary[3].szName));
|
|
tstr_virtual_key_valid[3] = 65;
|
|
fileKeyboard.cxVKDictionary = 3;
|
|
fileKeyboard.dpVKDictionary[3].szName[0] = 0;
|
|
|
|
// virtual key, custom name, space before, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[ jkl]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY;
|
|
tstr_virtual_key_valid[3] = 259; // VK__MAX + 4
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(0, u16cmp(u"jkl", fileKeyboard.dpVKDictionary[3].szName));
|
|
tstr_virtual_key_valid[3] = 65;
|
|
fileKeyboard.cxVKDictionary = 3;
|
|
fileKeyboard.dpVKDictionary[3].szName[0] = 0;
|
|
|
|
// virtual key, custom name, space after, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[jkl ]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY;
|
|
tstr_virtual_key_valid[3] = 259; // VK__MAX + 4
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(0, u16cmp(u"jkl", fileKeyboard.dpVKDictionary[3].szName));
|
|
tstr_virtual_key_valid[3] = 65;
|
|
fileKeyboard.cxVKDictionary = 3;
|
|
fileKeyboard.dpVKDictionary[3].szName[0] = 0;
|
|
|
|
// virtual key, custom name, pre-existing name, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[def]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY;
|
|
tstr_virtual_key_valid[3] = 257; // VK__MAX + 2
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
tstr_virtual_key_valid[3] = 65;
|
|
|
|
// virtual key, custom name, pre-existing name, space before, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[ def]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY;
|
|
tstr_virtual_key_valid[3] = 257; // VK__MAX + 2
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
tstr_virtual_key_valid[3] = 65;
|
|
|
|
// virtual key, custom name, pre-existing name, space after, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[def ]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY;
|
|
tstr_virtual_key_valid[3] = 257; // VK__MAX + 2
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
tstr_virtual_key_valid[3] = 65;
|
|
|
|
// virtual key, in VKeyNames, kmcmp::FMnemonicLayout true, VKeyMayBeVCKey false, valid
|
|
fileKeyboard.version = VERSION_90;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
EXPECT_EQ(FALSE, VKeyMayBeVCKey[9]); // K_TAB
|
|
u16cpy(str, u"[K_TAB]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY;
|
|
tstr_virtual_key_valid[3] = 9; // K_TAB
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(0, msgproc_errors.size());
|
|
tstr_virtual_key_valid[3] = 65;
|
|
|
|
// virtual key, in VKeyNames, kmcmp::FMnemonicLayout true, VKeyMayBeVCKey true, KmnCompilerMessages::WARN_VirtualKeyWithMnemonicLayout
|
|
fileKeyboard.version = VERSION_90;
|
|
kmcmp::FMnemonicLayout = TRUE;
|
|
EXPECT_EQ(TRUE, VKeyMayBeVCKey[65]); // K_A
|
|
u16cpy(str, u"[K_A]");
|
|
EXPECT_EQ(STATUS_Success, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
tstr_virtual_key_valid[2] = ISVIRTUALKEY;
|
|
EXPECT_EQ(0, u16cmp(tstr_virtual_key_valid, tstr));
|
|
EXPECT_EQ(1, msgproc_errors.size());
|
|
EXPECT_EQ(KmnCompilerMessages::WARN_VirtualKeyWithMnemonicLayout, msgproc_errors[0].errorCode);
|
|
msgproc_errors.clear();
|
|
|
|
// virtual key, in VKeyNames, multiple keys, KmnCompilerMessages::ERROR_InvalidToken (see #12307)
|
|
fileKeyboard.version = VERSION_90;
|
|
u16cpy(str, u"[K_A K_B]");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidToken, GetXStringImpl(tstr, &fileKeyboard, str, u"", output, 80, 0, &newp, FALSE));
|
|
}
|
|
|
|
// KMX_DWORD process_baselayout(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx)
|
|
// KMX_DWORD process_platform(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx)
|
|
// KMX_DWORD process_if_synonym(KMX_DWORD dwSystemID, PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx)
|
|
// KMX_DWORD process_if(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx)
|
|
// KMX_DWORD process_reset(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx)
|
|
// KMX_DWORD process_expansion(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx, int max)
|
|
// KMX_DWORD process_set_synonym(KMX_DWORD dwSystemID, PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx)
|
|
// KMX_DWORD process_set(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx)
|
|
// KMX_DWORD process_save(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx)
|
|
// int xatoi(PKMX_WCHAR *p)
|
|
// int GetGroupNum(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
|
|
|
TEST_F(CompilerTest, ProcessEthnologueStore_test) {
|
|
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u"abc"));
|
|
EXPECT_EQ(KmnCompilerMessages::WARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u";abc"));
|
|
EXPECT_EQ(KmnCompilerMessages::WARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u",abc"));
|
|
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u" abc"));
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abc "));
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abcd"));
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"ab"));
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"a"));
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_InvalidEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"a2b"));
|
|
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u"")); // needs correcting ... see #11955
|
|
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u"abc def"));
|
|
EXPECT_EQ(STATUS_Success, ProcessEthnologueStore((PKMX_WCHAR)u"abc def"));
|
|
EXPECT_EQ(KmnCompilerMessages::WARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abc,def"));
|
|
EXPECT_EQ(KmnCompilerMessages::WARN_PunctuationInEthnologueCode, ProcessEthnologueStore((PKMX_WCHAR)u"abc;def"));
|
|
}
|
|
|
|
// KMX_DWORD ProcessHotKey(PKMX_WCHAR p, KMX_DWORD *hk)
|
|
// void SetChecksum(PKMX_BYTE buf, PKMX_DWORD CheckSum, KMX_DWORD sz)
|
|
// void kmcmp::CheckStoreUsage(PFILE_KEYBOARD fk, int storeIndex, KMX_BOOL fIsStore, KMX_BOOL fIsOption, KMX_BOOL fIsCall)
|
|
// KMX_DWORD WriteCompiledKeyboard(PFILE_KEYBOARD fk, KMX_BYTE**data, size_t& dataSize)
|
|
// KMX_DWORD ReadLine(KMX_BYTE* infile, int sz, int& offset, PKMX_WCHAR wstr, KMX_BOOL PreProcess)
|
|
|
|
TEST_F(CompilerTest, GetRHS_test) {
|
|
KMX_WCHAR str[LINESIZE];
|
|
KMX_WCHAR tstr[128];
|
|
|
|
// KmnCompilerMessages::ERROR_NoTokensFound, empty string
|
|
u16cpy(str, u"");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, GetRHS(&fileKeyboard, str, tstr, 80, 0, FALSE));
|
|
|
|
// KmnCompilerMessages::ERROR_NoTokensFound, no '>'
|
|
u16cpy(str, u"abc");
|
|
EXPECT_EQ(KmnCompilerMessages::ERROR_NoTokensFound, GetRHS(&fileKeyboard, str, tstr, 80, 0, FALSE));
|
|
|
|
// STATUS_Success
|
|
u16cpy(str, u"> nul c\n");
|
|
EXPECT_EQ(STATUS_Success, GetRHS(&fileKeyboard, str, tstr, 80, 0, FALSE));
|
|
}
|
|
|
|
// void safe_wcsncpy(PKMX_WCHAR out, PKMX_WCHAR in, int cbMax)
|
|
// KMX_BOOL IsSameToken(PKMX_WCHAR *p, KMX_WCHAR const * token)
|
|
// static bool endsWith(const std::string& str, const std::string& suffix)
|
|
// KMX_DWORD ImportBitmapFile(PFILE_KEYBOARD fk, PKMX_WCHAR szName, PKMX_DWORD FileSize, PKMX_BYTE *Buf)
|
|
// int atoiW(PKMX_WCHAR p)
|
|
// KMX_DWORD kmcmp::CheckUTF16(int n)
|
|
|
|
TEST_F(CompilerTest, isIntegerWstring_test) {
|
|
EXPECT_FALSE(isIntegerWstring(nullptr));
|
|
EXPECT_FALSE(isIntegerWstring((PKMX_WCHAR)u""));
|
|
EXPECT_FALSE(isIntegerWstring((PKMX_WCHAR)u"a"));
|
|
EXPECT_TRUE(isIntegerWstring((PKMX_WCHAR)u"-1"));
|
|
EXPECT_TRUE(isIntegerWstring((PKMX_WCHAR)u"1"));
|
|
EXPECT_FALSE(isIntegerWstring((PKMX_WCHAR)u" 1"));
|
|
EXPECT_FALSE(isIntegerWstring((PKMX_WCHAR)u"1 "));
|
|
EXPECT_TRUE(isIntegerWstring((PKMX_WCHAR)u"42"));
|
|
EXPECT_TRUE(isIntegerWstring((PKMX_WCHAR)u"2147483647")); // INT_MAX
|
|
EXPECT_FALSE(isIntegerWstring((PKMX_WCHAR)u"2147483648")); // INT_MAX + 1
|
|
EXPECT_FALSE(isIntegerWstring((PKMX_WCHAR)u"9999999999")); // > INT_MAX
|
|
EXPECT_TRUE(isIntegerWstring((PKMX_WCHAR)u"-2147483648")); // -INT_MAX - 1
|
|
EXPECT_FALSE(isIntegerWstring((PKMX_WCHAR)u"-2147483649")); // -INT_MAX - 2
|
|
EXPECT_FALSE(isIntegerWstring((PKMX_WCHAR)u"-9999999999")); // < -INT_MAX - 1
|
|
}
|
|
|
|
// KMX_DWORD kmcmp::UTF32ToUTF16(int n, int *n1, int *n2)
|
|
// KMX_BOOL BuildVKDictionary(PFILE_KEYBOARD fk)
|
|
// int GetVKCode(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
|
// int GetDeadKey(PFILE_KEYBOARD fk, PKMX_WCHAR p)
|
|
// void kmcmp::RecordDeadkeyNames(PFILE_KEYBOARD fk)
|
|
// KMX_BOOL kmcmp::IsValidCallStore(PFILE_STORE fs)
|
|
|
|
TEST_F(CompilerTest, hasPreamble_test) {
|
|
EXPECT_FALSE(hasPreamble(u""));
|
|
EXPECT_FALSE(hasPreamble(u"\uFEFE")); // not \uFEFF
|
|
EXPECT_TRUE(hasPreamble(u"\uFEFF"));
|
|
EXPECT_FALSE(hasPreamble(u"a\uFEFF"));
|
|
}
|
|
|
|
// PFILE_STORE FindSystemStore(PFILE_KEYBOARD fk, KMX_DWORD dwSystemID)
|
|
|
|
// Helper to convert UTF-16 buffer to std::u16string
|
|
static std::u16string buffer_to_u16string(const KMX_BYTE* buf, int sz16) {
|
|
std::u16string out;
|
|
for (int i = 0; i < sz16; i += 2) {
|
|
char16_t ch = buf[i] | (buf[i+1] << 8);
|
|
out.push_back(ch);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
TEST(UTF16TempFromUTF8, HandlesValidUTF8WithoutBOM) {
|
|
const char* utf8 = "abc \xE2\x82\xAC"; // "abc €"
|
|
int sz = strlen(utf8);
|
|
KMX_BYTE* tempfile = nullptr;
|
|
int sz16 = 0;
|
|
ASSERT_TRUE(UTF16TempFromUTF8((KMX_BYTE*)utf8, sz, &tempfile, &sz16));
|
|
ASSERT_EQ(sz16, 10); // 5 UTF-16 code units * 2 bytes
|
|
std::u16string result = buffer_to_u16string(tempfile, sz16);
|
|
EXPECT_EQ(result, u"abc \u20AC");
|
|
delete[] tempfile;
|
|
}
|
|
|
|
TEST(UTF16TempFromUTF8, HandlesValidUTF8WithBOM) {
|
|
// UTF-8 BOM + "A"
|
|
const char utf8[] = { char(0xEF), char(0xBB), char(0xBF), 'A', 0 };
|
|
int sz = 4;
|
|
KMX_BYTE* tempfile = nullptr;
|
|
int sz16 = 0;
|
|
ASSERT_TRUE(UTF16TempFromUTF8((KMX_BYTE*)utf8, sz, &tempfile, &sz16));
|
|
ASSERT_EQ(sz16, 2); // Only 'A' (1 code unit) * 2 bytes
|
|
std::u16string result = buffer_to_u16string(tempfile, sz16);
|
|
EXPECT_EQ(result, u"A");
|
|
delete[] tempfile;
|
|
}
|
|
|
|
TEST(UTF16TempFromUTF8, HandlesInvalidUTF8FallbacksToCP1252) {
|
|
// 0x80 is invalid in UTF-8, should fallback to CP1252 (U+20AC)
|
|
const char invalid_utf8[] = { char(0x80), 0 };
|
|
int sz = 1;
|
|
KMX_BYTE* tempfile = nullptr;
|
|
int sz16 = 0;
|
|
ASSERT_TRUE(UTF16TempFromUTF8((KMX_BYTE*)invalid_utf8, sz, &tempfile, &sz16));
|
|
ASSERT_EQ(sz16, 2);
|
|
std::u16string result = buffer_to_u16string(tempfile, sz16);
|
|
EXPECT_EQ(result, u"\u20AC");
|
|
delete[] tempfile;
|
|
}
|
|
|
|
TEST(UTF16TempFromUTF8, HandlesEmptyInput) {
|
|
KMX_BYTE* tempfile = nullptr;
|
|
int sz16 = 0;
|
|
ASSERT_FALSE(UTF16TempFromUTF8(nullptr, 0, &tempfile, &sz16));
|
|
// tempfile should remain nullptr, sz16 should be 0
|
|
EXPECT_EQ(tempfile, nullptr);
|
|
EXPECT_EQ(sz16, 0);
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, ValidAscii) {
|
|
std::vector<KMX_BYTE> v = {'h', 'e', 'l', 'l', 'o'};
|
|
EXPECT_TRUE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Valid2Byte) {
|
|
std::vector<KMX_BYTE> v = {0xC2, 0xA2}; // U+00A2: ¢
|
|
EXPECT_TRUE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Valid3Byte) {
|
|
std::vector<KMX_BYTE> v = {0xE2, 0x82, 0xAC}; // U+20AC: €
|
|
EXPECT_TRUE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Valid4Byte) {
|
|
std::vector<KMX_BYTE> v = {0xF0, 0x9F, 0x98, 0x80}; // U+1F600: 😀
|
|
EXPECT_TRUE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, InvalidOverlongEncoding) {
|
|
std::vector<KMX_BYTE> v = {0xC1, 0x81}; // Overlong encoding for ASCII
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, InvalidMissingContinuation) {
|
|
std::vector<KMX_BYTE> v = {0xE2, 0x82}; // Missing one continuation byte
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, InvalidLoneContinuation) {
|
|
std::vector<KMX_BYTE> v = {0x80}; // Continuation byte without starter
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Invalid4ByteOutOfRange) {
|
|
std::vector<KMX_BYTE> v = {0xF4, 0x90, 0x80, 0x80}; // > U+10FFFF
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, ValidMixedAsciiAndMultiByte) {
|
|
std::vector<KMX_BYTE> v = {'A', 0xC2, 0xA2, 0xE2, 0x82, 0xAC, 0xF0, 0x9F, 0x98, 0x80};
|
|
EXPECT_TRUE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Invalid2ByteBadSecondByte) {
|
|
std::vector<KMX_BYTE> v = {0xD2, 0x28};
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Invalid2ByteBadSecondByteTooHigh) {
|
|
std::vector<KMX_BYTE> v = {0xD2, 0xC8};
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Invalid3ByteBadSecondByte) {
|
|
std::vector<KMX_BYTE> v = {0xE2, 0x28, 0xA1};
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Invalid3ByteBadThirdByte) {
|
|
std::vector<KMX_BYTE> v = {0xE2, 0xA8, 0xD1};
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Invalid4ByteBadSecondByte) {
|
|
std::vector<KMX_BYTE> v = {0xF2, 0xC8, 0xB2, 0x88};
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Invalid4ByteBadThirdByte) {
|
|
std::vector<KMX_BYTE> v = {0xF2, 0xB8, 0x02, 0x88};
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, Invalid4ByteBadFourthByte) {
|
|
std::vector<KMX_BYTE> v = {0xF2, 0xB8, 0xA2, 0xD8};
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, InvalidByteC0) {
|
|
std::vector<KMX_BYTE> v = {0xC1};
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, InvalidByteF5) {
|
|
std::vector<KMX_BYTE> v = {0xF5};
|
|
EXPECT_FALSE(isValidUtf8(v.data(), v.size()));
|
|
}
|
|
|
|
TEST(IsValidUtf8Test, ValidEmptyInput) {
|
|
std::vector<KMX_BYTE> v = {};
|
|
EXPECT_TRUE(isValidUtf8(v.data(), v.size()));
|
|
}
|