Skip to content

Commit 7a03a13

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 7a03a13

File tree

8 files changed

+308
-0
lines changed

8 files changed

+308
-0
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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 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+
#ifndef TEST_STATIC_CRT
16+
unsigned char *(__cdecl *p__mbsnbcat)(unsigned char*,const unsigned char*,size_t);
17+
18+
static BOOL Init(void)
19+
{
20+
HMODULE hdll = LoadLibraryA(TEST_DLL_NAME);
21+
22+
p__mbsnbcat = (void *)GetProcAddress(hdll, "_mbsnbcat");
23+
ok(p__mbsnbcat != NULL, "Failed to load _mbsnbcat from %s\n", TEST_DLL_NAME);
24+
return (p__mbsnbcat != NULL);
25+
}
26+
#define _mbsnbcat p__mbsnbcat
27+
#endif
28+
29+
static USHORT GetWinVersion(VOID)
30+
{
31+
return ((GetVersion() & 0xFF) << 8) |
32+
((GetVersion() >> 8) & 0xFF);
33+
}
34+
35+
START_TEST(_mbsnbcat)
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 (!Init())
52+
{
53+
skip("Skipping tests, because _mbsnbcat is not available\n");
54+
return;
55+
}
56+
#endif
57+
58+
/* Test invalid arguments */
59+
StartSeh()
60+
s = _mbsnbcat(NULL, NULL, 0);
61+
EndSeh(STATUS_SUCCESS);
62+
ok(s == NULL, "Expected _mbsnbcat to return NULL, got %p\n", s);
63+
64+
StartSeh()
65+
s = _mbsnbcat(NULL, NULL, 10);
66+
EndSeh((CrtDll || (MsVcrt && GetWinVersion() <= 0x502)) ? STATUS_ACCESS_VIOLATION : STATUS_SUCCESS);
67+
ok(s == NULL, "Expected _mbsnbcat to return NULL, got %p\n", s);
68+
69+
memset(dest, 'X', sizeof(dest));
70+
StartSeh()
71+
s = _mbsnbcat(dest, NULL, 0);
72+
EndSeh(STATUS_SUCCESS);
73+
ok(s == dest, "Expected _mbsnbcat to return dest pointer, got %p\n", s);
74+
ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
75+
76+
memset(dest, 'X', sizeof(dest));
77+
StartSeh()
78+
s = _mbsnbcat(dest, second, 0);
79+
EndSeh(STATUS_SUCCESS);
80+
ok(s == dest, "Expected _mbsnbcat to return dest pointer, got %p\n", s);
81+
ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
82+
83+
memset(dest, 'X', sizeof(dest));
84+
s = NULL;
85+
StartSeh()
86+
s = _mbsnbcat(dest, NULL, 10);
87+
EndSeh((CrtDll || (MsVcrt && GetWinVersion() <= 0x502)) ? STATUS_ACCESS_VIOLATION : STATUS_SUCCESS);
88+
ok(s == NULL, "Expected _mbsnbcat to return NULL, got %p\n", s);
89+
ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
90+
91+
memset(dest, 'X', sizeof(dest));
92+
dest[0] = '\0';
93+
StartSeh()
94+
s = _mbsnbcat(dest, second, sizeof(second));
95+
EndSeh(STATUS_SUCCESS);
96+
ok(s == dest, "Expected _mbsnbcat to return dest pointer, got %p\n", s);
97+
ok(!memcmp(dest, second, sizeof(second)),
98+
"Expected the output buffer string to be \"duck\", got '%s'\n", dest);
99+
100+
/* Test source truncation behavior */
101+
memset(dest, 'X', sizeof(dest));
102+
memcpy(dest, first, sizeof(first));
103+
s = _mbsnbcat(dest, second, 0);
104+
ok(s == dest, "Expected _mbsnbcat to return dest pointer, got %p\n", s);
105+
ok(!memcmp(dest, first, sizeof(first)),
106+
"Expected the output buffer string to be \"dinosaur\", got '%s'\n", dest);
107+
108+
memset(dest, 'X', sizeof(dest));
109+
memcpy(dest, first, sizeof(first));
110+
s = _mbsnbcat(dest, second, sizeof(second));
111+
ok(s == dest, "Expected _mbsnbcat to return dest pointer, got %p\n", s);
112+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
113+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
114+
115+
memset(dest, 'X', sizeof(dest));
116+
memcpy(dest, first, sizeof(first));
117+
s = _mbsnbcat(dest, second, sizeof(second) + 1);
118+
ok(s == dest, "Expected _mbsnbcat to return dest pointer, got %p\n", s);
119+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
120+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
121+
122+
memset(dest, 'X', sizeof(dest));
123+
memcpy(dest, first, sizeof(first));
124+
s = _mbsnbcat(dest, second, sizeof(second) - 1);
125+
ok(s == dest, "Expected _mbsnbcat to return dest pointer, got %p\n", s);
126+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
127+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
128+
129+
memset(dest, 'X', sizeof(dest));
130+
memcpy(dest, first, sizeof(first));
131+
s = _mbsnbcat(dest, second, sizeof(second) - 2);
132+
ok(s == dest, "Expected _mbsnbcat to return dest pointer, got %p\n", s);
133+
ok(!memcmp(dest, "dinosaurduc", sizeof("dinosaurduc")),
134+
"Expected the output buffer string to be \"dinosaurduc\", got '%s'\n", dest);
135+
136+
/* Test typical scenario */
137+
memset(dest, 'X', sizeof(dest));
138+
memcpy(dest, first, sizeof(first));
139+
s = _mbsnbcat(dest, second, sizeof(second) - 1);
140+
ok(s == dest, "Expected _mbsnbcat to return dest pointer, got %p\n", s);
141+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
142+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
143+
144+
/* TODO: Add some distinguishing tests (_mbsncat vs. _mbsnbcat) for copying bytes */
145+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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+
#ifndef TEST_STATIC_CRT
16+
unsigned char *(__cdecl *p__mbsncat)(unsigned char*,const unsigned char*,size_t);
17+
18+
static BOOL Init(void)
19+
{
20+
HMODULE hdll = LoadLibraryA(TEST_DLL_NAME);
21+
22+
p__mbsncat = (void *)GetProcAddress(hdll, "_mbsncat");
23+
ok(p__mbsncat != NULL, "Failed to load _mbsncat from %s\n", TEST_DLL_NAME);
24+
return (p__mbsncat != NULL);
25+
}
26+
#define _mbsncat p__mbsncat
27+
#endif
28+
29+
static USHORT GetWinVersion(VOID)
30+
{
31+
return ((GetVersion() & 0xFF) << 8) |
32+
((GetVersion() >> 8) & 0xFF);
33+
}
34+
35+
START_TEST(_mbsncat)
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 (!Init())
52+
{
53+
skip("Skipping tests, because _mbsncat is not available\n");
54+
return;
55+
}
56+
#endif
57+
58+
/* Test invalid arguments */
59+
StartSeh()
60+
s = _mbsncat(NULL, NULL, 0);
61+
EndSeh(STATUS_SUCCESS);
62+
ok(s == NULL, "Expected _mbsncat to return NULL, got %p\n", s);
63+
64+
StartSeh()
65+
s = _mbsncat(NULL, NULL, 10);
66+
EndSeh((CrtDll || (MsVcrt && GetWinVersion() <= 0x502)) ? STATUS_ACCESS_VIOLATION : STATUS_SUCCESS);
67+
ok(s == NULL, "Expected _mbsncat to return NULL, got %p\n", s);
68+
69+
memset(dest, 'X', sizeof(dest));
70+
StartSeh()
71+
s = _mbsncat(dest, NULL, 0);
72+
EndSeh(STATUS_SUCCESS);
73+
ok(s == dest, "Expected _mbsncat to return dest pointer, got %p\n", s);
74+
ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
75+
76+
memset(dest, 'X', sizeof(dest));
77+
StartSeh()
78+
s = _mbsncat(dest, second, 0);
79+
EndSeh(STATUS_SUCCESS);
80+
ok(s == dest, "Expected _mbsncat to return dest pointer, got %p\n", s);
81+
ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
82+
83+
memset(dest, 'X', sizeof(dest));
84+
s = NULL;
85+
StartSeh()
86+
s = _mbsncat(dest, NULL, 10);
87+
EndSeh((CrtDll || (MsVcrt && GetWinVersion() <= 0x502)) ? STATUS_ACCESS_VIOLATION : STATUS_SUCCESS);
88+
ok(s == NULL, "Expected _mbsncat to return NULL, got %p\n", s);
89+
ok(dest[0] == 'X', "Expected the output buffer to be untouched\n");
90+
91+
memset(dest, 'X', sizeof(dest));
92+
dest[0] = '\0';
93+
StartSeh()
94+
s = _mbsncat(dest, second, sizeof(second));
95+
EndSeh(STATUS_SUCCESS);
96+
ok(s == dest, "Expected _mbsncat to return dest pointer, got %p\n", s);
97+
ok(!memcmp(dest, second, sizeof(second)),
98+
"Expected the output buffer string to be \"duck\", got '%s'\n", dest);
99+
100+
/* Test source truncation behavior */
101+
memset(dest, 'X', sizeof(dest));
102+
memcpy(dest, first, sizeof(first));
103+
s = _mbsncat(dest, second, 0);
104+
ok(s == dest, "Expected _mbsncat to return dest pointer, got %p\n", s);
105+
ok(!memcmp(dest, first, sizeof(first)),
106+
"Expected the output buffer string to be \"dinosaur\", got '%s'\n", dest);
107+
108+
memset(dest, 'X', sizeof(dest));
109+
memcpy(dest, first, sizeof(first));
110+
s = _mbsncat(dest, second, sizeof(second));
111+
ok(s == dest, "Expected _mbsncat to return dest pointer, got %p\n", s);
112+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
113+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
114+
115+
memset(dest, 'X', sizeof(dest));
116+
memcpy(dest, first, sizeof(first));
117+
s = _mbsncat(dest, second, sizeof(second) + 1);
118+
ok(s == dest, "Expected _mbsncat to return dest pointer, got %p\n", s);
119+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
120+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
121+
122+
memset(dest, 'X', sizeof(dest));
123+
memcpy(dest, first, sizeof(first));
124+
s = _mbsncat(dest, second, sizeof(second) - 1);
125+
ok(s == dest, "Expected _mbsncat to return dest pointer, got %p\n", s);
126+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
127+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
128+
129+
memset(dest, 'X', sizeof(dest));
130+
memcpy(dest, first, sizeof(first));
131+
s = _mbsncat(dest, second, sizeof(second) - 2);
132+
ok(s == dest, "Expected _mbsncat to return dest pointer, got %p\n", s);
133+
ok(!memcmp(dest, "dinosaurduc", sizeof("dinosaurduc")),
134+
"Expected the output buffer string to be \"dinosaurduc\", got '%s'\n", dest);
135+
136+
/* Test typical scenario */
137+
memset(dest, 'X', sizeof(dest));
138+
memcpy(dest, first, sizeof(first));
139+
s = _mbsncat(dest, second, sizeof(second) - 1);
140+
ok(s == dest, "Expected _mbsncat to return dest pointer, got %p\n", s);
141+
ok(!memcmp(dest, "dinosaurduck", sizeof("dinosaurduck")),
142+
"Expected the output buffer string to be \"dinosaurduck\", got '%s'\n", dest);
143+
144+
/* TODO: Add some distinguishing tests (_mbsncat vs. _mbsnbcat) for copying chars */
145+
}

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)