Skip to content

Commit 0504f5c

Browse files
committed
[CRT_APITEST] Add _mbsn(b)cat tests based on Wine 10.0
These tests examine msvcrt, crtdll, and our static CRT. - msvcrt/crtdll verified passing on Windows 2003, 7 and 10. CORE-19308
1 parent fa92d95 commit 0504f5c

File tree

8 files changed

+195
-0
lines changed

8 files changed

+195
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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 _mbsnbcat
5+
* COPYRIGHT: Copyright 2025 Stanislav Motylkov <[email protected]>
6+
*/
7+
8+
#include <apitest.h>
9+
#include <mbstring.h>
10+
#define WIN32_NO_STATUS
11+
12+
typedef unsigned char *(__cdecl *PFN__mbsncat)(unsigned char*, const unsigned char*, size_t);
13+
14+
extern VOID mbsncat_PerformTests(_In_ LPSTR fname, _In_opt_ PFN__mbsncat func);
15+
16+
START_TEST(_mbsnbcat)
17+
{
18+
#ifndef TEST_STATIC_CRT
19+
#define _mbsnbcat NULL
20+
#endif
21+
mbsncat_PerformTests("_mbsnbcat", _mbsnbcat);
22+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
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 _mbsncat
5+
* COPYRIGHT: Copyright 2025 Doug Lyons <[email protected]>
6+
* Copyright 2025 Stanislav Motylkov <[email protected]>
7+
*/
8+
9+
#include <apitest.h>
10+
#include <mbstring.h>
11+
#define WIN32_NO_STATUS
12+
#include <pseh/pseh2.h>
13+
#include <ndk/mmfuncs.h>
14+
15+
typedef unsigned char *(__cdecl *PFN__mbsncat)(unsigned char*, const unsigned char*, size_t);
16+
17+
#ifndef TEST_STATIC_CRT
18+
static PFN__mbsncat Init(_In_ LPSTR fname)
19+
{
20+
static PFN__mbsncat p__mbsncat;
21+
HMODULE hdll = LoadLibraryA(TEST_DLL_NAME);
22+
23+
p__mbsncat = (PFN__mbsncat)GetProcAddress(hdll, fname);
24+
ok(p__mbsncat != NULL, "Failed to load %s from %s\n", fname, TEST_DLL_NAME);
25+
return p__mbsncat;
26+
}
27+
#endif
28+
29+
static USHORT GetWinVersion(VOID)
30+
{
31+
return ((GetVersion() & 0xFF) << 8) |
32+
((GetVersion() >> 8) & 0xFF);
33+
}
34+
35+
VOID mbsncat_PerformTests(_In_ LPSTR fname, _In_opt_ PFN__mbsncat func)
36+
{
37+
unsigned char dest[16];
38+
const unsigned char first[] = "dinosaur";
39+
const unsigned char second[] = "duck";
40+
unsigned char *s;
41+
BOOL MsVcrt = FALSE, CrtDll = FALSE;
42+
43+
#ifdef TEST_MSVCRT
44+
MsVcrt = TRUE;
45+
#endif
46+
#ifdef TEST_CRTDLL
47+
CrtDll = TRUE;
48+
#endif
49+
50+
#ifndef TEST_STATIC_CRT
51+
if (!func)
52+
func = Init(fname);
53+
#endif
54+
if (!func)
55+
{
56+
skip("Skipping tests, because %s is not available\n", fname);
57+
return;
58+
}
59+
60+
/* Test invalid arguments */
61+
StartSeh()
62+
s = func(NULL, NULL, 0);
63+
EndSeh(STATUS_SUCCESS);
64+
ok(s == NULL, "Expected %s to return NULL, got %p\n", fname, s);
65+
66+
StartSeh()
67+
s = func(NULL, NULL, 10);
68+
EndSeh((CrtDll || (MsVcrt && GetWinVersion() <= 0x502)) ? STATUS_ACCESS_VIOLATION : STATUS_SUCCESS);
69+
ok(s == NULL, "Expected %s to return NULL, got %p\n", fname, s);
70+
71+
memset(dest, 'X', sizeof(dest));
72+
StartSeh()
73+
s = func(dest, NULL, 0);
74+
EndSeh(STATUS_SUCCESS);
75+
ok(s == dest, "Expected %s to return dest pointer, got %p\n", fname, s);
76+
ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
77+
78+
memset(dest, 'X', sizeof(dest));
79+
StartSeh()
80+
s = func(dest, second, 0);
81+
EndSeh(STATUS_SUCCESS);
82+
ok(s == dest, "Expected %s to return dest pointer, got %p\n", fname, s);
83+
ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
84+
85+
memset(dest, 'X', sizeof(dest));
86+
s = NULL;
87+
StartSeh()
88+
s = func(dest, NULL, 10);
89+
EndSeh((CrtDll || (MsVcrt && GetWinVersion() <= 0x502)) ? STATUS_ACCESS_VIOLATION : STATUS_SUCCESS);
90+
ok(s == NULL, "Expected %s to return NULL, got %p\n", fname, s);
91+
ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
92+
93+
memset(dest, 'X', sizeof(dest));
94+
dest[0] = '\0';
95+
StartSeh()
96+
s = func(dest, second, sizeof(second));
97+
EndSeh(STATUS_SUCCESS);
98+
ok(s == dest, "Expected %s to return dest pointer, got %p\n", fname, s);
99+
ok(!memcmp(dest, second, sizeof(second)),
100+
"Expected the output buffer string to be \"duck\", got '%s'\n", dest);
101+
102+
/* Test source truncation behavior */
103+
memset(dest, 'X', sizeof(dest));
104+
memcpy(dest, first, sizeof(first));
105+
s = func(dest, second, 0);
106+
ok(s == dest, "Expected %s to return dest pointer, got %p\n", fname, s);
107+
ok(!memcmp(dest, first, sizeof(first)),
108+
"Expected the output buffer string to be \"dinosaur\", got '%s'\n", dest);
109+
110+
memset(dest, 'X', sizeof(dest));
111+
memcpy(dest, first, sizeof(first));
112+
s = func(dest, second, sizeof(second));
113+
ok(s == dest, "Expected %s to return dest pointer, got %p\n", fname, s);
114+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
115+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
116+
117+
memset(dest, 'X', sizeof(dest));
118+
memcpy(dest, first, sizeof(first));
119+
s = func(dest, second, sizeof(second) + 1);
120+
ok(s == dest, "Expected %s to return dest pointer, got %p\n", fname, s);
121+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
122+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
123+
124+
memset(dest, 'X', sizeof(dest));
125+
memcpy(dest, first, sizeof(first));
126+
s = func(dest, second, sizeof(second) - 1);
127+
ok(s == dest, "Expected %s to return dest pointer, got %p\n", fname, s);
128+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
129+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
130+
131+
memset(dest, 'X', sizeof(dest));
132+
memcpy(dest, first, sizeof(first));
133+
s = func(dest, second, sizeof(second) - 2);
134+
ok(s == dest, "Expected %s to return dest pointer, got %p\n", fname, s);
135+
ok(!memcmp(dest, "dinosaurduc", sizeof("dinosaurduc")),
136+
"Expected the output buffer string to be \"dinosaurduc\", got '%s'\n", dest);
137+
138+
/* Test typical scenario */
139+
memset(dest, 'X', sizeof(dest));
140+
memcpy(dest, first, sizeof(first));
141+
s = func(dest, second, sizeof(second) - 1);
142+
ok(s == dest, "Expected %s to return dest pointer, got %p\n", fname, s);
143+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
144+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
145+
146+
/* TODO: Add some distinguishing tests (_mbsncat vs. _mbsnbcat) for copying chars */
147+
}
148+
149+
START_TEST(_mbsncat)
150+
{
151+
#ifndef TEST_STATIC_CRT
152+
#define _mbsncat NULL
153+
#endif
154+
mbsncat_PerformTests("_mbsncat", _mbsncat);
155+
}

modules/rostests/apitests/crt/static_crt_apitest.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
list(APPEND SOURCE_STATIC
3+
_mbsnbcat.c
4+
_mbsncat.c
35
_snprintf.c
46
_snwprintf.c
57
_vscprintf.c

modules/rostests/apitests/crt/testlist.c

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

5+
extern void func__mbsnbcat(void);
6+
extern void func__mbsncat(void);
57
extern void func__mbsncmp(void);
68
extern void func__mbsstr(void);
79
#if defined(_M_ARM)
@@ -44,6 +46,8 @@ const struct test winetest_testlist[] =
4446
{
4547
{ "_vsnprintf", func__vsnprintf },
4648
{ "_vsnwprintf", func__vsnwprintf },
49+
{ "_mbsnbcat", func__mbsnbcat },
50+
{ "_mbsncat", func__mbsncat },
4751
{ "mbstowcs", func_mbstowcs },
4852
{ "mbtowc", func_mbtowc },
4953
{ "setjmp", func_setjmp },

modules/rostests/apitests/crtdll/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
list(APPEND SOURCE_CRTDLL
3+
../crt/_mbsnbcat.c
4+
../crt/_mbsncat.c
35
../crt/_mbsncmp.c
46
../crt/_mbsstr.c
57
../crt/setjmp.c

modules/rostests/apitests/crtdll/testlist.c

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

5+
extern void func__mbsnbcat(void);
6+
extern void func__mbsncat(void);
57
extern void func__mbsncmp(void);
68
extern void func__mbsstr(void);
79
extern void func__snprintf(void);
@@ -22,6 +24,8 @@ extern void func_wctomb(void);
2224

2325
const struct test winetest_testlist[] =
2426
{
27+
{ "_mbsnbcat", func__mbsnbcat },
28+
{ "_mbsncat", func__mbsncat },
2529
{ "_mbsncmp", func__mbsncmp },
2630
{ "_mbsstr", func__mbsstr },
2731
{ "_snprintf", func__snprintf },

modules/rostests/apitests/msvcrt/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ list(APPEND SOURCE_CRT_TESTS
1010
../crt/fpcontrol.c
1111
../crt/_finite.c
1212
../crt/_isnan.c
13+
../crt/_mbsnbcat.c
14+
../crt/_mbsncat.c
1315
../crt/_mbsncmp.c
1416
../crt/_mbsstr.c
1517
../crt/_snprintf.c

modules/rostests/apitests/msvcrt/testlist.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
extern void func__finite(void);
66
extern void func__isnan(void);
7+
extern void func__mbsnbcat(void);
8+
extern void func__mbsncat(void);
79
extern void func__mbsncmp(void);
810
extern void func__mbsstr(void);
911
extern void func__snprintf(void);
@@ -60,6 +62,8 @@ const struct test winetest_testlist[] =
6062
{
6163
{ "_finite", func__finite },
6264
{ "_isnan", func__isnan },
65+
{ "_mbsnbcat", func__mbsnbcat },
66+
{ "_mbsncat", func__mbsncat },
6367
{ "_mbsncmp", func__mbsncmp },
6468
{ "_mbsstr", func__mbsstr },
6569
{ "_snprintf", func__snprintf },

0 commit comments

Comments
 (0)