Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818/* * PROJECT: ReactOS API tests * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Tests for Char* functions * COPYRIGHT: Copyright 2022 Stanislav Motylkov <x86corez@gmail.com> */
#include "precomp.h"
#include <winnls.h>#include <ndk/rtlfuncs.h>#include <pseh/pseh2.h>#include <strsafe.h>#include <versionhelpers.h>
#define INVALID_PTR_OFF(x) ((PVOID)(ULONG_PTR)(0xdeadbeefdeadbeefULL + x))#define INVALID_PTR INVALID_PTR_OFF(0)
/* Default code page to be tested */#define TEST_ACP 1252
typedef enum{ testLen, testOffs, testBoth,} TEST_TYPE;
/* Dynamic allocation tests */typedef struct{ TEST_TYPE testType; LPWSTR lpszStart; /* Specified string for szStart */ LPWSTR lpszCurrent; /* Specified string for szCurrent (only when testType == testBoth) */ INT iOffset; /* Specified offset to test (only when testType == testOffs) */ INT iResOffset; /* Expected offset when szCurrent >= szStart */ INT iResOffsetNeg; /* Expected offset when szCurrent < szStart */ BOOL bWithinStart; /* TRUE for pointer expected to be within szStart, FALSE for within szCurrent */ BOOL bWideOnly; /* Perform test only for Unicode case */} TESTS_CHARPREV;
TESTS_CHARPREV TestCharPrev[] ={ {testLen, L"C:\\ReactOS", NULL, 0, 9, 9, TRUE, FALSE}, {testOffs, L"abcdefghijk", NULL, 11, 10, 10, TRUE, FALSE}, {testOffs, L"test a´^~¯", NULL, 10, 9, 9, TRUE, FALSE}, {testOffs, L"test å", NULL, 6, 5, 5, TRUE, FALSE}, {testBoth, L"C:\\ReactOS", L"", 0, -1, 0, FALSE, FALSE}, {testBoth, L"C:\\ReactOS\\", L"C:\\ReactOS", 0, -1, 0, FALSE, FALSE}, {testBoth, L"C:\\ReactOS\\", L"ReactOS", 0, -1, 0, FALSE, FALSE},};
TESTS_CHARPREV TestCharPrev_XP[] ={ /* XP/2003 treat diacritics as normal characters */ {testOffs, L"test a\x030a", NULL, 7, 6, 6, TRUE, TRUE}, {testOffs, L"test a\x0301\x0302\x0303\x0304", NULL, 10, 9, 9, TRUE, TRUE}, {testOffs, L"test a\x0301\x0302\x0303\x0304", NULL, 9, 8, 8, TRUE, TRUE}, {testOffs, L"test a\x0301\x0302\x0303\x0304", NULL, 8, 7, 7, TRUE, TRUE}, {testOffs, L"test a\x0301\x0302\x0303\x0304", NULL, 7, 6, 6, TRUE, TRUE},};
TESTS_CHARPREV TestCharPrev_Vista[] ={ /* Vista+ does respect diacritics and skip them */ {testOffs, L"test a\x030a", NULL, 7, 5, 5, TRUE, TRUE}, {testOffs, L"test a\x0301\x0302\x0303\x0304", NULL, 10, 5, 5, TRUE, TRUE}, {testOffs, L"test a\x0301\x0302\x0303\x0304", NULL, 9, 5, 5, TRUE, TRUE}, {testOffs, L"test a\x0301\x0302\x0303\x0304", NULL, 8, 5, 5, TRUE, TRUE}, {testOffs, L"test a\x0301\x0302\x0303\x0304", NULL, 7, 5, 5, TRUE, TRUE},};
/* Static tests */static const WCHAR wszReactOS[] = L"C:\\ReactOS";static const CHAR szReactOS[] = "C:\\ReactOS";static const WCHAR wszSpecial[] = L"test\0\0\0\0\0\0aa\t\t\t\r\n\r\n";static const CHAR szSpecial[] = "test\0\0\0\0\0\0aa\t\t\t\r\n\r\n";static const WCHAR wszMagic1[] = L"test a\x030a";static const WCHAR wszMagic2[] = L"test a\x0301\x0302\x0303\x0304";
static const CHAR szUTF8Cyril[] = "test \xD1\x82\xD0\xB5\xD1\x81\xD1\x82"; /* UTF8(L"test тест") */static const CHAR szUTF8Greek[] = "test \xCF\x84\xCE\xB5\xCF\x83\xCF\x84"; /* UTF8(L"test τεστ") */static const CHAR szUTF8Japan[] = "test \xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88"; /* UTF8(L"test テスト") */static const CHAR szCP932Japan[] = "test \x83\x65\x83\x58\x83\x67"; /* CP932(L"test テスト") */
typedef struct{ LPCWSTR wszStart; LPCWSTR wszCurrent; LPCWSTR wszResult; LPCSTR szStart; LPCSTR szCurrent; LPCSTR szResult;} ST_TESTS_CHARPREV;
ST_TESTS_CHARPREV TestStaticCharPrev[] ={ {wszReactOS, wszReactOS, wszReactOS, szReactOS, szReactOS, szReactOS}, {wszReactOS, wszReactOS + 1, wszReactOS, szReactOS, szReactOS + 1, szReactOS}, {wszReactOS, wszReactOS + 2, wszReactOS + 1, szReactOS, szReactOS + 2, szReactOS + 1}, {wszReactOS, wszReactOS + 3, wszReactOS + 2, szReactOS, szReactOS + 3, szReactOS + 2}, {wszReactOS, wszReactOS + 10, wszReactOS + 9, szReactOS, szReactOS + 10, szReactOS + 9},
{wszReactOS + 2, wszReactOS, wszReactOS, szReactOS + 2, szReactOS, szReactOS}, {wszReactOS + 2, wszReactOS + 1, wszReactOS + 1, szReactOS + 2, szReactOS + 1, szReactOS + 1}, {wszReactOS + 2, wszReactOS + 2, wszReactOS + 2, szReactOS + 2, szReactOS + 2, szReactOS + 2}, {wszReactOS + 2, wszReactOS + 3, wszReactOS + 2, szReactOS + 2, szReactOS + 3, szReactOS + 2}, {wszReactOS + 2, wszReactOS + 4, wszReactOS + 3, szReactOS + 2, szReactOS + 4, szReactOS + 3},
/* Test null-terminators */ {wszSpecial, wszSpecial + 8, wszSpecial + 7, szSpecial, szSpecial + 8, szSpecial + 7},
/* Test tabulation */ {wszSpecial, wszSpecial + 13, wszSpecial + 12, szSpecial, szSpecial + 13, szSpecial + 12},
/* Test linebreak */ {wszSpecial, wszSpecial + 17, wszSpecial + 16, szSpecial, szSpecial + 17, szSpecial + 16}, {wszSpecial, wszSpecial + 18, wszSpecial + 17, szSpecial, szSpecial + 18, szSpecial + 17},};
ST_TESTS_CHARPREV TestStaticCharPrev_XP[] ={ /* XP/2003 treat diacritics as normal characters */ {wszMagic1, wszMagic1 + 7, wszMagic1 + 6, NULL, NULL, NULL}, {wszMagic2, wszMagic2 + 10, wszMagic2 + 9, NULL, NULL, NULL}, {wszMagic2, wszMagic2 + 9, wszMagic2 + 8, NULL, NULL, NULL}, {wszMagic2, wszMagic2 + 8, wszMagic2 + 7, NULL, NULL, NULL}, {wszMagic2, wszMagic2 + 7, wszMagic2 + 6, NULL, NULL, NULL},};
ST_TESTS_CHARPREV TestStaticCharPrev_Vista[] ={ /* Vista+ does respect diacritics and skip them */ {wszMagic1, wszMagic1 + 7, wszMagic1 + 5, NULL, NULL, NULL}, {wszMagic2, wszMagic2 + 10, wszMagic2 + 5, NULL, NULL, NULL}, {wszMagic2, wszMagic2 + 9, wszMagic2 + 5, NULL, NULL, NULL}, {wszMagic2, wszMagic2 + 8, wszMagic2 + 5, NULL, NULL, NULL}, {wszMagic2, wszMagic2 + 7, wszMagic2 + 5, NULL, NULL, NULL},};
typedef struct{ UINT uCodePage; LPCSTR szStart; LPCSTR szCurrent; LPCSTR szResult;} ST_CODEPAGE_TESTS_CHARPREV;
ST_CODEPAGE_TESTS_CHARPREV TestStaticCodePageCharPrev[] ={ /* UTF-8 characters are not properly counted */ {CP_UTF8, szUTF8Cyril, szUTF8Cyril + 2, szUTF8Cyril + 1}, {CP_UTF8, szUTF8Cyril, szUTF8Cyril + 7, szUTF8Cyril + 6}, {CP_UTF8, szUTF8Cyril, szUTF8Cyril + 9, szUTF8Cyril + 8},
{CP_UTF8, szUTF8Greek, szUTF8Greek + 7, szUTF8Greek + 6}, {CP_UTF8, szUTF8Greek, szUTF8Greek + 9, szUTF8Greek + 8},
{CP_UTF8, szUTF8Japan, szUTF8Japan + 8, szUTF8Japan + 7}, {CP_UTF8, szUTF8Japan, szUTF8Japan + 11, szUTF8Japan + 10},
/* Code Page 932 / Shift-JIS characters are properly counted */ {932, szCP932Japan, szCP932Japan + 2, szCP932Japan + 1}, {932, szCP932Japan, szCP932Japan + 7, szCP932Japan + 5}, {932, szCP932Japan, szCP932Japan + 9, szCP932Japan + 7},};
typedef struct{ LPCWSTR wszString; LPCWSTR wszResult; LPCSTR szString; LPCSTR szResult;} ST_TESTS_CHARNEXT;
ST_TESTS_CHARNEXT TestStaticCharNext[] ={ {wszReactOS, wszReactOS + 1, szReactOS, szReactOS + 1}, {wszReactOS + 1, wszReactOS + 2, szReactOS + 1, szReactOS + 2}, {wszReactOS + 2, wszReactOS + 3, szReactOS + 2, szReactOS + 3}, {wszReactOS + 9, wszReactOS + 10, szReactOS + 9, szReactOS + 10}, {wszReactOS + 10, wszReactOS + 10, szReactOS + 10, szReactOS + 10},
/* Test null-terminators */ {wszSpecial + 3, wszSpecial + 4, szSpecial + 3, szSpecial + 4}, {wszSpecial + 4, wszSpecial + 4, szSpecial + 4, szSpecial + 4}, {wszSpecial + 5, wszSpecial + 5, szSpecial + 5, szSpecial + 5},
/* Test tabulation */ {wszSpecial + 12, wszSpecial + 13, szSpecial + 12, szSpecial + 13},
/* Test linebreak */ {wszSpecial + 15, wszSpecial + 16, szSpecial + 15, szSpecial + 16}, {wszSpecial + 16, wszSpecial + 17, szSpecial + 16, szSpecial + 17},};
ST_TESTS_CHARNEXT TestStaticCharNext_XP[] ={ /* XP/2003 treat diacritics as normal characters */ {wszMagic1 + 5, wszMagic1 + 6, NULL, NULL}, {wszMagic2 + 5, wszMagic2 + 6, NULL, NULL}, {wszMagic2 + 6, wszMagic2 + 7, NULL, NULL}, {wszMagic2 + 7, wszMagic2 + 8, NULL, NULL}, {wszMagic2 + 8, wszMagic2 + 9, NULL, NULL},};
ST_TESTS_CHARNEXT TestStaticCharNext_Vista[] ={ /* Vista+ does respect diacritics and skip them */ {wszMagic1 + 5, wszMagic1 + 7, NULL, NULL}, {wszMagic2 + 5, wszMagic2 + 10, NULL, NULL}, {wszMagic2 + 6, wszMagic2 + 10, NULL, NULL}, {wszMagic2 + 7, wszMagic2 + 10, NULL, NULL}, {wszMagic2 + 8, wszMagic2 + 10, NULL, NULL},};
typedef struct{ UINT uCodePage; LPCSTR szString; LPCSTR szResult;} ST_CODEPAGE_TESTS_CHARNEXT;
ST_CODEPAGE_TESTS_CHARNEXT TestStaticCodePageCharNext[] ={ /* UTF-8 characters are not properly counted */ {CP_UTF8, szUTF8Cyril, szUTF8Cyril + 1}, {CP_UTF8, szUTF8Cyril + 4, szUTF8Cyril + 5}, {CP_UTF8, szUTF8Cyril + 5, szUTF8Cyril + 6}, {CP_UTF8, szUTF8Cyril + 7, szUTF8Cyril + 8},
{CP_UTF8, szUTF8Greek + 5, szUTF8Greek + 6}, {CP_UTF8, szUTF8Greek + 7, szUTF8Greek + 8},
{CP_UTF8, szUTF8Japan + 5, szUTF8Japan + 6}, {CP_UTF8, szUTF8Japan + 8, szUTF8Japan + 9},
/* Code Page 932 / Shift-JIS characters are properly counted */ {932, szCP932Japan, szCP932Japan + 1}, {932, szCP932Japan + 5, szCP932Japan + 7}, {932, szCP932Japan + 7, szCP932Japan + 9},};
/* Exception tests (corner cases) */typedef struct{ LPCWSTR wszStart; LPCWSTR wszCurrent; LPCWSTR wszResult; LPCSTR szStart; LPCSTR szCurrent; LPCSTR szResult; LPCSTR szExResult; NTSTATUS resStatus;} EX_TESTS_CHARPREV;
EX_TESTS_CHARPREV TestExceptionCharPrev[] ={ {wszReactOS, NULL, NULL, szReactOS, NULL, NULL, NULL, STATUS_SUCCESS}, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, STATUS_SUCCESS}, {NULL, wszReactOS, wszReactOS - 1, NULL, szReactOS, szReactOS - 1, szReactOS - 1, STATUS_SUCCESS},
{INVALID_PTR, NULL, NULL, INVALID_PTR, NULL, NULL, NULL, STATUS_SUCCESS}, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, STATUS_SUCCESS}, {NULL, INVALID_PTR, NULL, NULL, INVALID_PTR, INVALID_PTR_OFF(-1) /* NULL on Win7 with updates */, NULL, STATUS_ACCESS_VIOLATION},
{wszReactOS, INVALID_PTR, NULL, szReactOS, INVALID_PTR, INVALID_PTR_OFF(-1) /* NULL on Win7 with updates */, NULL, STATUS_ACCESS_VIOLATION}, {INVALID_PTR, INVALID_PTR, INVALID_PTR, INVALID_PTR, INVALID_PTR, INVALID_PTR, INVALID_PTR, STATUS_SUCCESS}, {INVALID_PTR, wszReactOS, wszReactOS, INVALID_PTR, szReactOS, szReactOS, szReactOS, STATUS_SUCCESS},
{INVALID_PTR_OFF(-2), INVALID_PTR, NULL, INVALID_PTR_OFF(-2), INVALID_PTR, INVALID_PTR_OFF(-1) /* NULL on Win7 with updates */, NULL, STATUS_ACCESS_VIOLATION}, {INVALID_PTR, INVALID_PTR_OFF(2), NULL, INVALID_PTR, INVALID_PTR_OFF(2), INVALID_PTR_OFF(1) /* NULL on Win7 with updates */, NULL, STATUS_ACCESS_VIOLATION}, {INVALID_PTR, INVALID_PTR_OFF(-2), INVALID_PTR_OFF(-2), INVALID_PTR, INVALID_PTR_OFF(-2), INVALID_PTR_OFF(-2), INVALID_PTR_OFF(-2), STATUS_SUCCESS}, {INVALID_PTR_OFF(2), INVALID_PTR, INVALID_PTR, INVALID_PTR_OFF(2), INVALID_PTR, INVALID_PTR, INVALID_PTR, STATUS_SUCCESS},};
typedef struct{ LPCWSTR wszString; LPCWSTR wszResult; LPCSTR szString; LPCSTR szResult; NTSTATUS resStatus;} EX_TESTS_CHARNEXT;
EX_TESTS_CHARNEXT TestExceptionCharNext[] ={ {wszReactOS, wszReactOS + 1, szReactOS, szReactOS + 1, STATUS_SUCCESS}, {NULL, NULL, NULL, NULL, STATUS_ACCESS_VIOLATION}, {INVALID_PTR, NULL, INVALID_PTR, NULL, STATUS_ACCESS_VIOLATION},
{INVALID_PTR_OFF(-2), NULL, INVALID_PTR_OFF(-2), NULL, STATUS_ACCESS_VIOLATION}, {INVALID_PTR_OFF(2), NULL, INVALID_PTR_OFF(2), NULL, STATUS_ACCESS_VIOLATION},};
static LPWSTR AllocStringW(LPWSTR lpszStr, SIZE_T len){ LPWSTR str; SIZE_T sz;
if (!lpszStr) return NULL;
sz = (len + 1) * sizeof(lpszStr[0]); str = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz); if (!str) { trace("HeapAlloc failed (error %ld)\n", GetLastError()); goto Skip; } StringCbCopyW(str, sz, lpszStr);Skip: return str;}
static LPSTR AllocStringA(LPWSTR lpszStr, SIZE_T len){ LPSTR str; SIZE_T sz, mbs;
if (!lpszStr) return NULL;
sz = len + 1; str = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz); if (!str) { trace("HeapAlloc failed (error %ld)\n", GetLastError()); goto Skip; }
mbs = WideCharToMultiByte(TEST_ACP, 0, lpszStr, -1, NULL, 0, NULL, NULL); if (!mbs || mbs > sz) { HeapFree(GetProcessHeap(), 0, str); str = NULL; trace("WideCharToMultiByte returned %lu (error %ld)\n", mbs, GetLastError()); goto Skip; }
WideCharToMultiByte(TEST_ACP, 0, lpszStr, -1, str, mbs, NULL, NULL);Skip: return str;}
static void testCharPrevW(const TESTS_CHARPREV *pEntry, SIZE_T len, UINT i){ LPWSTR wszStart, wszCurrent; LPWSTR pchW; INT iRealOffset; BOOL b;
wszStart = AllocStringW(pEntry->lpszStart, len); if (!wszStart && pEntry->lpszStart) { skip("[%u] AllocStringW for wszStart failed\n", i); goto Cleanup; } if (pEntry->testType == testLen) wszCurrent = wszStart + len; else if (pEntry->testType == testOffs) wszCurrent = wszStart + pEntry->iOffset; else { wszCurrent = AllocStringW(pEntry->lpszCurrent, wcslen(pEntry->lpszCurrent)); if (!wszCurrent && pEntry->lpszCurrent) { skip("[%u] AllocStringW for wszCurrent failed\n", i); goto Cleanup; } } pchW = CharPrevW(wszStart, wszCurrent); if (wszCurrent - wszStart >= 0) iRealOffset = pEntry->iResOffset; else iRealOffset = pEntry->iResOffsetNeg; if (pEntry->bWithinStart) { b = pchW >= wszStart && pchW <= wszStart + len; if (iRealOffset >= 0) ok(b, "[%u] CharPrevW: pchW (0x%p) is expected to be within wszStart (0x%p)\n", i, pchW, wszStart); else ok(!b, "[%u] CharPrevW: pchW (0x%p) is expected to be outside wszStart (0x%p)\n", i, pchW, wszStart); ok(pchW == wszStart + iRealOffset, "[%u] CharPrevW: pchW is 0x%p (offset %d)\n", i, pchW, pchW - wszStart); } else { b = pchW >= wszCurrent && pchW <= wszCurrent + wcslen(pEntry->lpszCurrent); if (iRealOffset >= 0) ok(b, "[%u] CharPrevW: pchW (0x%p) is expected to be within wszCurrent (0x%p)\n", i, pchW, wszCurrent); else ok(!b, "[%u] CharPrevW: pchW (0x%p) is expected to be outside wszCurrent (0x%p)\n", i, pchW, wszCurrent); ok(pchW == wszCurrent + iRealOffset, "[%u] CharPrevW: pchW is 0x%p (offset %d)\n", i, pchW, pchW - wszCurrent); }
Cleanup: if (pEntry->testType != testBoth) wszCurrent = NULL; HeapFree(GetProcessHeap(), 0, wszStart); HeapFree(GetProcessHeap(), 0, wszCurrent);}
static void testCharPrevA(const TESTS_CHARPREV *pEntry, SIZE_T len, UINT i){ LPSTR szStart, szCurrent; LPSTR pchA, pchEx; INT iRealOffset; BOOL b;
szStart = AllocStringA(pEntry->lpszStart, len); if (!szStart && pEntry->lpszStart) { skip("[%u] AllocStringA for szStart failed\n", i); goto Cleanup; } if (pEntry->testType == testLen) szCurrent = szStart + len; else if (pEntry->testType == testOffs) szCurrent = szStart + pEntry->iOffset; else { szCurrent = AllocStringA(pEntry->lpszCurrent, wcslen(pEntry->lpszCurrent)); if (!szCurrent && pEntry->lpszCurrent) { skip("[%u] AllocStringA for szCurrent failed\n", i); goto Cleanup; } } pchA = CharPrevA(szStart, szCurrent); pchEx = CharPrevExA(TEST_ACP, szStart, szCurrent, 0); if (szCurrent - szStart >= 0) iRealOffset = pEntry->iResOffset; else iRealOffset = pEntry->iResOffsetNeg; if (pEntry->bWithinStart) { b = pchA >= szStart && pchA <= szStart + len; if (iRealOffset >= 0) ok(b, "[%u] CharPrevA: pchA (0x%p) is expected to be within szStart (0x%p)\n", i, pchA, szStart); else ok(!b, "[%u] CharPrevA: pchA (0x%p) is expected to be outside szStart (0x%p)\n", i, pchA, szStart); ok(pchA == szStart + iRealOffset, "[%u] CharPrevA: pchA is 0x%p (offset %d)\n", i, pchA, pchA - szStart); } else { b = pchA >= szCurrent && pchA <= szCurrent + wcslen(pEntry->lpszCurrent); if (iRealOffset >= 0) ok(b, "[%u] CharPrevA: pchA (0x%p) is expected to be within szCurrent (0x%p)\n", i, pchA, szCurrent); else ok(!b, "[%u] CharPrevA: pchA (0x%p) is expected to be outside szCurrent (0x%p)\n", i, pchA, szCurrent); ok(pchA == szCurrent + iRealOffset, "[%u] CharPrevA: pchA is 0x%p (offset %d)\n", i, pchA, pchA - szCurrent); } ok(pchA == pchEx, "[%u] CharPrevExA: pchA (0x%p) is not equal to pchEx (0x%p)\n", i, pchA, pchEx);
Cleanup: if (pEntry->testType != testBoth) szCurrent = NULL; HeapFree(GetProcessHeap(), 0, szStart); HeapFree(GetProcessHeap(), 0, szCurrent);}
static void testDynCharPrev(const TESTS_CHARPREV *pEntry, UINT i){ SIZE_T len;
len = wcslen(pEntry->lpszStart); testCharPrevW(pEntry, len, i);
if (pEntry->bWideOnly) return;
testCharPrevA(pEntry, len, i);}
static void testStatCharPrev(const ST_TESTS_CHARPREV *pEntry, UINT i){ LPWSTR pchW; LPSTR pchA;
pchW = CharPrevW(pEntry->wszStart, pEntry->wszCurrent); ok(pchW == pEntry->wszResult, "[%u] CharPrevW: pchW is 0x%p (expected 0x%p)\n", i, pchW, pEntry->wszResult);
if (!pEntry->szStart) return;
pchA = CharPrevA(pEntry->szStart, pEntry->szCurrent); ok(pchA == pEntry->szResult, "[%u] CharPrevA: pchA is 0x%p (expected 0x%p)\n", i, pchA, pEntry->szResult);
pchA = CharPrevExA(TEST_ACP, pEntry->szStart, pEntry->szCurrent, 0); ok(pchA == pEntry->szResult, "[%u] CharPrevExA: pchA is 0x%p (expected 0x%p)\n", i, pchA, pEntry->szResult);}
static void testStatCodePageCharPrev(const ST_CODEPAGE_TESTS_CHARPREV *pEntry, UINT i){ LPSTR pchA;
pchA = CharPrevExA(pEntry->uCodePage, pEntry->szStart, pEntry->szCurrent, 0); ok(pchA == pEntry->szResult, "[%u] CharPrevExA(%u): pchA is 0x%p (expected 0x%p)\n", i, pEntry->uCodePage, pchA, pEntry->szResult);}
static void testStatCharNext(const ST_TESTS_CHARNEXT *pEntry, UINT i){ LPWSTR pchW; LPSTR pchA;
pchW = CharNextW(pEntry->wszString); ok(pchW == pEntry->wszResult, "[%u] CharNextW: pchW is 0x%p (expected 0x%p)\n", i, pchW, pEntry->wszResult);
if (!pEntry->szString) return;
pchA = CharNextA(pEntry->szString); ok(pchA == pEntry->szResult, "[%u] CharNextA: pchA is 0x%p (expected 0x%p)\n", i, pchA, pEntry->szResult);
pchA = CharNextExA(TEST_ACP, pEntry->szString, 0); ok(pchA == pEntry->szResult, "[%u] CharNextExA: pchA is 0x%p (expected 0x%p)\n", i, pchA, pEntry->szResult);}
static void testStatCodePageCharNext(const ST_CODEPAGE_TESTS_CHARNEXT *pEntry, UINT i){ LPSTR pchA;
pchA = CharNextExA(pEntry->uCodePage, pEntry->szString, 0); ok(pchA == pEntry->szResult, "[%u] CharNextExA(%u): pchA is 0x%p (expected 0x%p)\n", i, pEntry->uCodePage, pchA, pEntry->szResult);}
static void testCharPrev(void){ UINT i;
/* Perform dynamic allocation tests */ for (i = 0; i < _countof(TestCharPrev); i++) { testDynCharPrev(&TestCharPrev[i], i); }
if (!IsWindowsVistaOrGreater()) { for (i = 0; i < _countof(TestCharPrev_XP); i++) { testDynCharPrev(&TestCharPrev_XP[i], i); } } else { for (i = 0; i < _countof(TestCharPrev_Vista); i++) { testDynCharPrev(&TestCharPrev_Vista[i], i); } }
/* Perform static tests */ for (i = 0; i < _countof(TestStaticCharPrev); i++) { testStatCharPrev(&TestStaticCharPrev[i], i); }
if (!IsWindowsVistaOrGreater()) { for (i = 0; i < _countof(TestStaticCharPrev_XP); i++) { testStatCharPrev(&TestStaticCharPrev_XP[i], i); } } else { for (i = 0; i < _countof(TestStaticCharPrev_Vista); i++) { testStatCharPrev(&TestStaticCharPrev_Vista[i], i); } }
for (i = 0; i < _countof(TestStaticCodePageCharPrev); i++) { testStatCodePageCharPrev(&TestStaticCodePageCharPrev[i], i); }
/* Perform exception tests (check corner cases) */ if (INVALID_PTR < (PVOID)wszReactOS) { ok(FALSE, "testCharPrev: unexpected INVALID PTR < wszReactOS\n"); return; } if (INVALID_PTR < (PVOID)szReactOS) { ok(FALSE, "testCharPrev: unexpected INVALID PTR < szReactOS\n"); return; }
for (i = 0; i < _countof(TestExceptionCharPrev); i++) { LPWSTR pchW; LPSTR pchA; const EX_TESTS_CHARPREV *pEntry = &TestExceptionCharPrev[i]; NTSTATUS Status = STATUS_SUCCESS;
//trace("0x%p 0x%p\n", pEntry->wszStart, pEntry->wszCurrent); pchW = NULL; _SEH2_TRY { pchW = CharPrevW(pEntry->wszStart, pEntry->wszCurrent); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; ok(Status == pEntry->resStatus, "[%u] CharPrevW: Status is 0x%lX, expected 0x%lX\n", i, Status, pEntry->resStatus); ok(pchW == pEntry->wszResult, "[%u] CharPrevW: pchW is 0x%p, expected 0x%p\n", i, pchW, pEntry->wszResult);
//trace("0x%p 0x%p\n", pEntry->szStart, pEntry->szCurrent); pchA = NULL; _SEH2_TRY { pchA = CharPrevA(pEntry->szStart, pEntry->szCurrent); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; ok(Status == pEntry->resStatus, "[%u] CharPrevA: Status is 0x%lX, expected 0x%lX\n", i, Status, pEntry->resStatus); ok(pchA == pEntry->szResult, "[%u] CharPrevA: pchA is 0x%p, expected 0x%p\n", i, pchA, pEntry->szResult);
pchA = NULL; _SEH2_TRY { pchA = CharPrevExA(TEST_ACP, pEntry->szStart, pEntry->szCurrent, 0); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; ok(Status == pEntry->resStatus, "[%u] CharPrevExA: Status is 0x%lX, expected 0x%lX\n", i, Status, pEntry->resStatus); ok(pchA == pEntry->szExResult, "[%u] CharPrevExA: pchA is 0x%p, expected 0x%p\n", i, pchA, pEntry->szExResult); }}
static void testCharNext(void){ UINT i;
/* Perform static tests */ for (i = 0; i < _countof(TestStaticCharNext); i++) { testStatCharNext(&TestStaticCharNext[i], i); }
if (!IsWindowsVistaOrGreater()) { for (i = 0; i < _countof(TestStaticCharNext_XP); i++) { testStatCharNext(&TestStaticCharNext_XP[i], i); } } else { for (i = 0; i < _countof(TestStaticCharNext_Vista); i++) { testStatCharNext(&TestStaticCharNext_Vista[i], i); } }
for (i = 0; i < _countof(TestStaticCodePageCharNext); i++) { testStatCodePageCharNext(&TestStaticCodePageCharNext[i], i); }
/* Perform exception tests (check corner cases) */ if (INVALID_PTR < (PVOID)wszReactOS) { ok(FALSE, "testCharNext: unexpected INVALID PTR < wszReactOS\n"); return; } if (INVALID_PTR < (PVOID)szReactOS) { ok(FALSE, "testCharNext: unexpected INVALID PTR < szReactOS\n"); return; }
for (i = 0; i < _countof(TestExceptionCharNext); i++) { LPWSTR pchW; LPSTR pchA; const EX_TESTS_CHARNEXT *pEntry = &TestExceptionCharNext[i]; NTSTATUS Status = STATUS_SUCCESS;
//trace("0x%p\n", pEntry->wszString); pchW = NULL; _SEH2_TRY { pchW = CharNextW(pEntry->wszString); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; ok(Status == pEntry->resStatus, "[%u] CharNextW: Status is 0x%lX, expected 0x%lX\n", i, Status, pEntry->resStatus); ok(pchW == pEntry->wszResult, "[%u] CharNextW: pchW is 0x%p, expected 0x%p\n", i, pchW, pEntry->wszResult);
//trace("0x%p 0x%p\n", pEntry->szString); pchA = NULL; _SEH2_TRY { pchA = CharNextA(pEntry->szString); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; ok(Status == pEntry->resStatus, "[%u] CharNextA: Status is 0x%lX, expected 0x%lX\n", i, Status, pEntry->resStatus); ok(pchA == pEntry->szResult, "[%u] CharNextA: pchA is 0x%p, expected 0x%p\n", i, pchA, pEntry->szResult);
pchA = NULL; _SEH2_TRY { pchA = CharNextExA(TEST_ACP, pEntry->szString, 0); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; ok(Status == pEntry->resStatus, "[%u] CharNextExA: Status is 0x%lX, expected 0x%lX\n", i, Status, pEntry->resStatus); ok(pchA == pEntry->szResult, "[%u] CharNextExA: pchA is 0x%p, expected 0x%p\n", i, pchA, pEntry->szResult); }}
START_TEST(CharFuncs){ testCharPrev(); testCharNext();}