Add many tests for wcstomb and wctomb, which I used for =

Colin Finck mail at colinfinck.de
Sun Jul 27 18:50:38 CDT 2008


verifying my reimplementation of these functions.=0A=
 All tests pass under WinXP SP2.=0A=
=0A=
---=0A=
 dlls/msvcrt/tests/string.c |  168 =
++++++++++++++++++++++++++++++++++++++++++++=0A=
 1 files changed, 168 insertions(+), 0 deletions(-)=0A=
=0A=
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c=0A=
index 5247515..6953683 100644=0A=
--- a/dlls/msvcrt/tests/string.c=0A=
+++ b/dlls/msvcrt/tests/string.c=0A=
@@ -2,6 +2,7 @@=0A=
  * Unit test suite for string functions.=0A=
  *=0A=
  * Copyright 2004 Uwe Bonnes=0A=
+ * Copyright 2008 Colin Finck=0A=
  *=0A=
  * This library is free software; you can redistribute it and/or=0A=
  * modify it under the terms of the GNU Lesser General Public=0A=
@@ -47,10 +48,13 @@ static char *buf_to_string(const unsigned char *bin, =
int len, int nr)=0A=
 =0A=
 static void* (*pmemcpy)(void *, const void *, size_t n);=0A=
 static int* (*pmemcmp)(void *, const void *, size_t n);=0A=
+static char* (*p_setlocale)(int category, const char* locale);=0A=
 static int (*pstrcpy_s)(char *dst, size_t len, const char *src);=0A=
 static int (*pstrcat_s)(char *dst, size_t len, const char *src);=0A=
 static int (*p_mbsnbcpy_s)(unsigned char * dst, size_t size, const =
unsigned char * src, size_t count);=0A=
 static int (*p_wcscpy_s)(wchar_t *wcDest, size_t size, const wchar_t =
*wcSrc);=0A=
+static int (*p_wctomb)(char *mbchar, wchar_t wchar);=0A=
+static size_t (*p_wcstombs)(char *mbstr, const wchar_t *wcstr, size_t =
count);=0A=
 =0A=
 #define SETNOFAIL(x,y) x =3D (void*)GetProcAddress(hMsvcrt,y)=0A=
 #define SET(x,y) SETNOFAIL(x,y); ok(x !=3D NULL, "Export '%s' not =
found\n", y)=0A=
@@ -607,6 +611,164 @@ static void test_wcscpy_s(void)=0A=
     ok(szDestShort[0] =3D=3D 0, "szDestShort[0] not 0\n");=0A=
 }=0A=
 =0A=
+static void test_wctomb_wcstombs(void)=0A=
+{=0A=
+    char* locale;=0A=
+    char mbc;=0A=
+    char mbs[5];=0A=
+    int ret;=0A=
+    wchar_t wc1 =3D 228;                           /* Western =
Windows-1252 character */=0A=
+    wchar_t wc2 =3D 1088;                          /* Russian =
Windows-1251 character not displayable for Windows-1252 */=0A=
+    wchar_t wcs[5] =3D {'T', 'h', 1088, 'i', 0};   /* String with ASCII =
characters and a Russian character */=0A=
+    wchar_t dbwcs[3] =3D {28953, 25152, 0};        /* String with =
Chinese (codepage 950) characters */=0A=
+=0A=
+    p_setlocale(LC_ALL, "C");=0A=
+    ret =3D p_wcstombs(NULL, dbwcs, 0);=0A=
+    ok(ret =3D=3D 2, "ret is %d\n", ret);=0A=
+=0A=
+    memset(mbs, 0, 5);=0A=
+    ret =3D p_wcstombs(mbs, dbwcs, ret);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(mbs[0] =3D=3D 0, "mbs[0] is %d\n", mbs[0]);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+=0A=
+    ret =3D p_wcstombs(NULL, wcs, 0);=0A=
+    ok(ret =3D=3D 4, "ret is %d\n", ret);=0A=
+=0A=
+    ret =3D p_wcstombs(mbs, wcs, ret);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(!strcmp(mbs, "Th"), "mbs is %s\n", mbs);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+=0A=
+    ret =3D p_wctomb(&mbc, wcs[0]);=0A=
+    ok(ret =3D=3D 1, "ret is %d\n", ret);=0A=
+    ok(mbc =3D=3D 84, "mbc is %d\n", mbc);=0A=
+=0A=
+    mbc =3D 84;=0A=
+    ret =3D p_wcstombs(&mbc, &dbwcs[0], 1);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(mbc =3D=3D 84, "mbc is %d\n", mbc);=0A=
+=0A=
+    ret =3D p_wcstombs(mbs, wcs, 0);=0A=
+    ok(ret =3D=3D 0, "ret is %d\n", ret);=0A=
+=0A=
+    /* The length for the null character (in any locale) is 0, but if =
you pass a variable, it will be set to 0 and wctomb returns 1 */=0A=
+    ret =3D p_wctomb(NULL, 0);=0A=
+    ok(ret =3D=3D 0, "ret is %d\n", ret);=0A=
+=0A=
+    ret =3D p_wctomb(&mbc, 0);=0A=
+    ok(ret =3D=3D 1, "ret is %d\n", ret);=0A=
+    ok(mbc =3D=3D 0, "mbc is %d\n", mbc);=0A=
+=0A=
+    /* msvcr80.dll changes mbc in the following call back to 0, =
msvcrt.dll from WinXP SP2 leaves it untouched */=0A=
+    mbc =3D 84;=0A=
+    ret =3D p_wctomb(&mbc, dbwcs[0]);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+    ok(mbc =3D=3D 84, "mbc is %d\n", mbc);=0A=
+=0A=
+    /* With a real locale, -1 also becomes a possible return value in =
case of an invalid character */=0A=
+    locale =3D p_setlocale(LC_ALL, "English");=0A=
+    if(!locale)=0A=
+    {=0A=
+        skip("setlocale failed for English, this locale is probably not =
installed on your system\n");=0A=
+        goto setlocale_russian;=0A=
+    }=0A=
+=0A=
+    ret =3D p_wcstombs(NULL, wcs, 0);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+=0A=
+    ret =3D p_wcstombs(NULL, dbwcs, 0);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+=0A=
+    ret =3D p_wcstombs(NULL, wcs, 2);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+=0A=
+    /* Test p_wctomb() as well */=0A=
+    ret =3D p_wctomb(&mbc, wc1);=0A=
+    ok(ret =3D=3D 1, "ret is %d\n", ret);=0A=
+    ok(mbc =3D=3D -28, "mbc is %d\n", mbc);=0A=
+=0A=
+    ret =3D p_wctomb(&mbc, wc2);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+    ok(mbc =3D=3D 63, "mbc is %d\n", mbc);=0A=
+=0A=
+    ret =3D p_wcstombs(&mbc, wcs, 1);=0A=
+    ok(ret =3D=3D 1, "ret is %d\n", ret);=0A=
+    ok(mbc =3D=3D 84, "mbc is %d\n", mbc);=0A=
+=0A=
+    memset(mbs, 0, sizeof(mbs));=0A=
+    ret =3D p_wcstombs(mbs, wcs, sizeof(mbs));=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+    ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs);=0A=
+    mbs[0] =3D 0;=0A=
+=0A=
+    /* wcstombs mustn't add any null character automatically.=0A=
+       So in this case, we should get the same string again, even if we =
only copied the first three bytes. */=0A=
+    ret =3D p_wcstombs(mbs, wcs, 3);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+    ok(!strcmp(mbs, "Th?i"), "mbs is %s\n", mbs);=0A=
+    memset(mbs, 0, 5);=0A=
+=0A=
+    /* Now this shouldn't be the case like above as we zeroed the =
complete string buffer. */=0A=
+    ret =3D p_wcstombs(mbs, wcs, 3);=0A=
+    ok(ret =3D=3D -1, "ret is %d\n", ret);=0A=
+    ok(errno =3D=3D EILSEQ, "errno is %d\n", errno);=0A=
+    ok(!strcmp(mbs, "Th?"), "mbs is %s\n", mbs);=0A=
+=0A=
+    /* Try another locale */=0A=
+setlocale_russian:=0A=
+    locale =3D p_setlocale(LC_ALL, "Russian");=0A=
+    if(!locale)=0A=
+    {=0A=
+        skip("setlocale failed for Russian, this locale is probably not =
installed on your system\n");=0A=
+        goto setlocale_chinese;=0A=
+    }=0A=
+=0A=
+    ret =3D p_wcstombs(mbs, wcs, sizeof(mbs));=0A=
+    ok(ret =3D=3D 4, "ret is %d\n", ret);=0A=
+    ok(!strcmp(mbs, "Th=F0i"), "mbs is %s\n", mbs);=0A=
+=0A=
+    ret =3D p_wctomb(&mbc, wc2);=0A=
+    ok(ret =3D=3D 1, "ret is %d\n", ret);=0A=
+    ok(mbc =3D=3D -16, "mbc is %d\n", mbc);=0A=
+=0A=
+    ret =3D p_wctomb(&mbc, wc1);=0A=
+    ok(ret =3D=3D 1, "ret is %d\n", ret);=0A=
+    ok(mbc =3D=3D 97, "mbc is %d\n", mbc);=0A=
+=0A=
+    /* Double-byte tests */=0A=
+setlocale_chinese:=0A=
+    locale =3D p_setlocale(LC_ALL, "Chinese");=0A=
+    if(!locale)=0A=
+    {=0A=
+        skip("setlocale failed for Chinese, this locale is probably not =
installed on your system\n");=0A=
+        return;=0A=
+    }=0A=
+=0A=
+    ret =3D p_wcstombs(mbs, dbwcs, sizeof(mbs));=0A=
+    ok(ret =3D=3D 4, "ret is %d\n", ret);=0A=
+    ok(!strcmp(mbs, "=B5H=A9=D2"), "mbs is %s\n", mbs);=0A=
+    memset(mbs, 0, 5);=0A=
+=0A=
+    ret =3D p_wcstombs(NULL, dbwcs, 0);=0A=
+    ok(ret =3D=3D 4, "ret is %d\n", ret);=0A=
+=0A=
+    ret =3D p_wcstombs(mbs, dbwcs, 1);=0A=
+    ok(ret =3D=3D 0, "ret is %d\n", ret);=0A=
+    ok(mbs[0] =3D=3D 0, "mbs[0] is %d\n", mbs[0]);=0A=
+=0A=
+    ret =3D p_wcstombs(mbs, wcs, 1);=0A=
+    ok(ret =3D=3D 1, "ret is %d\n", ret);=0A=
+    ok(mbs[0] =3D=3D 84, "mbs[0] is %d\n", mbs[0]);=0A=
+}=0A=
+=0A=
 START_TEST(string)=0A=
 {=0A=
     char mem[100];=0A=
@@ -617,12 +779,16 @@ START_TEST(string)=0A=
     if (!hMsvcrt)=0A=
         hMsvcrt =3D GetModuleHandleA("msvcrtd.dll");=0A=
     ok(hMsvcrt !=3D 0, "GetModuleHandleA failed\n");=0A=
+=0A=
     SET(pmemcpy,"memcpy");=0A=
     SET(pmemcmp,"memcmp");=0A=
     pstrcpy_s =3D (void *)GetProcAddress( hMsvcrt,"strcpy_s" );=0A=
     pstrcat_s =3D (void *)GetProcAddress( hMsvcrt,"strcat_s" );=0A=
     p_mbsnbcpy_s =3D (void *)GetProcAddress( hMsvcrt,"_mbsnbcpy_s" );=0A=
     p_wcscpy_s =3D (void *)GetProcAddress( hMsvcrt,"wcscpy_s" );=0A=
+    SET(p_setlocale, "setlocale");=0A=
+    SET(p_wctomb, "wctomb");=0A=
+    SET(p_wcstombs, "wcstombs");=0A=
 =0A=
     /* MSVCRT memcpy behaves like memmove for overlapping moves,=0A=
        MFC42 CString::Insert seems to rely on that behaviour */=0A=
@@ -647,4 +813,6 @@ START_TEST(string)=0A=
     test__mbsnbcpy_s();=0A=
 =0A=
     test_wcscpy_s();=0A=
+=0A=
+    test_wctomb_wcstombs();=0A=
 }=0A=
-- =0A=
1.5.6.1.1071.g76fb=0A=
=0A=

------=_NextPart_000_0023_01C8F043.5F9F4E50--




More information about the wine-patches mailing list