From 4a981826c15dcaf6db8f9e07f2a5f72604ec0e6a Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Sun, 4 Jun 2017 01:50:58 +0000 Subject: [PATCH] [MSVCRT_WINETEST] Sync with Wine Staging 2.9. CORE-13362 svn path=/trunk/; revision=74882 --- rostests/winetests/msvcrt/cpp.c | 8 +++- rostests/winetests/msvcrt/file.c | 58 +++++++++++++++++++++++ rostests/winetests/msvcrt/misc.c | 74 +++++++++++++++++++++++++++++- rostests/winetests/msvcrt/printf.c | 36 ++++++++++++++- rostests/winetests/msvcrt/scanf.c | 14 ++++++ rostests/winetests/msvcrt/string.c | 48 ++++++++++++++++--- 6 files changed, 228 insertions(+), 10 deletions(-) diff --git a/rostests/winetests/msvcrt/cpp.c b/rostests/winetests/msvcrt/cpp.c index 490ddeea274..cf5e4c7d60b 100644 --- a/rostests/winetests/msvcrt/cpp.c +++ b/rostests/winetests/msvcrt/cpp.c @@ -969,7 +969,11 @@ static void test_rtti(void) void *child_class_sig0 = &child_class_sig0_vtbl[1]; void *virtual_base_class_vtbl[2] = {&virtual_base_class_rtti.object_locator}; int virtual_base_class_vbtbl[2] = {0, 0x100}; - void *virtual_base_class[2] = {&virtual_base_class_vtbl[1], virtual_base_class_vbtbl}; + struct { + void *virtual_base[2]; + char data[0x110-sizeof(void*)]; + void *vbthis; + } virtual_base_class = { {&virtual_base_class_vtbl[1], virtual_base_class_vbtbl} }; static const char* e_name = "name"; type_info *ti,*bti; @@ -1082,7 +1086,7 @@ static void test_rtti(void) ok(casted == (char*)&child_class+4, "failed cast to child class (%p %p)\n", casted, &child_class); casted = p__RTDynamicCast(&virtual_base_class, 0, &virtual_base_class_rtti.type_info[0], &virtual_base_class_rtti.type_info[1], 0); - ok(casted == (char*)&virtual_base_class+0x110+sizeof(void*), "failed cast to child class (%p %p)\n", casted, &virtual_base_class); + ok(casted == &virtual_base_class.vbthis, "failed cast to child class (%p %p)\n", casted, &virtual_base_class); } struct _demangle { diff --git a/rostests/winetests/msvcrt/file.c b/rostests/winetests/msvcrt/file.c index 9e2beee27e0..2c356ea9644 100644 --- a/rostests/winetests/msvcrt/file.c +++ b/rostests/winetests/msvcrt/file.c @@ -49,6 +49,8 @@ static HANDLE proc_handles[2]; static int (__cdecl *p_fopen_s)(FILE**, const char*, const char*); static int (__cdecl *p__wfopen_s)(FILE**, const wchar_t*, const wchar_t*); +static errno_t (__cdecl *p__get_fmode)(int*); +static errno_t (__cdecl *p__set_fmode)(int); static const char* get_base_name(const char *path) { @@ -71,6 +73,8 @@ static void init(void) p_fopen_s = (void*)GetProcAddress(hmod, "fopen_s"); p__wfopen_s = (void*)GetProcAddress(hmod, "_wfopen_s"); __pioinfo = (void*)GetProcAddress(hmod, "__pioinfo"); + p__get_fmode = (void*)GetProcAddress(hmod, "_get_fmode"); + p__set_fmode = (void*)GetProcAddress(hmod, "_set_fmode"); } static void test_filbuf( void ) @@ -2386,6 +2390,59 @@ static void test_close(void) DeleteFileA( "fdopen.tst" ); } +static void test__creat(void) +{ + int fd, pos, count, readonly, old_fmode = 0, have_fmode; + char buf[6], testdata[4] = {'a', '\n', 'b', '\n'}; + + have_fmode = p__get_fmode && p__set_fmode && !p__get_fmode(&old_fmode); + if (!have_fmode) + win_skip("_fmode can't be set, skipping mode tests\n"); + + if (have_fmode) + p__set_fmode(_O_TEXT); + fd = _creat("_creat.tst", 0); + ok(fd > 0, "_creat failed\n"); + _write(fd, testdata, 4); + if (have_fmode) { + pos = _tell(fd); + ok(pos == 6, "expected pos 6 (text mode), got %d\n", pos); + } + ok(_lseek(fd, SEEK_SET, 0) == 0, "_lseek failed\n"); + count = _read(fd, buf, 6); + ok(count == 4, "_read returned %d, expected 4\n", count); + count = count > 0 ? count > 4 ? 4 : count : 0; + ok(memcmp(buf, testdata, count) == 0, "_read returned wrong contents\n"); + _close(fd); + readonly = GetFileAttributesA("_creat.tst") & FILE_ATTRIBUTE_READONLY; + ok(readonly, "expected read-only file\n"); + SetFileAttributesA("_creat.tst", FILE_ATTRIBUTE_NORMAL); + DeleteFileA("_creat.tst"); + + if (have_fmode) + p__set_fmode(_O_BINARY); + fd = _creat("_creat.tst", _S_IREAD | _S_IWRITE); + ok(fd > 0, "_creat failed\n"); + _write(fd, testdata, 4); + if (have_fmode) { + pos = _tell(fd); + ok(pos == 4, "expected pos 4 (binary mode), got %d\n", pos); + } + ok(_lseek(fd, SEEK_SET, 0) == 0, "_lseek failed\n"); + count = _read(fd, buf, 6); + ok(count == 4, "_read returned %d, expected 4\n", count); + count = count > 0 ? count > 4 ? 4 : count : 0; + ok(memcmp(buf, testdata, count) == 0, "_read returned wrong contents\n"); + _close(fd); + readonly = GetFileAttributesA("_creat.tst") & FILE_ATTRIBUTE_READONLY; + ok(!readonly, "expected rw file\n"); + SetFileAttributesA("_creat.tst", FILE_ATTRIBUTE_NORMAL); + DeleteFileA("_creat.tst"); + + if (have_fmode) + p__set_fmode(old_fmode); +} + START_TEST(file) { int arg_c; @@ -2453,6 +2510,7 @@ START_TEST(file) test__open_osfhandle(); test_write_flush(); test_close(); + test__creat(); /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report * file contains lines in the correct order diff --git a/rostests/winetests/msvcrt/misc.c b/rostests/winetests/msvcrt/misc.c index b7f5bdbd51e..2aeff43daa3 100644 --- a/rostests/winetests/msvcrt/misc.c +++ b/rostests/winetests/msvcrt/misc.c @@ -58,6 +58,8 @@ static void (__cdecl *p_qsort_s)(void*, MSVCRT_size_t, MSVCRT_size_t, static double (__cdecl *p_atan)(double); static double (__cdecl *p_exp)(double); static double (__cdecl *p_tanh)(double); +static void *(__cdecl *p_lfind_s)(const void*, const void*, unsigned int*, + size_t, int (__cdecl *)(void*, const void*, const void*), void*); static void init(void) { @@ -75,6 +77,7 @@ static void init(void) p_atan = (void *)GetProcAddress(hmod, "atan"); p_exp = (void *)GetProcAddress(hmod, "exp"); p_tanh = (void *)GetProcAddress(hmod, "tanh"); + p_lfind_s = (void *)GetProcAddress(hmod, "_lfind_s"); } static void test_rand_s(void) @@ -558,7 +561,7 @@ static void test_thread_handle_close(void) DWORD ret; /* _beginthread: handle is not closed on ExitThread and _endthreadex */ - hThread = (HANDLE)_beginthread(test_thread_func, 0, (void*)0); + hThread = (HANDLE)_beginthread(test_thread_func, 0, NULL); ok(hThread != INVALID_HANDLE_VALUE, "_beginthread failed (%d)\n", errno); WaitForSingleObject(hThread, INFINITE); ret = CloseHandle(hThread); @@ -596,6 +599,74 @@ static void test_thread_handle_close(void) ok(ret, "ret = %d\n", ret); } +static int __cdecl _lfind_s_comp(void *ctx, const void *l, const void *r) +{ + *(int *)ctx = 0xdeadc0de; + return *(int *)l - *(int *)r; +} + +static void test__lfind_s(void) +{ + static const int tests[] = {9000, 8001, 7002, 6003, 1003, 5004, 4005, 3006, 2007}; + unsigned int num; + void *found; + int ctx; + int key; + + if (!p_lfind_s) + { + win_skip("_lfind_s is not available\n"); + return; + } + + key = 1234; + num = sizeof(tests)/sizeof(tests[0]); + + errno = 0xdeadbeef; + found = p_lfind_s(NULL, tests, &num, sizeof(int), _lfind_s_comp, NULL); + ok(errno == EINVAL, "errno = %d\n", errno); + ok(!found, "Expected NULL, got %p\n", found); + + errno = 0xdeadbeef; + found = p_lfind_s(&key, NULL, &num, sizeof(int), _lfind_s_comp, NULL); + ok(errno == EINVAL, "errno = %d\n", errno); + ok(!found, "Expected NULL, got %p\n", found); + + errno = 0xdeadbeef; + found = p_lfind_s(&key, tests, &num, 0, _lfind_s_comp, NULL); + ok(errno == EINVAL, "errno = %d\n", errno); + ok(!found, "Expected NULL, got %p\n", found); + + errno = 0xdeadbeef; + found = p_lfind_s(&key, tests, &num, sizeof(int), NULL, NULL); + ok(errno == EINVAL, "errno = %d\n", errno); + ok(!found, "Expected NULL, got %p\n", found); + + ctx = -1; + key = 9000; + errno = 0xdeadbeef; + found = p_lfind_s(&key, tests, &num, sizeof(int), _lfind_s_comp, &ctx); + ok(errno == 0xdeadbeef, "errno = %d\n", errno); + ok(found == tests, "Expected %p, got %p\n", tests, found); + ok(ctx == 0xdeadc0de, "Expected 0xdeadc0de, got %x\n", ctx); + + ctx = -1; + key = 2007; + errno = 0xdeadbeef; + found = p_lfind_s(&key, tests, &num, sizeof(int), _lfind_s_comp, &ctx); + ok(errno == 0xdeadbeef, "errno = %d\n", errno); + ok(found == tests+8, "Expected %p, got %p\n", tests+8, found); + ok(ctx == 0xdeadc0de, "Expected 0xdeadc0de, got %x\n", ctx); + + ctx = -1; + key = 1234; + errno = 0xdeadbeef; + found = p_lfind_s(&key, tests, &num, sizeof(int), _lfind_s_comp, &ctx); + ok(errno == 0xdeadbeef, "errno = %d\n", errno); + ok(!found, "Expected NULL, got %p\n", found); + ok(ctx == 0xdeadc0de, "Expected 0xdeadc0de, got %x\n", ctx); +} + START_TEST(misc) { int arg_c; @@ -625,4 +696,5 @@ START_TEST(misc) test_qsort_s(); test_math_functions(); test_thread_handle_close(); + test__lfind_s(); } diff --git a/rostests/winetests/msvcrt/printf.c b/rostests/winetests/msvcrt/printf.c index 295c6dd3020..f9b3fc9ff0b 100644 --- a/rostests/winetests/msvcrt/printf.c +++ b/rostests/winetests/msvcrt/printf.c @@ -27,6 +27,7 @@ #include #include +#include #include "windef.h" #include "winbase.h" @@ -768,6 +769,39 @@ static void test_sprintf( void ) r = sprintf(buffer, format, INFINITY); ok(r==10, "r = %d\n", r); ok(!strcmp(buffer, "0000001.#J"), "failed: \"%s\"\n", buffer); + + format = "%c"; + r = sprintf(buffer, format, 'a'); + ok(r==1, "r = %d\n", r); + ok(!strcmp(buffer, "a"), "failed: \"%s\"\n", buffer); + r = sprintf(buffer, format, 0xa082); + ok(r==1, "r = %d\n", r); + ok(!strcmp(buffer, "\x82"), "failed: \"%s\"\n", buffer); + + format = "%C"; + r = sprintf(buffer, format, 'a'); + ok(r==1, "r = %d\n", r); + ok(!strcmp(buffer, "a"), "failed: \"%s\"\n", buffer); + r = sprintf(buffer, format, 0x3042); + ok(r==0, "r = %d\n", r); + ok(!strcmp(buffer, ""), "failed: \"%s\"\n", buffer); + + if(!setlocale(LC_ALL, "Japanese_Japan.932")) { + win_skip("Japanese_Japan.932 locale not available\n"); + return; + } + + format = "%c"; + r = sprintf(buffer, format, 0xa082); + ok(r==1, "r = %d\n", r); + ok(!strcmp(buffer, "\x82"), "failed: \"%s\"\n", buffer); + + format = "%C"; + r = sprintf(buffer, format, 0x3042); + ok(r==2, "r = %d\n", r); + ok(!strcmp(buffer, "\x82\xa0"), "failed: \"%s\"\n", buffer); + + setlocale(LC_ALL, "C"); } static void test_swprintf( void ) @@ -911,7 +945,7 @@ static void test_fcvt(void) { char *str; int dec=100, sign=100; - + /* Numbers less than 1.0 with different precisions */ str = _fcvt(0.0001, 1, &dec, &sign ); ok( 0 == strcmp(str,""), "bad return '%s'\n", str); diff --git a/rostests/winetests/msvcrt/scanf.c b/rostests/winetests/msvcrt/scanf.c index 6cb85facaf6..1d1f28eaf41 100644 --- a/rostests/winetests/msvcrt/scanf.c +++ b/rostests/winetests/msvcrt/scanf.c @@ -251,6 +251,10 @@ static void test_sscanf( void ) ok(ret == 2, "got %d\n", ret); ok(!strcmp(buffer, "test"), "buf %s\n", buffer); ok(!strcmp(buffer1, "value\xda"), "buf %s\n", buffer1); + + ret = sscanf("\x81\x82test", "\x81%\x82%s", buffer); + ok(ret == 1, "got %d\n", ret); + ok(!strcmp(buffer, "test"), "buf = %s\n", buffer); } static void test_sscanf_s(void) @@ -299,6 +303,8 @@ static void test_swscanf( void ) wchar_t buffer[100]; int result, ret; static const WCHAR formatd[] = {'%','d',0}; + const WCHAR format2[] = {'a',0x1234,'%',0x1234,'%','c',0}; + WCHAR c; /* check WEOF */ /* WEOF is an unsigned short -1 but swscanf returns int @@ -308,6 +314,14 @@ static void test_swscanf( void ) /* msvcrt returns 0 but should return -1 (later versions do) */ ok( ret == (short)WEOF || broken(ret == 0), "swscanf returns %x instead of %x\n", ret, WEOF ); + + buffer[0] = 'a'; + buffer[1] = 0x1234; + buffer[2] = 0x1234; + buffer[3] = 'b'; + ret = swscanf(buffer, format2, &c); + ok(ret == 1, "swscanf returned %d\n", ret); + ok(c == 'b', "c = %x\n", c); } START_TEST(scanf) diff --git a/rostests/winetests/msvcrt/string.c b/rostests/winetests/msvcrt/string.c index 8e78695d29b..a59ed91f09d 100644 --- a/rostests/winetests/msvcrt/string.c +++ b/rostests/winetests/msvcrt/string.c @@ -2827,11 +2827,21 @@ static void test__stricmp(void) static void test__wcstoi64(void) { static const WCHAR digit[] = { '9', 0 }; + static const WCHAR space[] = { ' ', 0 }; static const WCHAR stock[] = { 0x3231, 0 }; /* PARENTHESIZED IDEOGRAPH STOCK */ + static const WCHAR cjk_1[] = { 0x4e00, 0 }; /* CJK Ideograph, First */ static const WCHAR tamil[] = { 0x0bef, 0 }; /* TAMIL DIGIT NINE */ static const WCHAR thai[] = { 0x0e59, 0 }; /* THAI DIGIT NINE */ static const WCHAR fullwidth[] = { 0xff19, 0 }; /* FULLWIDTH DIGIT NINE */ + static const WCHAR superscript1[] = { 0xb9, 0 }; /* SUPERSCRIPT ONE */ + static const WCHAR minus_0x91[] = { '-', 0x0e50, 'x', 0xff19, '1', 0 }; + static const WCHAR plus_071[] = { '+', 0x0e50, 0xff17, '1', 0 }; static const WCHAR hex[] = { 0xff19, 'f', 0x0e59, 0xff46, 0 }; + static const WCHAR zeros[] = { + 0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6, + 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10 + }; + int i; __int64 res; unsigned __int64 ures; @@ -2844,21 +2854,33 @@ static void test__wcstoi64(void) res = p_wcstoi64(digit, NULL, 10); ok(res == 9, "res != 9\n"); + res = p_wcstoi64(space, &endpos, 0); + ok(endpos == space, "endpos != space\n"); res = p_wcstoi64(stock, &endpos, 10); ok(res == 0, "res != 0\n"); ok(endpos == stock, "Incorrect endpos (%p-%p)\n", stock, endpos); + res = p_wcstoi64(cjk_1, NULL, 0); + ok(res == 0, "res != 0\n"); res = p_wcstoi64(tamil, &endpos, 10); ok(res == 0, "res != 0\n"); ok(endpos == tamil, "Incorrect endpos (%p-%p)\n", tamil, endpos); res = p_wcstoi64(thai, NULL, 10); - todo_wine ok(res == 9, "res != 9\n"); + ok(res == 9, "res != 9\n"); res = p_wcstoi64(fullwidth, NULL, 10); - todo_wine ok(res == 9, "res != 9\n"); + ok(res == 9, "res != 9\n"); + res = p_wcstoi64(superscript1, NULL, 10); + ok(res == 0, "res != 0\n"); res = p_wcstoi64(hex, NULL, 16); - todo_wine ok(res == 0x9f9, "res != 0x9f9\n"); + ok(res == 0x9f9, "res != 0x9f9\n"); + res = p_wcstoi64(minus_0x91, NULL, 0); + ok(res == -0x91, "res != -0x91\n"); + res = p_wcstoi64(plus_071, NULL, 0); + ok(res == 071, "res != 071\n"); ures = p_wcstoui64(digit, NULL, 10); ok(ures == 9, "ures != 9\n"); + ures = p_wcstoui64(space, &endpos, 0); + ok(endpos == space, "endpos != space\n"); ures = p_wcstoui64(stock, &endpos, 10); ok(ures == 0, "ures != 0\n"); ok(endpos == stock, "Incorrect endpos (%p-%p)\n", stock, endpos); @@ -2866,11 +2888,25 @@ static void test__wcstoi64(void) ok(ures == 0, "ures != 0\n"); ok(endpos == tamil, "Incorrect endpos (%p-%p)\n", tamil, endpos); ures = p_wcstoui64(thai, NULL, 10); - todo_wine ok(ures == 9, "ures != 9\n"); + ok(ures == 9, "ures != 9\n"); ures = p_wcstoui64(fullwidth, NULL, 10); - todo_wine ok(ures == 9, "ures != 9\n"); + ok(ures == 9, "ures != 9\n"); + ures = p_wcstoui64(superscript1, NULL, 10); + ok(ures == 0, "ures != 0\n"); ures = p_wcstoui64(hex, NULL, 16); - todo_wine ok(ures == 0x9f9, "ures != 0x9f9\n"); + ok(ures == 0x9f9, "ures != 0x9f9\n"); + ures = p_wcstoui64(plus_071, NULL, 0); + ok(ures == 071, "ures != 071\n"); + + /* Test various unicode digits */ + for (i = 0; i < sizeof(zeros) / sizeof(zeros[0]); ++i) { + WCHAR tmp[] = {zeros[i] + 4, zeros[i], zeros[i] + 5, 0}; + res = p_wcstoi64(tmp, NULL, 0); + ok(res == 405, "with zero = U+%04X: got %d, expected 405\n", zeros[i], (int)res); + tmp[1] = zeros[i] + 10; + res = p_wcstoi64(tmp, NULL, 16); + ok(res == 4, "with zero = U+%04X: got %d, expected 4\n", zeros[i], (int)res); + } return; }