Based on msvcrt:scanf tests.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ucrtbase/tests/Makefile.in | 1 + dlls/ucrtbase/tests/scanf.c | 280 ++++++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 dlls/ucrtbase/tests/scanf.c
diff --git a/dlls/ucrtbase/tests/Makefile.in b/dlls/ucrtbase/tests/Makefile.in index 3fd4b1c7d389..116bdcc7b653 100644 --- a/dlls/ucrtbase/tests/Makefile.in +++ b/dlls/ucrtbase/tests/Makefile.in @@ -4,4 +4,5 @@ C_SRCS = \ cpp.c \ misc.c \ printf.c \ + scanf.c \ string.c diff --git a/dlls/ucrtbase/tests/scanf.c b/dlls/ucrtbase/tests/scanf.c new file mode 100644 index 000000000000..644e79921613 --- /dev/null +++ b/dlls/ucrtbase/tests/scanf.c @@ -0,0 +1,280 @@ +/* + * Conformance tests for *scanf functions. + * + * Copyright 2002 Uwe Bonnes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdio.h> +#include <math.h> + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" + +#include "wine/test.h" + +static int (__cdecl *p_vsscanf)(unsigned __int64 options, const char *str, size_t len, const char *format, + void *locale, __ms_va_list valist); + +static BOOL init(void) +{ + HMODULE hmod = LoadLibraryA("ucrtbase.dll"); + + if (!hmod) + { + win_skip("ucrtbase.dll not installed\n"); + return FALSE; + } + + p_vsscanf = (void *)GetProcAddress(hmod, "__stdio_common_vsscanf"); + + return TRUE; +} + +static int WINAPIV vsscanf_wrapper(unsigned __int64 options, const char *str, const char *format, ...) +{ + int ret; + __ms_va_list valist; + __ms_va_start(valist, format); + ret = p_vsscanf(options, str, -1, format, NULL, valist); + __ms_va_end(valist); + return ret; +} + +#define UCRTBASE_SCANF_SECURECRT (0x0001) +#define UCRTBASE_SCANF_LEGACY_WIDE_SPECIFIERS (0x0002) +#define UCRTBASE_SCANF_LEGACY_MSVCRT_COMPATIBILITY (0x0004) + +static void test_sscanf(void) +{ + static const float float1 = -82.6267f, float2 = 27.76f; + char buffer[100], buffer1[100]; + int result, ret, hour, min, count; + LONGLONG result64; + char c; + void *ptr; + float ret_float1, ret_float2; + double double_res; + unsigned int i; + + static const unsigned int tests[] = + { + 0, + UCRTBASE_SCANF_LEGACY_WIDE_SPECIFIERS, + UCRTBASE_SCANF_LEGACY_MSVCRT_COMPATIBILITY, + }; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + ret = vsscanf_wrapper(tests[i], "", "%d", &result); + ok(ret == EOF, "sscanf returned %d for flags %#x\n", ret, tests[i]); + + ret = vsscanf_wrapper(tests[i], "000000000046F170", "%p", &ptr); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(ptr == (void *)0x46f170, "sscanf reads %p for flags %#x\n", ptr, tests[i]); + + ret = vsscanf_wrapper(tests[i], "0046F171", "%p", &ptr); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(ptr == (void *)0x46f171, "sscanf reads %p for flags %#x\n", ptr, tests[i]); + + ret = vsscanf_wrapper(tests[i], "46F172", "%p", &ptr); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(ptr == (void *)0x46f172, "sscanf reads %p for flags %#x\n", ptr, tests[i]); + + ret = vsscanf_wrapper(tests[i], "0x46F173", "%p", &ptr); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + todo_wine ok(ptr == (void *)0x46f173, "sscanf reads %p for flags %#x\n", ptr, tests[i]); + + ret = vsscanf_wrapper(tests[i], "-46F174", "%p", &ptr); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(ptr == (void *)(ULONG_PTR)-0x46f174, "sscanf reads %p for flags %#x\n", ptr, tests[i]); + + ret = vsscanf_wrapper(tests[i], "+46F175", "%p", &ptr); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(ptr == (void *)0x46f175, "sscanf reads %p for flags %#x\n", ptr, tests[i]); + + ret = vsscanf_wrapper(tests[i], "1233", "%p", &ptr); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(ptr == (void *)0x1233, "sscanf reads %p for flags %#x\n", ptr, tests[i]); + + ret = vsscanf_wrapper(tests[i], "1234", "%P", &ptr); + todo_wine ok(ret == 0, "sscanf returned %d for flags %#x\n", ret, tests[i]); + + ret = vsscanf_wrapper(tests[i], "0x519", "%x", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == 0x519, "sscanf reads %#x for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], "0x51a", "%x", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == 0x51a, "sscanf reads %#x for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], "0x51g", "%x", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == 0x51, "sscanf reads %#x for flags %#x\n", result, tests[i]); + + result = 0; + ret = vsscanf_wrapper(tests[i], "-1", "%x", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == -1, "sscanf reads %#x for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], ""%12@", "%"%%%d%@", &result); + todo_wine ok(ret == 0, "sscanf returned %d for flags %#x\n", ret, tests[i]); + + sprintf(buffer, "%f %f", float1, float2); + ret = vsscanf_wrapper(tests[i], buffer, "%f%f", &ret_float1, &ret_float2); + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(ret_float1 == float1, "got wrong float %.8e for flags %#x\n", ret_float1, tests[i]); + ok(ret_float2 == float2, "got wrong float %.8e for flags %#x\n", ret_float2, tests[i]); + + sprintf(buffer, "%lf", 32.715); + ret = vsscanf_wrapper(tests[i], buffer, "%lf", &double_res); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(double_res == 32.715, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); + ret = vsscanf_wrapper(tests[i], buffer, "%Lf", &double_res); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(double_res == 32.715, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); + + ret = vsscanf_wrapper(tests[i], "1.1e-30", "%lf", &double_res); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(double_res == 1.1e-30, "got wrong double %.16e for flags %#x\n", double_res, tests[i]); + + ret = vsscanf_wrapper(tests[i], " Waverly", "%*c%[^\n]", buffer); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(!strcmp(buffer, " Waverly"), "got string '%s' for flags %#x\n", buffer, tests[i]); + + ret = vsscanf_wrapper(tests[i], "abcefgdh", "%*[a-cg-e]%c", &buffer[0]); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(buffer[0] == 'd', "got char '%c' for flags %#x\n", buffer[0], tests[i]); + + ret = vsscanf_wrapper(tests[i], "abcefgdh", "%*[a-cd-dg-e]%c", &buffer[0]); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(buffer[0] == 'h', "got char '%c' for flags %#x\n", buffer[0], tests[i]); + + strcpy(buffer, "foo"); + strcpy(buffer1, "bar"); + ret = vsscanf_wrapper(tests[i], "a", "%s%s", buffer, buffer1); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(!strcmp(buffer, "a"), "got string '%s' for flags %#x\n", buffer, tests[i]); + ok(!strcmp(buffer1, "bar"), "got string '%s' for flags %#x\n", buffer1, tests[i]); + + ret = vsscanf_wrapper(tests[i], "21:59:20", "%d%n", &result, &count); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == 21, "got wrong number %d for flags %#x\n", result, tests[i]); + ok(count == 2, "got wrong count %d for flags %#x\n", count, tests[i]); + + ret = vsscanf_wrapper(tests[i], ":59:20", "%*c%n", &count); + ok(ret == 0, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(count == 1, "got wrong count %d for flags %#x\n", count, tests[i]); + + result = 0xdeadbeef; + ret = vsscanf_wrapper(tests[i], "12345678", "%hd", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == 0xdead614e, "got wrong number %#x for flags %#x\n", result, tests[i]); + + result = 0xdeadbeef; + ret = vsscanf_wrapper(tests[i], "12345678", "%hhd", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + todo_wine ok(result == 0xdeadbe4e, "got wrong number %#x for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], "12345678901234", "%lld", &result64); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result64 == 12345678901234, "got wrong number 0x%s for flags %#x\n", + wine_dbgstr_longlong(result64), tests[i]); + + ret = vsscanf_wrapper(tests[i], "123", "%i", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == 123, "got wrong number %d for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], "-1", "%i", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == -1, "got wrong number %d for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], "123", "%d", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == 123, "got wrong number %d for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], "-1", "%d", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == -1, "got wrong number %d for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], "017", "%i", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == 15, "got wrong number %d for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], "0x17", "%i", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == 23, "got wrong number %d for flags %#x\n", result, tests[i]); + + ret = vsscanf_wrapper(tests[i], "-1", "%o", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == -1, "got wrong number %d for flags %#x\n", result, tests[i]); + + ret = 0xdeadbeef; + ret = vsscanf_wrapper(tests[i], "-1", "%u", &result); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(result == -1, "got wrong number %d for flags %#x\n", result, tests[i]); + + c = 0x55; + ret = vsscanf_wrapper(tests[i], "a", "%c", &c); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(c == 'a', "got wrong char '%c' for flags %#x\n", c, tests[i]); + + c = 0x55; + ret = vsscanf_wrapper(tests[i], " a", "%c", &c); + ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(c == ' ', "got wrong char '%c' for flags %#x\n", c, tests[i]); + + c = 0x55; + ret = vsscanf_wrapper(tests[i], "18:59", "%d:%d%c", &hour, &min, &c); + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(hour == 18, "got wrong char '%c' for flags %#x\n", hour, tests[i]); + ok(min == 59, "got wrong char '%c' for flags %#x\n", min, tests[i]); + ok(c == 0x55, "got wrong char '%c' for flags %#x\n", c, tests[i]); + + strcpy(buffer, "foo"); + strcpy(buffer1, "bar"); + ret = vsscanf_wrapper(tests[i], "abc def", "%s %n%s", buffer, &count, buffer1); + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(!strcmp(buffer, "abc"), "got wrong string '%s' for flags %#x\n", buffer, tests[i]); + ok(count == 6, "got wrong count %d for flags %#x\n", count, tests[i]); + ok(!strcmp(buffer1, "def"), "got wrong string '%s' for flags %#x\n", buffer1, tests[i]); + + ret = vsscanf_wrapper(tests[i], "3:45", "%d:%d%n", &hour, &min, &count); + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(hour == 3, "got wrong char '%c' for flags %#x\n", hour, tests[i]); + ok(min == 45, "got wrong char '%c' for flags %#x\n", min, tests[i]); + ok(count == 4, "got wrong count %d for flags %#x\n", count, tests[i]); + + strcpy(buffer, "foo"); + strcpy(buffer1, "bar"); + ret = vsscanf_wrapper(tests[i], "test=value\xda", "%[^=] = %[^;]", buffer, buffer1); + ok(ret == 2, "sscanf returned %d for flags %#x\n", ret, tests[i]); + ok(!strcmp(buffer, "test"), "got wrong string '%s' for flags %#x\n", buffer, tests[i]); + ok(!strcmp(buffer1, "value\xda"), "got wrong string '%s' for flags %#x\n", buffer1, tests[i]); + + strcpy(buffer, "foo"); + ret = vsscanf_wrapper(tests[i], "\x81\x82test", "\x81\x82%s", buffer); + todo_wine ok(ret == 0, "sscanf returned %d for flags %#x\n", ret, tests[i]); + } +} + +START_TEST(scanf) +{ + if (!init()) return; + + test_sscanf(); +}
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/msvcrt/scanf.h | 3 +++ dlls/ucrtbase/tests/scanf.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcrt/scanf.h b/dlls/msvcrt/scanf.h index 0903d6909ae9..1058a7a911a2 100644 --- a/dlls/msvcrt/scanf.h +++ b/dlls/msvcrt/scanf.h @@ -309,6 +309,9 @@ _FUNCTION_ { if (I64_prefix) _SET_NUMBER_(LONGLONG); else if (l_prefix) _SET_NUMBER_(LONG); else if (h_prefix == 1) _SET_NUMBER_(short int); +#if _MSVCR_VER >= 140 + else if (h_prefix == 2) _SET_NUMBER_(char); +#endif else _SET_NUMBER_(int); } } diff --git a/dlls/ucrtbase/tests/scanf.c b/dlls/ucrtbase/tests/scanf.c index 644e79921613..3cfee80ad426 100644 --- a/dlls/ucrtbase/tests/scanf.c +++ b/dlls/ucrtbase/tests/scanf.c @@ -188,7 +188,7 @@ static void test_sscanf(void) result = 0xdeadbeef; ret = vsscanf_wrapper(tests[i], "12345678", "%hhd", &result); ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]); - todo_wine ok(result == 0xdeadbe4e, "got wrong number %#x for flags %#x\n", result, tests[i]); + ok(result == 0xdeadbe4e, "got wrong number %#x for flags %#x\n", result, tests[i]);
ret = vsscanf_wrapper(tests[i], "12345678901234", "%lld", &result64); ok(ret == 1, "sscanf returned %d for flags %#x\n", ret, tests[i]);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=53485
Your paranoid android.
=== w1064v1809 (32 bit report) ===
ucrtbase: scanf.c:271: Test failed: sscanf returned 1 for flags 0 scanf.c:271: Test failed: sscanf returned 1 for flags 0x2 scanf.c:271: Test failed: sscanf returned 1 for flags 0x4
=== w1064v1809 (64 bit report) ===
ucrtbase: scanf.c:271: Test failed: sscanf returned 1 for flags 0 scanf.c:271: Test failed: sscanf returned 1 for flags 0x2 scanf.c:271: Test failed: sscanf returned 1 for flags 0x4
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=53484
Your paranoid android.
=== w1064v1809 (32 bit report) ===
ucrtbase: scanf.c:271: Test failed: sscanf returned 1 for flags 0 scanf.c:271: Test failed: sscanf returned 1 for flags 0x2 scanf.c:271: Test failed: sscanf returned 1 for flags 0x4
=== w1064v1809 (64 bit report) ===
ucrtbase: scanf.c:271: Test failed: sscanf returned 1 for flags 0 scanf.c:271: Test failed: sscanf returned 1 for flags 0x2 scanf.c:271: Test failed: sscanf returned 1 for flags 0x4