Skip to content

Commit 8b85d24

Browse files
committed
[CRT_APITEST] Add various _ismbc* tests not covered by Wine
Verified passing on Windows 7 and 10. CORE-19396
1 parent f2c0b5f commit 8b85d24

File tree

7 files changed

+283
-0
lines changed

7 files changed

+283
-0
lines changed
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
/*
2+
* PROJECT: ReactOS API tests
3+
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4+
* PURPOSE: Tests for _ismbc* functions
5+
* COPYRIGHT: Copyright 2025 Doug Lyons <[email protected]>
6+
* Copyright 2025 Stanislav Motylkov <[email protected]>
7+
*/
8+
9+
#include <apitest.h>
10+
#include <mbctype.h>
11+
#include <mbstring.h>
12+
#define WIN32_NO_STATUS
13+
14+
typedef int (__cdecl *PFN_chk)(unsigned int c, int cjk);
15+
typedef int (__cdecl *PFN__ismbc)(unsigned int c);
16+
static USHORT ver;
17+
18+
#ifndef TEST_STATIC_CRT
19+
#ifndef TEST_CRTDLL
20+
static PFN__ismbc p__ismbcalnum;
21+
static PFN__ismbc p__ismbcgraph;
22+
static PFN__ismbc p__ismbcpunct;
23+
#endif
24+
static PFN__ismbc p__ismbcalpha;
25+
static PFN__ismbc p__ismbcdigit;
26+
static PFN__ismbc p__ismbcprint;
27+
static PFN__ismbc p__ismbcsymbol;
28+
static PFN__ismbc p__ismbcspace;
29+
30+
static BOOL Init()
31+
{
32+
int fails = 0;
33+
HMODULE hdll = LoadLibraryA(TEST_DLL_NAME);
34+
35+
#ifndef TEST_CRTDLL
36+
p__ismbcalnum = (PFN__ismbc)GetProcAddress(hdll, "_ismbcalnum");
37+
ok(p__ismbcalnum != NULL, "Failed to load _ismbcalnum from %s\n", TEST_DLL_NAME);
38+
if (p__ismbcalnum == NULL) fails++;
39+
40+
p__ismbcgraph = (PFN__ismbc)GetProcAddress(hdll, "_ismbcgraph");
41+
ok(p__ismbcgraph != NULL, "Failed to load _ismbcgraph from %s\n", TEST_DLL_NAME);
42+
if (p__ismbcgraph == NULL) fails++;
43+
44+
p__ismbcpunct = (PFN__ismbc)GetProcAddress(hdll, "_ismbcpunct");
45+
ok(p__ismbcpunct != NULL, "Failed to load _ismbcpunct from %s\n", TEST_DLL_NAME);
46+
if (p__ismbcpunct == NULL) fails++;
47+
#endif
48+
49+
p__ismbcalpha = (PFN__ismbc)GetProcAddress(hdll, "_ismbcalpha");
50+
ok(p__ismbcalpha != NULL, "Failed to load _ismbcalpha from %s\n", TEST_DLL_NAME);
51+
if (p__ismbcalpha == NULL) fails++;
52+
53+
p__ismbcdigit = (PFN__ismbc)GetProcAddress(hdll, "_ismbcdigit");
54+
ok(p__ismbcdigit != NULL, "Failed to load _ismbcdigit from %s\n", TEST_DLL_NAME);
55+
if (p__ismbcdigit == NULL) fails++;
56+
57+
p__ismbcprint = (PFN__ismbc)GetProcAddress(hdll, "_ismbcprint");
58+
ok(p__ismbcprint != NULL, "Failed to load _ismbcprint from %s\n", TEST_DLL_NAME);
59+
if (p__ismbcprint == NULL) fails++;
60+
61+
p__ismbcsymbol = (PFN__ismbc)GetProcAddress(hdll, "_ismbcsymbol");
62+
ok(p__ismbcsymbol != NULL, "Failed to load _ismbcsymbol from %s\n", TEST_DLL_NAME);
63+
if (p__ismbcsymbol == NULL) fails++;
64+
65+
p__ismbcspace = (PFN__ismbc)GetProcAddress(hdll, "_ismbcspace");
66+
ok(p__ismbcspace != NULL, "Failed to load _ismbcspace from %s\n", TEST_DLL_NAME);
67+
if (p__ismbcspace == NULL) fails++;
68+
69+
return (fails == 0);
70+
}
71+
#define _ismbcalnum p__ismbcalnum
72+
#define _ismbcalpha p__ismbcalpha
73+
#define _ismbcdigit p__ismbcdigit
74+
#define _ismbcprint p__ismbcprint
75+
#define _ismbcsymbol p__ismbcsymbol
76+
#define _ismbcspace p__ismbcspace
77+
#define _ismbcgraph p__ismbcgraph
78+
#define _ismbcpunct p__ismbcpunct
79+
#endif
80+
81+
static USHORT GetWinVersion(VOID)
82+
{
83+
return ((GetVersion() & 0xFF) << 8) |
84+
((GetVersion() >> 8) & 0xFF);
85+
}
86+
87+
int CHK_ismbcalpha(unsigned int c, int cjk)
88+
{
89+
int ret = 0;
90+
if (!cjk)
91+
return ((c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a));
92+
93+
ret = CHK_ismbcalpha(c, 0) || (c >= 0xa6 && c <= 0xdf);
94+
if (ver >= 0x602)
95+
ret |= (
96+
(c >= 0x8152 && c <= 0x8155) || (c >= 0x8157 && c <= 0x815b) || c == 0x81f0 ||
97+
(c >= 0x8260 && c <= 0x8279) || (c >= 0x8281 && c <= 0x829a) || (c >= 0x829f && c <= 0x82f1) ||
98+
(c >= 0x8340 && c <= 0x837e) || (c >= 0x8380 && c <= 0x8396) || (c >= 0x839f && c <= 0x83b6) || (c >= 0x83bf && c <= 0x83d6) ||
99+
(c >= 0x8440 && c <= 0x8460) || (c >= 0x8470 && c <= 0x847e) || (c >= 0x8480 && c <= 0x8491) ||
100+
(c >= 0x8754 && c <= 0x875d) ||
101+
(c >= 0x889f && c <= 0x88fc) ||
102+
(((c >> 8) >= 0x89 && (c >> 8) <= 0x97) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
103+
(((c >> 8) == 0x98) && (((c & 255) >= 0x40 && (c & 255) <= 0x72) || ((c & 255) >= 0x9f && (c & 255) <= 0xfc))) ||
104+
(((c >> 8) >= 0x99 && (c >> 8) <= 0x9f) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
105+
(((c >> 8) >= 0xe0 && (c >> 8) <= 0xe9) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
106+
(((c >> 8) == 0xea) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xa4))) ||
107+
(((c >> 8) == 0xed) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
108+
(((c >> 8) == 0xee) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xec) || ((c & 255) >= 0xef && (c & 255) <= 0xf8))) ||
109+
(((c >> 8) == 0xfa) && (((c & 255) >= 0x40 && (c & 255) <= 0x53) || ((c & 255) >= 0x5c && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
110+
(((c >> 8) == 0xfb) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
111+
(c >= 0xfc40 && c <= 0xfc4b));
112+
return ret;
113+
}
114+
115+
int CHK_ismbcdigit(unsigned int c, int cjk)
116+
{
117+
if (!cjk || ver < 0x602)
118+
return (c >= 0x30 && c <= 0x39);
119+
else
120+
return (CHK_ismbcdigit(c, 0) || (c >= 0x824f && c <= 0x8258));
121+
}
122+
123+
int CHK_ismbcalnum(unsigned int c, int cjk)
124+
{
125+
return CHK_ismbcalpha(c, cjk) || CHK_ismbcdigit(c, cjk);
126+
}
127+
128+
int CHK_ismbcsymbol(unsigned int c, int cjk)
129+
{
130+
if (!cjk)
131+
#ifndef TEST_CRTDLL
132+
return 0;
133+
#else
134+
return CHK_ismbcsymbol(c, 1);
135+
#endif
136+
else
137+
return (c >= 0x8141 && c <= 0x817e) || (c >= 0x8180 && c <= 0x81ac);
138+
}
139+
140+
int CHK_ismbcspace(unsigned int c, int cjk)
141+
{
142+
if (!cjk || ver < 0x602)
143+
return (c == 0x20 || (c >= 0x09 && c <= 0x0D));
144+
else
145+
return (CHK_ismbcspace(c, 0) || c == 0x8140);
146+
}
147+
148+
int CHK_ismbcpunct(unsigned int c, int cjk)
149+
{
150+
int ret = 0;
151+
if (!cjk)
152+
return (c >= 0x21 && c <= 0x2f) || (c >= 0x3a && c <= 0x40) || (c >= 0x5b && c <= 0x60) || (c >= 0x7b && c <= 0x7e);
153+
154+
ret = CHK_ismbcpunct(c, 0) || (c >= 0xa1 && c <= 0xa5);
155+
if (ver >= 0x602)
156+
ret |= (c >= 0x8141 && c <= 0x8149) || c == 0x814c || c == 0x814e || c == 0x8151 || c == 0x8156 || (c >= 0x815c && c <= 0x815f) || (c >= 0x8163 && c <= 0x817a) || (c >= 0x817c && c <= 0x817e) ||
157+
c == 0x8180 || (c >= 0x818b && c <= 0x818d) || (c >= 0x8193 && c <= 0x8198) || c == 0x81a6 || c == 0x81f1 || (c >= 0x81f5 && c <= 0x81f7) ||
158+
(c >= 0x8780 && c <= 0x8781) ||
159+
(c >= 0xeefb && c <= 0xeefc) ||
160+
(c >= 0xfa56 && c <= 0xfa57);
161+
return ret;
162+
}
163+
164+
int CHK_ismbcgraph(unsigned int c, int cjk)
165+
{
166+
return CHK_ismbcalpha(c, cjk) || CHK_ismbcdigit(c, cjk) || CHK_ismbcpunct(c, cjk);
167+
}
168+
169+
int CHK_ismbcprint(unsigned int c, int cjk)
170+
{
171+
int ret = 0;
172+
if (!cjk)
173+
#ifndef TEST_CRTDLL
174+
return c == 0x20 ||
175+
CHK_ismbcsymbol(c, cjk) || CHK_ismbcgraph(c, cjk);
176+
#else
177+
{
178+
ret |= (c >= 0xa6 && c <= 0xdf) ||
179+
(((c >> 8) >= 0x81 && (c >> 8) <= 0x9f) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
180+
(((c >> 8) >= 0xe0 && (c >> 8) <= 0xef) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
181+
(((c >> 8) >= 0xfa && (c >> 8) <= 0xfc) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
182+
CHK_ismbcprint(c, 1);
183+
if (ver < 0x602)
184+
ret |= (((c >> 8) >= 0xf0 && (c >> 8) <= 0xf9) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc)));
185+
return ret;
186+
}
187+
#endif
188+
189+
ret = c == 0x20 || CHK_ismbcgraph(c, cjk);
190+
if (ver >= 0x602)
191+
ret |= c == 0x8140 ||
192+
(c >= 0x81b8 && c <= 0x81bf) || (c >= 0x81c8 && c <= 0x81ce) || (c >= 0x81da && c <= 0x81e8) || (c >= 0x81f2 && c <= 0x81f7) || c == 0x81fc ||
193+
(c >= 0x849f && c <= 0x84be) ||
194+
(c >= 0x8740 && c <= 0x875d) || (c >= 0x875f && c <= 0x8775) || c == 0x877e || (c >= 0x8782 && c <= 0x879c) ||
195+
(c >= 0xeef9 && c <= 0xeefa) ||
196+
(((c >> 8) >= 0xf0 && (c >> 8) <= 0xf9) && (((c & 255) >= 0x40 && (c & 255) <= 0x7e) || ((c & 255) >= 0x80 && (c & 255) <= 0xfc))) ||
197+
(c >= 0xfa54 && c <= 0xfa5b) ||
198+
CHK_ismbcsymbol(c, cjk);
199+
return ret;
200+
}
201+
202+
void TEST_ismbc(_In_opt_ PFN__ismbc func, _In_ LPCSTR name, _In_ PFN_chk chk)
203+
{
204+
int i, res, prev_cp = _getmbcp();
205+
206+
/* SBCS codepage */
207+
_setmbcp(1252);
208+
209+
for (i = 0; i < 0x10000; i++)
210+
{
211+
res = func(i);
212+
213+
if (chk(i, 0))
214+
{
215+
ok(res, "%s: Expected the character 0x%x to return TRUE, got FALSE\n", name, i);
216+
}
217+
else
218+
{
219+
ok(!res, "%s: Expected the character 0x%x to return FALSE, got TRUE\n", name, i);
220+
}
221+
}
222+
223+
/* MBCS (Japanese) codepage */
224+
_setmbcp(932);
225+
226+
#ifndef TEST_CRTDLL
227+
/* crtdll doesn't export _getmbcp/_setmbcp, and doesn't seem to handle code pages.
228+
* setlocale and SetThreadLocale are also being ignored. */
229+
for (i = 0; i < 0x10000; i++)
230+
{
231+
res = func(i);
232+
233+
if (chk(i, 1))
234+
{
235+
ok(res, "%s: Expected the character 0x%x to return TRUE, got FALSE\n", name, i);
236+
}
237+
else
238+
{
239+
ok(!res, "%s: Expected the character 0x%x to return FALSE, got TRUE\n", name, i);
240+
}
241+
}
242+
#endif
243+
244+
_setmbcp(prev_cp);
245+
}
246+
247+
START_TEST(_ismbc)
248+
{
249+
#ifndef TEST_STATIC_CRT
250+
if (!Init())
251+
{
252+
skip("Skipping tests, because some functions are not available\n");
253+
return;
254+
}
255+
#endif
256+
ver = GetWinVersion();
257+
258+
#ifndef TEST_CRTDLL
259+
TEST_ismbc(_ismbcalnum, "_ismbcalnum", CHK_ismbcalnum);
260+
#endif
261+
TEST_ismbc(_ismbcalpha, "_ismbcalpha", CHK_ismbcalpha);
262+
TEST_ismbc(_ismbcdigit, "_ismbcdigit", CHK_ismbcdigit);
263+
TEST_ismbc(_ismbcprint, "_ismbcprint", CHK_ismbcprint);
264+
TEST_ismbc(_ismbcsymbol, "_ismbcsymbol", CHK_ismbcsymbol);
265+
TEST_ismbc(_ismbcspace, "_ismbcspace", CHK_ismbcspace);
266+
// _ismbclegal() - covered by msvcrt:string
267+
// _ismbcl0() - covered by msvcrt:string
268+
// _ismbcl1() - covered by msvcrt:string
269+
// _ismbcl2() - covered by msvcrt:string
270+
#ifndef TEST_CRTDLL
271+
TEST_ismbc(_ismbcgraph, "_ismbcgraph", CHK_ismbcgraph);
272+
TEST_ismbc(_ismbcpunct, "_ismbcpunct", CHK_ismbcpunct);
273+
#endif
274+
}

modules/rostests/apitests/crt/static_crt_apitest.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
list(APPEND SOURCE_STATIC
3+
_ismbc.c
34
_mbsnbcat.c
45
_mbsncat.c
56
_snprintf.c

modules/rostests/apitests/crt/testlist.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define STANDALONE
33
#include <apitest.h>
44

5+
extern void func__ismbc(void);
56
extern void func__mbsnbcat(void);
67
extern void func__mbsncat(void);
78
extern void func__mbsncmp(void);
@@ -46,6 +47,7 @@ const struct test winetest_testlist[] =
4647
{
4748
{ "_vsnprintf", func__vsnprintf },
4849
{ "_vsnwprintf", func__vsnwprintf },
50+
{ "_ismbc", func__ismbc },
4951
{ "_mbsnbcat", func__mbsnbcat },
5052
{ "_mbsncat", func__mbsncat },
5153
{ "mbstowcs", func_mbstowcs },

modules/rostests/apitests/crtdll/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
list(APPEND SOURCE_CRTDLL
3+
../crt/_ismbc.c
34
../crt/_mbsnbcat.c
45
../crt/_mbsncat.c
56
../crt/_mbsncmp.c

modules/rostests/apitests/crtdll/testlist.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define STANDALONE
33
#include <apitest.h>
44

5+
extern void func__ismbc(void);
56
extern void func__mbsnbcat(void);
67
extern void func__mbsncat(void);
78
extern void func__mbsncmp(void);
@@ -24,6 +25,7 @@ extern void func_wctomb(void);
2425

2526
const struct test winetest_testlist[] =
2627
{
28+
{ "_ismbc", func__ismbc },
2729
{ "_mbsnbcat", func__mbsnbcat },
2830
{ "_mbsncat", func__mbsncat },
2931
{ "_mbsncmp", func__mbsncmp },

modules/rostests/apitests/msvcrt/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ endif()
99
list(APPEND SOURCE_CRT_TESTS
1010
../crt/fpcontrol.c
1111
../crt/_finite.c
12+
../crt/_ismbc.c
1213
../crt/_isnan.c
1314
../crt/_mbsnbcat.c
1415
../crt/_mbsncat.c

modules/rostests/apitests/msvcrt/testlist.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <apitest.h>
44

55
extern void func__finite(void);
6+
extern void func__ismbc(void);
67
extern void func__isnan(void);
78
extern void func__mbsnbcat(void);
89
extern void func__mbsncat(void);
@@ -61,6 +62,7 @@ extern void func_splitpath(void);
6162
const struct test winetest_testlist[] =
6263
{
6364
{ "_finite", func__finite },
65+
{ "_ismbc", func__ismbc },
6466
{ "_isnan", func__isnan },
6567
{ "_mbsnbcat", func__mbsnbcat },
6668
{ "_mbsncat", func__mbsncat },

0 commit comments

Comments
 (0)