From c6cd8c67b4f13cc9430590207e7d8aad50cd718b Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Sun, 4 Nov 2007 15:54:33 +0000 Subject: [PATCH] - Update msvcrt_winetest to Wine-04112007. - Disable test_codepage, since it causes internal GCC error during compiling. svn path=/trunk/; revision=30119 --- rostests/winetests/msvcrt/cpp.c | 33 +- rostests/winetests/msvcrt/data.c | 79 +++ rostests/winetests/msvcrt/dir.c | 23 +- rostests/winetests/msvcrt/environ.c | 24 +- rostests/winetests/msvcrt/file.c | 613 ++++++++++++++++++++++-- rostests/winetests/msvcrt/headers.c | 493 +++++++++++++++++++ rostests/winetests/msvcrt/heap.c | 317 +++++++++++- rostests/winetests/msvcrt/msvcrt.rbuild | 30 +- rostests/winetests/msvcrt/printf.c | 141 ++++-- rostests/winetests/msvcrt/scanf.c | 45 +- rostests/winetests/msvcrt/string.c | 333 ++++++++++++- rostests/winetests/msvcrt/testlist.c | 4 +- rostests/winetests/msvcrt/time.c | 86 ++-- 13 files changed, 2077 insertions(+), 144 deletions(-) create mode 100644 rostests/winetests/msvcrt/data.c create mode 100644 rostests/winetests/msvcrt/headers.c diff --git a/rostests/winetests/msvcrt/cpp.c b/rostests/winetests/msvcrt/cpp.c index 3fd66e35c3c..f47c456a178 100644 --- a/rostests/winetests/msvcrt/cpp.c +++ b/rostests/winetests/msvcrt/cpp.c @@ -14,7 +14,7 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * NOTES * This tests is only valid for ix86 platforms, on others it's a no-op. @@ -126,7 +126,7 @@ static void* bAncientVersion; /* Emulate a __thiscall */ #ifdef _MSC_VER -_inline static void* do_call_func1(void *func, void *_this) +static inline void* do_call_func1(void *func, void *_this) { volatile void* retval = 0; __asm @@ -140,7 +140,7 @@ _inline static void* do_call_func1(void *func, void *_this) return (void*)retval; } -_inline static void* do_call_func2(void *func, void *_this, void* arg) +static inline void* do_call_func2(void *func, void *_this, const void* arg) { volatile void* retval = 0; __asm @@ -164,7 +164,7 @@ static void* do_call_func1(void *func, void *_this) : "memory" ); return ret; } -static void* do_call_func2(void *func, void *_this, void* arg) +static void* do_call_func2(void *func, void *_this, const void* arg) { void* ret; __asm__ __volatile__ ("pushl %2\n\tcall *%1" @@ -176,7 +176,7 @@ static void* do_call_func2(void *func, void *_this, void* arg) #endif #define call_func1(x,y) do_call_func1((void*)x,(void*)y) -#define call_func2(x,y,z) do_call_func2((void*)x,(void*)y,(void*)z) +#define call_func2(x,y,z) do_call_func2((void*)x,(void*)y,(const void*)z) /* Some exports are only available in later versions */ #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y) @@ -184,8 +184,10 @@ static void* do_call_func2(void *func, void *_this, void* arg) static void InitFunctionPtrs(void) { - hMsvcrt = LoadLibraryA("msvcrt.dll"); - ok(hMsvcrt != 0, "LoadLibraryA failed\n"); + hMsvcrt = GetModuleHandleA("msvcrt.dll"); + if (!hMsvcrt) + hMsvcrt = GetModuleHandleA("msvcrtd.dll"); + ok(hMsvcrt != 0, "GetModuleHandleA failed\n"); if (hMsvcrt) { SETNOFAIL(poperator_new, "??_U@YAPAXI@Z"); @@ -871,7 +873,7 @@ static int strcmp_space(const char *s1, const char *s2) static void test_demangle(void) { - static struct {const char* in; const char* out;} test[] = { + static struct {const char* in; const char* out; unsigned int flags;} test[] = { {"??0bad_alloc@std@@QAE@ABV01@@Z", "public: __thiscall std::bad_alloc::bad_alloc(class std::bad_alloc const &)"}, {"??0bad_alloc@std@@QAE@PBD@Z", "public: __thiscall std::bad_alloc::bad_alloc(char const *)"}, {"??0bad_cast@@AAE@PBQBD@Z", "private: __thiscall bad_cast::bad_cast(char const * const *)"}, @@ -973,15 +975,23 @@ static void test_demangle(void) {"??0aa$_3a@@QAE@XZ", "public: __thiscall aa$_3a::aa$_3a(void)"}, {"??2?$aaa@AAUbbb@@AAUccc@@AAU2@@ddd@1eee@2@QAEHXZ", "public: int __thiscall eee::eee::ddd::ddd::aaa::operator new(void)"}, {"?pSW@@3P6GHKPAX0PAU_tagSTACKFRAME@@0P6GH0K0KPAK@ZP6GPAX0K@ZP6GK0K@ZP6GK00PAU_tagADDRESS@@@Z@ZA", "int (__stdcall* pSW)(unsigned long,void *,void *,struct _tagSTACKFRAME *,void *,int (__stdcall*)(void *,unsigned long,void *,unsigned long,unsigned long *),void * (__stdcall*)(void *,unsigned long),unsigned long (__stdcall*)(void *,unsigned long),unsigned long (__stdcall*)(void *,void *,struct _tagADDRESS *))"}, +{"?$_aaa@Vbbb@@", "_aaa"}, +{"?$aaa@Vbbb@ccc@@Vddd@2@", "aaa"}, +{ "??0?$Foo@P6GHPAX0@Z@@QAE@PAD@Z", "public: __thiscall Foo::Foo(char *)"}, +{ "??0?$Foo@P6GHPAX0@Z@@QAE@PAD@Z", "__thiscall Foo::Foo(char *)", 0x880}, +{ "?Qux@Bar@@0PAP6AHPAV1@AAH1PAH@ZA", "private: static int (__cdecl** Bar::Qux)(class Bar *,int &,int &,int *)" }, +{ "?Qux@Bar@@0PAP6AHPAV1@AAH1PAH@ZA", "Bar::Qux", 0x1800}, }; int i, num_test = (sizeof(test)/sizeof(test[0])); char* name; for (i = 0; i < num_test; i++) { - name = p__unDName(0, test[i].in, 0, pmalloc, pfree, 0); + name = p__unDName(0, test[i].in, 0, pmalloc, pfree, test[i].flags); ok(name != NULL && !strcmp_space(test[i].out, name), - "Got name \"%s\" for %d\n", name, i); + "Got name \"%s\" for %d\n", name, i ); + ok(name != NULL && !strcmp_space(test[i].out, name), + "Expected \"%s\"\n", test[i].out ); pfree(name); } } @@ -998,8 +1008,5 @@ START_TEST(cpp) test_rtti(); test_demangle_datatype(); test_demangle(); - - if (hMsvcrt) - FreeLibrary(hMsvcrt); } #endif /* __i386__ */ diff --git a/rostests/winetests/msvcrt/data.c b/rostests/winetests/msvcrt/data.c new file mode 100644 index 00000000000..a981c876cb9 --- /dev/null +++ b/rostests/winetests/msvcrt/data.c @@ -0,0 +1,79 @@ +/* + * Tests msvcrt/data.c + * + * Copyright 2006 Andrew Ziem + * + * 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 "wine/test.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef void (*_INITTERMFUN)(void); +static void (*p_initterm)(_INITTERMFUN *start, _INITTERMFUN *end); + +static int callbacked; + +static void initcallback(void) +{ + callbacked++; +} + +#define initterm_test(start, end, expected) \ + callbacked = 0; \ + p_initterm(start, end); \ + ok(expected == callbacked,"_initterm: callbacks count mismatch: got %i, expected %i\n", callbacked, expected); + +static void test_initterm(void) +{ + int i; + static _INITTERMFUN callbacks[4]; + + if (!p_initterm) + return; + + for (i = 0; i < 4; i++) + { + callbacks[i] = initcallback; + } + + initterm_test(&callbacks[0], &callbacks[1], 1); + initterm_test(&callbacks[0], &callbacks[2], 2); + initterm_test(&callbacks[0], &callbacks[3], 3); + + callbacks[1] = NULL; + initterm_test(&callbacks[0], &callbacks[3], 2); +} + +START_TEST(data) +{ + HMODULE hmsvcrt; + hmsvcrt = GetModuleHandleA("msvcrt.dll"); + if (!hmsvcrt) + hmsvcrt = GetModuleHandleA("msvcrtd.dll"); + if (hmsvcrt) + p_initterm=(void*)GetProcAddress(hmsvcrt, "_initterm"); + test_initterm(); +} diff --git a/rostests/winetests/msvcrt/dir.c b/rostests/winetests/msvcrt/dir.c index 3c8ba21c5a4..6929a76a5eb 100644 --- a/rostests/winetests/msvcrt/dir.c +++ b/rostests/winetests/msvcrt/dir.c @@ -15,7 +15,7 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "wine/test.h" @@ -31,10 +31,26 @@ #include #include -void test_fullpath(void) +static void test_makepath(void) +{ + char buffer[MAX_PATH]; + + _makepath(buffer, "C", "\\foo", "dummy", "txt"); + ok( strcmp(buffer, "C:\\foo\\dummy.txt") == 0, "unexpected result: %s\n", buffer); + _makepath(buffer, "C:", "\\foo\\", "dummy", ".txt"); + ok( strcmp(buffer, "C:\\foo\\dummy.txt") == 0, "unexpected result: %s\n", buffer); + + /* this works with native and e.g. Freelancer depends on it */ + strcpy(buffer, "foo"); + _makepath(buffer, NULL, buffer, "dummy.txt", NULL); + ok( strcmp(buffer, "foo\\dummy.txt") == 0, "unexpected result: %s\n", buffer); +} + +static void test_fullpath(void) { char full[MAX_PATH]; char tmppath[MAX_PATH]; + char prevpath[MAX_PATH]; char level1[MAX_PATH]; char level2[MAX_PATH]; char teststring[MAX_PATH]; @@ -42,6 +58,7 @@ void test_fullpath(void) BOOL rc,free1,free2; free1=free2=TRUE; + GetCurrentDirectory(MAX_PATH, prevpath); GetTempPath(MAX_PATH,tmppath); strcpy(level1,tmppath); strcat(level1,"msvcrt-test\\"); @@ -79,6 +96,7 @@ void test_fullpath(void) ok(strcmp(freeme,teststring)==0,"Invalid Path returned %s\n",freeme); free(freeme); + SetCurrentDirectory(prevpath); if (free2) RemoveDirectory(level2); if (free1) @@ -88,4 +106,5 @@ void test_fullpath(void) START_TEST(dir) { test_fullpath(); + test_makepath(); } diff --git a/rostests/winetests/msvcrt/environ.c b/rostests/winetests/msvcrt/environ.c index 87355bcdbb6..6175e14af69 100644 --- a/rostests/winetests/msvcrt/environ.c +++ b/rostests/winetests/msvcrt/environ.c @@ -15,12 +15,33 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "wine/test.h" #include +static const char *a_very_long_env_string = + "LIBRARY_PATH=" + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/;" + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/;" + "/mingw/lib/gcc/mingw32/3.4.2/;" + "/usr/lib/gcc/mingw32/3.4.2/;" + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/../../../../mingw32/lib/mingw32/3.4.2/;" + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/../../../../mingw32/lib/;" + "/mingw/mingw32/lib/mingw32/3.4.2/;" + "/mingw/mingw32/lib/;" + "/mingw/lib/mingw32/3.4.2/;" + "/mingw/lib/;" + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/../../../mingw32/3.4.2/;" + "C:/Program Files/GLBasic/Compiler/platform/Win32/Bin/../lib/gcc/mingw32/3.4.2/../../../;" + "/mingw/lib/mingw32/3.4.2/;" + "/mingw/lib/;" + "/lib/mingw32/3.4.2/;" + "/lib/;" + "/usr/lib/mingw32/3.4.2/;" + "/usr/lib/"; + START_TEST(environ) { ok( _putenv("cat=") == 0, "_putenv failed on deletion of nonexistent environment variable\n" ); @@ -30,6 +51,7 @@ START_TEST(environ) ok( _putenv("=") == -1, "should not accept '=' as input\n" ); ok( _putenv("=dog") == -1, "should not accept '=dog' as input\n" ); + ok( _putenv(a_very_long_env_string) == 0, "_putenv failed for long environment string\n"); ok( getenv("nonexistent") == NULL, "getenv should fail with nonexistent var name\n" ); } diff --git a/rostests/winetests/msvcrt/file.c b/rostests/winetests/msvcrt/file.c index 100ddf7db1b..e0f1b997e1f 100644 --- a/rostests/winetests/msvcrt/file.c +++ b/rostests/winetests/msvcrt/file.c @@ -16,7 +16,7 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "wine/test.h" @@ -24,14 +24,18 @@ #include #include #include +#include #include #include +#include #include #include #include #include #include +static HANDLE proc_handles[2]; + static void test_fdopen( void ) { static const char buffer[] = {0,1,2,3,4,5,6,7,8,9}; @@ -131,7 +135,178 @@ static void test_fileops( void ) unlink ("fdopen.tst"); } -static WCHAR* AtoW( char* p ) +#define IOMODE (ao?"ascii mode":"binary mode") +static void test_readmode( BOOL ascii_mode ) +{ + static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9\r\n\r\nA,B,C,D,E\r\nX,Y,Z"; + static const char padbuffer[] = "ghjghjghjghj"; + static const char nlbuffer[] = "\r\n"; + char buffer[2*BUFSIZ+256]; + const char *optr; + int fd; + FILE *file; + const int *ip; + int i, j, m, ao, pl; + unsigned int fp; + long l; + + fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE); + /* an internal buffer of BUFSIZ is maintained, so make a file big + * enough to test operations that cross the buffer boundary + */ + j = (2*BUFSIZ-4)/strlen(padbuffer); + for (i=0; i= 0) + { + if (fstat(fd, &buf) == 0) + { + if ((buf.st_mode & _S_IFMT) == _S_IFREG) + { + ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev); + ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", + buf.st_dev, buf.st_rdev); + ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", + buf.st_nlink); + ok(buf.st_size == 0, "st_size is %d, expected 0\n", + buf.st_size); + } + else + skip("file is not a file?\n"); + } + else + skip("fstat failed, errno %d\n", errno); + close(fd); + remove("stat.tst"); + } + else + skip("open failed with errno %d\n", errno); + + /* Tests for a char device */ + if (_dup2(0, 10) == 0) + { + if (fstat(10, &buf) == 0) + { + if (buf.st_mode == _S_IFCHR) + { + ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev); + ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev); + ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink); + } + else + skip("stdin is not a char device?\n"); + } + else + skip("fstat failed with errno %d\n", errno); + close(10); + } + else + skip("_dup2 failed with errno %d\n", errno); + + /* Tests for pipes */ + if (_pipe(pipes, 1024, O_BINARY) == 0) + { + if (fstat(pipes[0], &buf) == 0) + { + if (buf.st_mode == _S_IFIFO) + { + ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", + buf.st_dev, pipes[0]); + ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", + buf.st_rdev, pipes[0]); + ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", + buf.st_nlink); + } + else + skip("pipe() didn't make a pipe?\n"); + } + else + skip("fstat failed with errno %d\n", errno); + close(pipes[0]); + close(pipes[1]); + } + else + skip("pipe failed with errno %d\n", errno); +} + +static const char* pipe_string="Hello world"; + +static void test_pipes_child(int argc, char** args) +{ + int fd; + + if (argc < 5) + { + ok(0, "not enough parameters: %d\n", argc); + return; + } + + fd=atoi(args[3]); + ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno); + + fd=atoi(args[4]); + write(fd, pipe_string, strlen(pipe_string)); + ok(close(fd) == 0, "unable to close %d: %d\n", fd, errno); +} + +static void test_pipes(const char* selfname) +{ + int pipes[2]; + char str_fdr[12], str_fdw[12]; + FILE* file; + const char* arg_v[6]; + char buf[4096]; + int r; + + /* Test reading from a pipe with read() */ + if (_pipe(pipes, 1024, O_BINARY) < 0) + { + ok(0, "pipe failed with errno %d\n", errno); + return; + } + + arg_v[0] = selfname; + arg_v[1] = "tests/file.c"; + arg_v[2] = "pipes"; + arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]); + arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]); + arg_v[5] = NULL; + proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v); + ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno); + + r=read(pipes[0], buf, sizeof(buf)-1); + ok(r == strlen(pipe_string), "expected to read %d bytes, got %d\n", strlen(pipe_string)+1, r); + if (r > 0) + buf[r]='\0'; + ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf); + r=read(pipes[0], buf, sizeof(buf)-1); + ok(r == 0, "expected to read 0 bytes, got %d\n", r); + ok(close(pipes[0]) == 0, "unable to close %d: %d\n", pipes[0], errno); + + /* Test reading from a pipe with fread() */ + if (_pipe(pipes, 1024, O_BINARY) < 0) + { + ok(0, "pipe failed with errno %d\n", errno); + return; + } + + arg_v[0] = selfname; + arg_v[1] = "tests/file.c"; + arg_v[2] = "pipes"; + arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]); + arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]); + arg_v[5] = NULL; + proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v); + ok(close(pipes[1]) == 0, "unable to close %d: %d\n", pipes[1], errno); + file=fdopen(pipes[0], "r"); + + r=fread(buf, 1, sizeof(buf)-1, file); + ok(r == strlen(pipe_string), "fread() returned %d instead of %d: ferror=%d\n", r, strlen(pipe_string), ferror(file)); + if (r > 0) + buf[r]='\0'; + ok(strcmp(buf, pipe_string) == 0, "got '%s' expected '%s'\n", buf, pipe_string); + + r=fread(buf, 1, sizeof(buf)-1, file); + ok(r == 0, "fread() returned %d instead of 0\n", r); + ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file)); + ok(feof(file), "feof() is false!\n"); + + ok(fclose(file) == 0, "unable to close the pipe: %d\n", errno); +} + START_TEST(file) { int arg_c; @@ -474,19 +1011,39 @@ START_TEST(file) /* testing low-level I/O */ if (arg_c >= 3) { - if (arg_c == 3) test_file_inherit_child(arg_v[2]); - else test_file_inherit_child_no(arg_v[2]); + if (strcmp(arg_v[2], "inherit") == 0) + test_file_inherit_child(arg_v[3]); + else if (strcmp(arg_v[2], "inherit_no") == 0) + test_file_inherit_child_no(arg_v[3]); + else if (strcmp(arg_v[2], "pipes") == 0) + test_pipes_child(arg_c, arg_v); + else + ok(0, "invalid argument '%s'\n", arg_v[2]); return; } test_file_inherit(arg_v[0]); test_file_write_read(); test_chsize(); + test_stat(); /* testing stream I/O */ test_fdopen(); test_fopen_fclose_fcloseall(); test_fileops(); + test_asciimode(); + test_readmode(FALSE); /* binary mode */ + test_readmode(TRUE); /* ascii mode */ + test_fgetc(); test_fgetwc(); + test_ctrlz(); test_file_put_get(); test_tmpnam(); + test_get_osfhandle(); + test_setmaxstdio(); + test_pipes(arg_v[0]); + + /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report + * file contains lines in the correct order + */ + WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000); } diff --git a/rostests/winetests/msvcrt/headers.c b/rostests/winetests/msvcrt/headers.c new file mode 100644 index 00000000000..d909ac7bf43 --- /dev/null +++ b/rostests/winetests/msvcrt/headers.c @@ -0,0 +1,493 @@ +/* + * Copyright 2004 Dimitrie O. Paun + * + * 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 + * + * This file contains tests to ensure the consistency between symbols + * defined in the regular msvcrt headers, and the corresponding duplicated + * symbols defined in msvcrt.h (prefixed by MSVCRT_). + */ + +#include "dos.h" +#include "math.h" +#include "stdlib.h" +#include "io.h" +#include "errno.h" +#include "fcntl.h" +#include "malloc.h" +#include "limits.h" +#include "mbctype.h" +#include "stdio.h" +#include "wchar.h" +#include "ctype.h" +//#include "crtdbg.h" +#include "share.h" +#include "search.h" +#include "wctype.h" +#include "float.h" +#include "stddef.h" +#include "mbstring.h" +#include "sys/locking.h" +#include "sys/utime.h" +#include "sys/types.h" +#include "sys/stat.h" +#include "sys/timeb.h" +#include "direct.h" +#include "conio.h" +#include "process.h" +#include "string.h" +#include "signal.h" +#include "time.h" +#include "locale.h" +#include "setjmp.h" +#include "wine/test.h" + +#ifdef __WINE_USE_MSVCRT +/* Wine-specific msvcrt headers */ +#define __WINE_MSVCRT_TEST +#include "eh.h" +#include "msvcrt.h" + +#ifdef __GNUC__ +#define TYPEOF(type) typeof(type) +#else +#define TYPEOF(type) int +#endif +#define MSVCRT(x) MSVCRT_##x +#define OFFSET(T,F) ((unsigned int)((char *)&((struct T *)0L)->F - (char *)0L)) +#define CHECK_SIZE(e) ok(sizeof(e) == sizeof(MSVCRT(e)), "Element has different sizes\n") +#define CHECK_TYPE(t) { TYPEOF(t) a = 0; TYPEOF(MSVCRT(t)) b = 0; a = b; CHECK_SIZE(t); } +#define CHECK_STRUCT(s) ok(sizeof(struct s) == sizeof(struct MSVCRT(s)), "Struct has different sizes\n") +#define CHECK_FIELD(s,e) ok(OFFSET(s,e) == OFFSET(MSVCRT(s),e), "Bad offset\n") +#define CHECK_DEF(d) ok(d == MSVCRT_##d, "Defines (MSVCRT_)" #d " are different: %d vs. %d\n", d, MSVCRT_##d) + +/************* Checking types ***************/ +static void test_types(void) +{ + CHECK_TYPE(wchar_t); + CHECK_TYPE(wint_t); + CHECK_TYPE(wctype_t); + CHECK_TYPE(_ino_t); + CHECK_TYPE(_fsize_t); + CHECK_TYPE(size_t); + CHECK_TYPE(intptr_t); + CHECK_TYPE(uintptr_t); + CHECK_TYPE(_dev_t); + CHECK_TYPE(_off_t); + CHECK_TYPE(clock_t); + CHECK_TYPE(time_t); + CHECK_TYPE(__time64_t); + CHECK_TYPE(fpos_t); + CHECK_SIZE(FILE); + CHECK_TYPE(terminate_handler); + CHECK_TYPE(terminate_function); + CHECK_TYPE(unexpected_handler); + CHECK_TYPE(unexpected_function); + CHECK_TYPE(_se_translator_function); + CHECK_TYPE(_beginthread_start_routine_t); + CHECK_TYPE(_onexit_t); + CHECK_TYPE(__sighandler_t); +} + +/************* Checking structs ***************/ +static void test_structs(void) +{ + CHECK_STRUCT(tm); + CHECK_FIELD(tm, tm_sec); + CHECK_FIELD(tm, tm_min); + CHECK_FIELD(tm, tm_hour); + CHECK_FIELD(tm, tm_mday); + CHECK_FIELD(tm, tm_mon); + CHECK_FIELD(tm, tm_year); + CHECK_FIELD(tm, tm_wday); + CHECK_FIELD(tm, tm_yday); + CHECK_FIELD(tm, tm_isdst); + CHECK_STRUCT(_timeb); + CHECK_FIELD(_timeb, time); + CHECK_FIELD(_timeb, millitm); + CHECK_FIELD(_timeb, timezone); + CHECK_FIELD(_timeb, dstflag); + CHECK_STRUCT(_iobuf); + CHECK_FIELD(_iobuf, _ptr); + CHECK_FIELD(_iobuf, _cnt); + CHECK_FIELD(_iobuf, _base); + CHECK_FIELD(_iobuf, _flag); + CHECK_FIELD(_iobuf, _file); + CHECK_FIELD(_iobuf, _charbuf); + CHECK_FIELD(_iobuf, _bufsiz); + CHECK_FIELD(_iobuf, _tmpfname); + CHECK_STRUCT(lconv); + CHECK_FIELD(lconv, decimal_point); + CHECK_FIELD(lconv, thousands_sep); + CHECK_FIELD(lconv, grouping); + CHECK_FIELD(lconv, int_curr_symbol); + CHECK_FIELD(lconv, currency_symbol); + CHECK_FIELD(lconv, mon_decimal_point); + CHECK_FIELD(lconv, mon_thousands_sep); + CHECK_FIELD(lconv, mon_grouping); + CHECK_FIELD(lconv, positive_sign); + CHECK_FIELD(lconv, negative_sign); + CHECK_FIELD(lconv, int_frac_digits); + CHECK_FIELD(lconv, frac_digits); + CHECK_FIELD(lconv, p_cs_precedes); + CHECK_FIELD(lconv, p_sep_by_space); + CHECK_FIELD(lconv, n_cs_precedes); + CHECK_FIELD(lconv, n_sep_by_space); + CHECK_FIELD(lconv, p_sign_posn); + CHECK_FIELD(lconv, n_sign_posn); + CHECK_STRUCT(_exception); + CHECK_FIELD(_exception, type); + CHECK_FIELD(_exception, name); + CHECK_FIELD(_exception, arg1); + CHECK_FIELD(_exception, arg2); + CHECK_FIELD(_exception, retval); + CHECK_STRUCT(_complex); + CHECK_FIELD(_complex, x); + CHECK_FIELD(_complex, y); + CHECK_STRUCT(_div_t); + CHECK_FIELD(_div_t, quot); + CHECK_FIELD(_div_t, rem); + CHECK_STRUCT(_ldiv_t); + CHECK_FIELD(_ldiv_t, quot); + CHECK_FIELD(_ldiv_t, rem); + CHECK_STRUCT(_heapinfo); + CHECK_FIELD(_heapinfo, _pentry); + CHECK_FIELD(_heapinfo, _size); + CHECK_FIELD(_heapinfo, _useflag); +#ifdef __i386__ + CHECK_STRUCT(__JUMP_BUFFER); + CHECK_FIELD(__JUMP_BUFFER, Ebp); + CHECK_FIELD(__JUMP_BUFFER, Ebx); + CHECK_FIELD(__JUMP_BUFFER, Edi); + CHECK_FIELD(__JUMP_BUFFER, Esi); + CHECK_FIELD(__JUMP_BUFFER, Esp); + CHECK_FIELD(__JUMP_BUFFER, Eip); + CHECK_FIELD(__JUMP_BUFFER, Registration); + CHECK_FIELD(__JUMP_BUFFER, TryLevel); + CHECK_FIELD(__JUMP_BUFFER, Cookie); + CHECK_FIELD(__JUMP_BUFFER, UnwindFunc); + CHECK_FIELD(__JUMP_BUFFER, UnwindData[6]); +#endif + CHECK_STRUCT(_diskfree_t); + CHECK_FIELD(_diskfree_t, total_clusters); + CHECK_FIELD(_diskfree_t, avail_clusters); + CHECK_FIELD(_diskfree_t, sectors_per_cluster); + CHECK_FIELD(_diskfree_t, bytes_per_sector); + CHECK_STRUCT(_finddata_t); + CHECK_FIELD(_finddata_t, attrib); + CHECK_FIELD(_finddata_t, time_create); + CHECK_FIELD(_finddata_t, time_access); + CHECK_FIELD(_finddata_t, time_write); + CHECK_FIELD(_finddata_t, size); + CHECK_FIELD(_finddata_t, name[260]); + CHECK_STRUCT(_finddatai64_t); + CHECK_FIELD(_finddatai64_t, attrib); + CHECK_FIELD(_finddatai64_t, time_create); + CHECK_FIELD(_finddatai64_t, time_access); + CHECK_FIELD(_finddatai64_t, time_write); + CHECK_FIELD(_finddatai64_t, size); + CHECK_FIELD(_finddatai64_t, name[260]); + CHECK_STRUCT(_wfinddata_t); + CHECK_FIELD(_wfinddata_t, attrib); + CHECK_FIELD(_wfinddata_t, time_create); + CHECK_FIELD(_wfinddata_t, time_access); + CHECK_FIELD(_wfinddata_t, time_write); + CHECK_FIELD(_wfinddata_t, size); + CHECK_FIELD(_wfinddata_t, name[260]); + CHECK_STRUCT(_wfinddatai64_t); + CHECK_FIELD(_wfinddatai64_t, attrib); + CHECK_FIELD(_wfinddatai64_t, time_create); + CHECK_FIELD(_wfinddatai64_t, time_access); + CHECK_FIELD(_wfinddatai64_t, time_write); + CHECK_FIELD(_wfinddatai64_t, size); + CHECK_FIELD(_wfinddatai64_t, name[260]); + CHECK_STRUCT(_utimbuf); + CHECK_FIELD(_utimbuf, actime); + CHECK_FIELD(_utimbuf, modtime); + CHECK_STRUCT(_stat); + CHECK_FIELD(_stat, st_dev); + CHECK_FIELD(_stat, st_ino); + CHECK_FIELD(_stat, st_mode); + CHECK_FIELD(_stat, st_nlink); + CHECK_FIELD(_stat, st_uid); + CHECK_FIELD(_stat, st_gid); + CHECK_FIELD(_stat, st_rdev); + CHECK_FIELD(_stat, st_size); + CHECK_FIELD(_stat, st_atime); + CHECK_FIELD(_stat, st_mtime); + CHECK_FIELD(_stat, st_ctime); + CHECK_FIELD(_stat, st_dev); + CHECK_FIELD(_stat, st_ino); + CHECK_FIELD(_stat, st_mode); + CHECK_FIELD(_stat, st_nlink); + CHECK_FIELD(_stat, st_uid); + CHECK_FIELD(_stat, st_gid); + CHECK_FIELD(_stat, st_rdev); + CHECK_FIELD(_stat, st_size); + CHECK_FIELD(_stat, st_atime); + CHECK_FIELD(_stat, st_mtime); + CHECK_FIELD(_stat, st_ctime); + CHECK_FIELD(_stat, st_dev); + CHECK_FIELD(_stat, st_ino); + CHECK_FIELD(_stat, st_mode); + CHECK_FIELD(_stat, st_nlink); + CHECK_FIELD(_stat, st_uid); + CHECK_FIELD(_stat, st_gid); + CHECK_FIELD(_stat, st_rdev); + CHECK_FIELD(_stat, st_size); + CHECK_FIELD(_stat, st_atime); + CHECK_FIELD(_stat, st_mtime); + CHECK_FIELD(_stat, st_ctime); + CHECK_STRUCT(stat); + CHECK_FIELD(stat, st_dev); + CHECK_FIELD(stat, st_ino); + CHECK_FIELD(stat, st_mode); + CHECK_FIELD(stat, st_nlink); + CHECK_FIELD(stat, st_uid); + CHECK_FIELD(stat, st_gid); + CHECK_FIELD(stat, st_rdev); + CHECK_FIELD(stat, st_size); + CHECK_FIELD(stat, st_atime); + CHECK_FIELD(stat, st_mtime); + CHECK_FIELD(stat, st_ctime); + CHECK_FIELD(stat, st_dev); + CHECK_FIELD(stat, st_ino); + CHECK_FIELD(stat, st_mode); + CHECK_FIELD(stat, st_nlink); + CHECK_FIELD(stat, st_uid); + CHECK_FIELD(stat, st_gid); + CHECK_FIELD(stat, st_rdev); + CHECK_FIELD(stat, st_size); + CHECK_FIELD(stat, st_atime); + CHECK_FIELD(stat, st_mtime); + CHECK_FIELD(stat, st_ctime); + CHECK_FIELD(stat, st_dev); + CHECK_FIELD(stat, st_ino); + CHECK_FIELD(stat, st_mode); + CHECK_FIELD(stat, st_nlink); + CHECK_FIELD(stat, st_uid); + CHECK_FIELD(stat, st_gid); + CHECK_FIELD(stat, st_rdev); + CHECK_FIELD(stat, st_size); + CHECK_FIELD(stat, st_atime); + CHECK_FIELD(stat, st_mtime); + CHECK_FIELD(stat, st_ctime); + CHECK_STRUCT(_stati64); + CHECK_FIELD(_stati64, st_dev); + CHECK_FIELD(_stati64, st_ino); + CHECK_FIELD(_stati64, st_mode); + CHECK_FIELD(_stati64, st_nlink); + CHECK_FIELD(_stati64, st_uid); + CHECK_FIELD(_stati64, st_gid); + CHECK_FIELD(_stati64, st_rdev); + CHECK_FIELD(_stati64, st_size); + CHECK_FIELD(_stati64, st_atime); + CHECK_FIELD(_stati64, st_mtime); + CHECK_FIELD(_stati64, st_ctime); + CHECK_STRUCT(_stat64); + CHECK_FIELD(_stat64, st_dev); + CHECK_FIELD(_stat64, st_ino); + CHECK_FIELD(_stat64, st_mode); + CHECK_FIELD(_stat64, st_nlink); + CHECK_FIELD(_stat64, st_uid); + CHECK_FIELD(_stat64, st_gid); + CHECK_FIELD(_stat64, st_rdev); + CHECK_FIELD(_stat64, st_size); + CHECK_FIELD(_stat64, st_atime); + CHECK_FIELD(_stat64, st_mtime); + CHECK_FIELD(_stat64, st_ctime); +} + +/************* Checking defines ***************/ +static void test_defines(void) +{ + CHECK_DEF(WEOF); + CHECK_DEF(EOF); + CHECK_DEF(TMP_MAX); + CHECK_DEF(RAND_MAX); + CHECK_DEF(BUFSIZ); + CHECK_DEF(STDIN_FILENO); + CHECK_DEF(STDOUT_FILENO); + CHECK_DEF(STDERR_FILENO); + CHECK_DEF(_IOFBF); + CHECK_DEF(_IONBF); + CHECK_DEF(_IOLBF); + CHECK_DEF(FILENAME_MAX); + CHECK_DEF(_P_WAIT); + CHECK_DEF(_P_NOWAIT); + CHECK_DEF(_P_OVERLAY); + CHECK_DEF(_P_NOWAITO); + CHECK_DEF(_P_DETACH); + CHECK_DEF(EPERM); + CHECK_DEF(ENOENT); + CHECK_DEF(ESRCH); + CHECK_DEF(EINTR); + CHECK_DEF(EIO); + CHECK_DEF(ENXIO); + CHECK_DEF(E2BIG); + CHECK_DEF(ENOEXEC); + CHECK_DEF(EBADF); + CHECK_DEF(ECHILD); + CHECK_DEF(EAGAIN); + CHECK_DEF(ENOMEM); + CHECK_DEF(EACCES); + CHECK_DEF(EFAULT); + CHECK_DEF(EBUSY); + CHECK_DEF(EEXIST); + CHECK_DEF(EXDEV); + CHECK_DEF(ENODEV); + CHECK_DEF(ENOTDIR); + CHECK_DEF(EISDIR); + CHECK_DEF(EINVAL); + CHECK_DEF(ENFILE); + CHECK_DEF(EMFILE); + CHECK_DEF(ENOTTY); + CHECK_DEF(EFBIG); + CHECK_DEF(ENOSPC); + CHECK_DEF(ESPIPE); + CHECK_DEF(EROFS); + CHECK_DEF(EMLINK); + CHECK_DEF(EPIPE); + CHECK_DEF(EDOM); + CHECK_DEF(ERANGE); + CHECK_DEF(EDEADLK); + CHECK_DEF(EDEADLOCK); + CHECK_DEF(ENAMETOOLONG); + CHECK_DEF(ENOLCK); + CHECK_DEF(ENOSYS); + CHECK_DEF(ENOTEMPTY); + CHECK_DEF(EILSEQ); + CHECK_DEF(LC_ALL); + CHECK_DEF(LC_COLLATE); + CHECK_DEF(LC_CTYPE); + CHECK_DEF(LC_MONETARY); + CHECK_DEF(LC_NUMERIC); + CHECK_DEF(LC_TIME); + CHECK_DEF(LC_MIN); + CHECK_DEF(LC_MAX); + CHECK_DEF(CLOCKS_PER_SEC); + CHECK_DEF(_HEAPEMPTY); + CHECK_DEF(_HEAPOK); + CHECK_DEF(_HEAPBADBEGIN); + CHECK_DEF(_HEAPBADNODE); + CHECK_DEF(_HEAPEND); + CHECK_DEF(_HEAPBADPTR); + CHECK_DEF(_FREEENTRY); + CHECK_DEF(_USEDENTRY); + CHECK_DEF(_OUT_TO_DEFAULT); + CHECK_DEF(_REPORT_ERRMODE); + CHECK_DEF(_UPPER); + CHECK_DEF(_LOWER); + CHECK_DEF(_DIGIT); + CHECK_DEF(_SPACE); + CHECK_DEF(_PUNCT); + CHECK_DEF(_CONTROL); + CHECK_DEF(_BLANK); + CHECK_DEF(_HEX); + CHECK_DEF(_LEADBYTE); + CHECK_DEF(_ALPHA); + CHECK_DEF(_IOREAD); + CHECK_DEF(_IOWRT); + CHECK_DEF(_IOMYBUF); + CHECK_DEF(_IOEOF); + CHECK_DEF(_IOERR); + CHECK_DEF(_IOSTRG); + CHECK_DEF(_IORW); + CHECK_DEF(_S_IEXEC); + CHECK_DEF(_S_IWRITE); + CHECK_DEF(_S_IREAD); + CHECK_DEF(_S_IFIFO); + CHECK_DEF(_S_IFCHR); + CHECK_DEF(_S_IFDIR); + CHECK_DEF(_S_IFREG); + CHECK_DEF(_S_IFMT); + CHECK_DEF(_LK_UNLCK); + CHECK_DEF(_LK_LOCK); + CHECK_DEF(_LK_NBLCK); + CHECK_DEF(_LK_RLCK); + CHECK_DEF(_LK_NBRLCK); + CHECK_DEF(_O_RDONLY); + CHECK_DEF(_O_WRONLY); + CHECK_DEF(_O_RDWR); + CHECK_DEF(_O_ACCMODE); + CHECK_DEF(_O_APPEND); + CHECK_DEF(_O_RANDOM); + CHECK_DEF(_O_SEQUENTIAL); + CHECK_DEF(_O_TEMPORARY); + CHECK_DEF(_O_NOINHERIT); + CHECK_DEF(_O_CREAT); + CHECK_DEF(_O_TRUNC); + CHECK_DEF(_O_EXCL); + CHECK_DEF(_O_SHORT_LIVED); + CHECK_DEF(_O_TEXT); + CHECK_DEF(_O_BINARY); + CHECK_DEF(_O_RAW); + CHECK_DEF(_SW_INEXACT); + CHECK_DEF(_SW_UNDERFLOW); + CHECK_DEF(_SW_OVERFLOW); + CHECK_DEF(_SW_ZERODIVIDE); + CHECK_DEF(_SW_INVALID); + CHECK_DEF(_SW_UNEMULATED); + CHECK_DEF(_SW_SQRTNEG); + CHECK_DEF(_SW_STACKOVERFLOW); + CHECK_DEF(_SW_STACKUNDERFLOW); + CHECK_DEF(_SW_DENORMAL); + CHECK_DEF(_FPCLASS_SNAN); + CHECK_DEF(_FPCLASS_QNAN); + CHECK_DEF(_FPCLASS_NINF); + CHECK_DEF(_FPCLASS_NN); + CHECK_DEF(_FPCLASS_ND); + CHECK_DEF(_FPCLASS_NZ); + CHECK_DEF(_FPCLASS_PZ); + CHECK_DEF(_FPCLASS_PD); + CHECK_DEF(_FPCLASS_PN); + CHECK_DEF(_FPCLASS_PINF); + CHECK_DEF(SIGINT); + CHECK_DEF(SIGILL); + CHECK_DEF(SIGFPE); + CHECK_DEF(SIGSEGV); + CHECK_DEF(SIGTERM); + CHECK_DEF(SIGBREAK); + CHECK_DEF(SIGABRT); + CHECK_DEF(NSIG); +#ifdef __i386__ + CHECK_DEF(_EM_INVALID); + CHECK_DEF(_EM_DENORMAL); + CHECK_DEF(_EM_ZERODIVIDE); + CHECK_DEF(_EM_OVERFLOW); + CHECK_DEF(_EM_UNDERFLOW); + CHECK_DEF(_EM_INEXACT); + CHECK_DEF(_IC_AFFINE); + CHECK_DEF(_IC_PROJECTIVE); + CHECK_DEF(_RC_CHOP); + CHECK_DEF(_RC_UP); + CHECK_DEF(_RC_DOWN); + CHECK_DEF(_RC_NEAR); + CHECK_DEF(_PC_24); + CHECK_DEF(_PC_53); + CHECK_DEF(_PC_64); +#endif +} + +#endif /* __WINE_USE_MSVCRT */ + +START_TEST(headers) +{ +#ifdef __WINE_USE_MSVCRT + test_types(); + test_structs(); + test_defines(); +#endif +} diff --git a/rostests/winetests/msvcrt/heap.c b/rostests/winetests/msvcrt/heap.c index 765caecc96e..2c4943a9ed2 100644 --- a/rostests/winetests/msvcrt/heap.c +++ b/rostests/winetests/msvcrt/heap.c @@ -15,12 +15,325 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include +#include +#include #include "wine/test.h" +static void (*p_aligned_free)(void*) = NULL; +static void * (*p_aligned_malloc)(size_t,size_t) = NULL; +static void * (*p_aligned_offset_malloc)(size_t,size_t,size_t) = NULL; +static void * (*p_aligned_realloc)(void*,size_t,size_t) = NULL; +static void * (*p_aligned_offset_realloc)(void*,size_t,size_t,size_t) = NULL; + +static void test_aligned_malloc(size_t size, size_t alignment) +{ + void *mem; + + mem = p_aligned_malloc(size, alignment); + + if ((alignment & (alignment - 1)) == 0) + ok(mem != NULL, "_aligned_malloc(%d, %d) failed\n", size, alignment); + else + ok(mem == NULL, "_aligned_malloc(%d, %d) should have failed\n", size, alignment); + + if (mem) + { + ok(((DWORD_PTR)mem & (alignment ? alignment - 1 : 0)) == 0, + "_aligned_malloc(%d, %d) not aligned: %p\n", size, alignment, mem); + if (winetest_debug > 1) + { + void *saved; + saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1)); + trace("_aligned_malloc(%3d, %3d) returns %p, saved = %p, diff = %d\n", + size, alignment, mem, saved, (char *)saved - (char *)mem); + } + p_aligned_free(mem); + } + else + ok(errno == EINVAL, "_aligned_malloc(%d, %d) errno: %d != %d\n", size, alignment, errno, EINVAL); +} + +static void test_aligned_offset_malloc(size_t size, size_t alignment, size_t offset) +{ + void *mem; + + mem = p_aligned_offset_malloc(size, alignment, offset); + + if ((alignment & (alignment - 1)) == 0) + if (offset < size) + ok(mem != NULL, "_aligned_offset_malloc(%d, %d, %d) failed\n", size, alignment, offset); + else + ok(errno == EINVAL, "_aligned_offset_malloc(%d, %d, %d) errno: %d != %d\n", size, alignment, offset, errno, EINVAL); + else + ok(mem == NULL, "_aligned_offset_malloc(%d, %d, %d) should have failed\n", size, alignment, offset); + + if (mem) + { + ok(((DWORD_PTR)((char *)mem + offset) & (alignment ? alignment - 1 : 0)) == 0, + "_aligned_offset_malloc(%d, %d, %d) not aligned: %p\n", size, alignment, offset, mem); + if (winetest_debug > 1) + { + void *saved; + saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1)); + trace("_aligned_offset_malloc(%3d, %3d, %3d) returns %p, saved = %p, diff = %d\n", + size, alignment, offset, mem, saved, (char *)saved - (char *)mem); + } + p_aligned_free(mem); + } + else + ok(errno == EINVAL, "_aligned_offset_malloc(%d, %d, %d) errno: %d != %d\n", size, alignment, offset, errno, EINVAL); +} + +static void test_aligned_realloc(size_t size1, size_t size2, size_t alignment) +{ + void *mem, *mem1, *mem2; + + mem = p_aligned_malloc(size1, alignment); + + if ((alignment & (alignment - 1)) == 0) + ok(mem != NULL, "_aligned_malloc(%d, %d) failed\n", size1, alignment); + else + ok(mem == NULL, "_aligned_malloc(%d, %d) should have failed\n", size1, alignment); + + if (mem) + { + mem1 = malloc(size1); + if (mem1) + { + int i; + for (i = 0; i < size1; i++) + ((char *)mem)[i] = i + 1; + memcpy(mem1, mem, size1); + } + + ok(((DWORD_PTR)mem & (alignment ? alignment - 1 : 0)) == 0, + "_aligned_malloc(%d, %d) not aligned: %p\n", size1, alignment, mem); + if (winetest_debug > 1) + { + void *saved; + saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1)); + trace("_aligned_malloc(%3d, %3d) returns %p, saved = %p, diff = %d\n", + size1, alignment, mem, saved, (char *)saved - (char *)mem); + } + + mem2 = p_aligned_realloc(mem, size2, alignment); + + ok(mem2 != NULL, "_aligned_realloc(%p, %d, %d) failed\n", mem, size2, alignment); + + if (mem2) + { + ok(((DWORD_PTR)mem2 & (alignment ? alignment - 1 : 0)) == 0, + "_aligned_realloc(%p, %d, %d) not aligned: %p\n", mem, size2, alignment, mem2); + if (winetest_debug > 1) + { + void *saved; + saved = *(void **)((DWORD_PTR)((char *)mem2 - sizeof(void *)) & ~(sizeof(void *) - 1)); + trace("_aligned_realloc(%p, %3d, %3d) returns %p, saved = %p, diff = %d\n", + mem, size2, alignment, mem2, saved, (char *)saved - (char *)mem2); + } + if (mem1) + { + ok(memcmp(mem2, mem1, min(size1, size2))==0, "_aligned_realloc(%p, %d, %d) has different data\n", mem, size2, alignment); + if (memcmp(mem2, mem1, min(size1, size2)) && winetest_debug > 1) + { + int i; + for (i = 0; i < min(size1, size2); i++) + { + if (((char *)mem2)[i] != ((char *)mem1)[i]) + trace("%d: %02x != %02x\n", i, ((char *)mem2)[i] & 0xff, ((char *)mem1)[i] & 0xff); + } + } + } + } + else + ok(errno == EINVAL, "_aligned_realloc(%p, %d, %d) errno: %d != %d\n", mem, size2, alignment, errno, EINVAL); + + p_aligned_free(mem); + free(mem1); + } + else + ok(errno == EINVAL, "_aligned_malloc(%d, %d) errno: %d != %d\n", size1, alignment, errno, EINVAL); +} + +static void test_aligned_offset_realloc(size_t size1, size_t size2, size_t alignment, size_t offset) +{ + void *mem, *mem1, *mem2; + + mem = p_aligned_offset_malloc(size1, alignment, offset); + + if ((alignment & (alignment - 1)) == 0) + ok(mem != NULL, "_aligned_offset_malloc(%d, %d, %d) failed\n", size1, alignment, offset); + else + ok(mem == NULL, "_aligned_offset_malloc(%d, %d, %d) should have failed\n", size1, alignment, offset); + + if (mem) + { + mem1 = malloc(size1); + if (mem1) + { + int i; + for (i = 0; i < size1; i++) + ((char *)mem)[i] = i + 1; + memcpy(mem1, mem, size1); + } + + ok(((DWORD_PTR)((char *)mem + offset) & (alignment ? alignment - 1 : 0)) == 0, + "_aligned_offset_malloc(%d, %d, %d) not aligned: %p\n", size1, alignment, offset, mem); + if (winetest_debug > 1) + { + void *saved; + saved = *(void **)((DWORD_PTR)((char *)mem - sizeof(void *)) & ~(sizeof(void *) - 1)); + trace("_aligned_offset_malloc(%3d, %3d, %3d) returns %p, saved = %p, diff = %d\n", + size1, alignment, offset, mem, saved, (char *)saved - (char *)mem); + } + + mem2 = p_aligned_offset_realloc(mem, size2, alignment, offset); + + ok(mem2 != NULL, "_aligned_offset_realloc(%p, %d, %d, %d) failed\n", mem, size2, alignment, offset); + + if (mem2) + { + ok(((DWORD_PTR)((char *)mem + offset) & (alignment ? alignment - 1 : 0)) == 0, + "_aligned_offset_realloc(%p, %d, %d, %d) not aligned: %p\n", mem, size2, alignment, offset, mem2); + if (winetest_debug > 1) + { + void *saved; + saved = *(void **)((DWORD_PTR)((char *)mem2 - sizeof(void *)) & ~(sizeof(void *) - 1)); + trace("_aligned_offset_realloc(%p, %3d, %3d, %3d) returns %p, saved = %p, diff = %d\n", + mem, size2, alignment, offset, mem2, saved, (char *)saved - (char *)mem2); + } + if (mem1) + { + ok(memcmp(mem2, mem1, min(size1, size2))==0, "_aligned_offset_realloc(%p, %d, %d, %d) has different data\n", mem, size2, alignment, offset); + if (memcmp(mem2, mem1, min(size1, size2)) && winetest_debug > 1) + { + int i; + for (i = 0; i < min(size1, size2); i++) + { + if (((char *)mem2)[i] != ((char *)mem1)[i]) + trace("%d: %02x != %02x\n", i, ((char *)mem2)[i] & 0xff, ((char *)mem1)[i] & 0xff); + } + } + } + } + else + ok(errno == EINVAL, "_aligned_offset_realloc(%p, %d, %d, %d) errno: %d != %d\n", mem, size2, alignment, offset, errno, EINVAL); + + p_aligned_free(mem); + free(mem1); + } + else + ok(errno == EINVAL, "_aligned_offset_malloc(%d, %d) errno: %d != %d\n", size1, alignment, errno, EINVAL); +} + +static void test_aligned(void) +{ + HMODULE msvcrt = GetModuleHandle("msvcrt.dll"); + + if (msvcrt == NULL) + return; + + p_aligned_free = (void*)GetProcAddress(msvcrt, "_aligned_free"); + p_aligned_malloc = (void*)GetProcAddress(msvcrt, "_aligned_malloc"); + p_aligned_offset_malloc = (void*)GetProcAddress(msvcrt, "_aligned_offset_malloc"); + p_aligned_realloc = (void*)GetProcAddress(msvcrt, "_aligned_realloc"); + p_aligned_offset_realloc = (void*)GetProcAddress(msvcrt, "_aligned_offset_realloc"); + + if (!p_aligned_free || !p_aligned_malloc || !p_aligned_offset_malloc || !p_aligned_realloc || !p_aligned_offset_realloc) + { + skip("aligned memory tests skipped\n"); + return; + } + + test_aligned_malloc(256, 0); + test_aligned_malloc(256, 1); + test_aligned_malloc(256, 2); + test_aligned_malloc(256, 3); + test_aligned_malloc(256, 4); + test_aligned_malloc(256, 8); + test_aligned_malloc(256, 16); + test_aligned_malloc(256, 32); + test_aligned_malloc(256, 64); + test_aligned_malloc(256, 127); + test_aligned_malloc(256, 128); + + test_aligned_offset_malloc(256, 0, 0); + test_aligned_offset_malloc(256, 1, 0); + test_aligned_offset_malloc(256, 2, 0); + test_aligned_offset_malloc(256, 3, 0); + test_aligned_offset_malloc(256, 4, 0); + test_aligned_offset_malloc(256, 8, 0); + test_aligned_offset_malloc(256, 16, 0); + test_aligned_offset_malloc(256, 32, 0); + test_aligned_offset_malloc(256, 64, 0); + test_aligned_offset_malloc(256, 127, 0); + test_aligned_offset_malloc(256, 128, 0); + + test_aligned_offset_malloc(256, 0, 4); + test_aligned_offset_malloc(256, 1, 4); + test_aligned_offset_malloc(256, 2, 4); + test_aligned_offset_malloc(256, 3, 4); + test_aligned_offset_malloc(256, 4, 4); + test_aligned_offset_malloc(256, 8, 4); + test_aligned_offset_malloc(256, 16, 4); + test_aligned_offset_malloc(256, 32, 4); + test_aligned_offset_malloc(256, 64, 4); + test_aligned_offset_malloc(256, 127, 4); + test_aligned_offset_malloc(256, 128, 4); + + test_aligned_offset_malloc(256, 8, 7); + test_aligned_offset_malloc(256, 8, 9); + test_aligned_offset_malloc(256, 8, 16); + test_aligned_offset_malloc(256, 8, 17); + test_aligned_offset_malloc(256, 8, 254); + test_aligned_offset_malloc(256, 8, 255); + test_aligned_offset_malloc(256, 8, 256); + test_aligned_offset_malloc(256, 8, 512); + + test_aligned_realloc(256, 512, 0); + test_aligned_realloc(256, 128, 0); + test_aligned_realloc(256, 512, 4); + test_aligned_realloc(256, 128, 4); + test_aligned_realloc(256, 512, 8); + test_aligned_realloc(256, 128, 8); + test_aligned_realloc(256, 512, 16); + test_aligned_realloc(256, 128, 16); + test_aligned_realloc(256, 512, 32); + test_aligned_realloc(256, 128, 32); + test_aligned_realloc(256, 512, 64); + test_aligned_realloc(256, 128, 64); + + test_aligned_offset_realloc(256, 512, 0, 0); + test_aligned_offset_realloc(256, 128, 0, 0); + test_aligned_offset_realloc(256, 512, 4, 0); + test_aligned_offset_realloc(256, 128, 4, 0); + test_aligned_offset_realloc(256, 512, 8, 0); + test_aligned_offset_realloc(256, 128, 8, 0); + test_aligned_offset_realloc(256, 512, 16, 0); + test_aligned_offset_realloc(256, 128, 16, 0); + test_aligned_offset_realloc(256, 512, 32, 0); + test_aligned_offset_realloc(256, 128, 32, 0); + test_aligned_offset_realloc(256, 512, 64, 0); + test_aligned_offset_realloc(256, 128, 64, 0); + + test_aligned_offset_realloc(256, 512, 0, 4); + test_aligned_offset_realloc(256, 128, 0, 4); + test_aligned_offset_realloc(256, 512, 4, 4); + test_aligned_offset_realloc(256, 128, 4, 4); + test_aligned_offset_realloc(256, 512, 8, 4); + test_aligned_offset_realloc(256, 128, 8, 4); + test_aligned_offset_realloc(256, 512, 16, 4); + test_aligned_offset_realloc(256, 128, 16, 4); + test_aligned_offset_realloc(256, 512, 32, 4); + test_aligned_offset_realloc(256, 128, 32, 4); + test_aligned_offset_realloc(256, 512, 64, 4); + test_aligned_offset_realloc(256, 128, 64, 4); +} + START_TEST(heap) { void *mem; @@ -39,4 +352,6 @@ START_TEST(heap) mem = realloc(NULL, 0); ok(mem != NULL, "memory not (re)allocated for size 0\n"); + + test_aligned(); } diff --git a/rostests/winetests/msvcrt/msvcrt.rbuild b/rostests/winetests/msvcrt/msvcrt.rbuild index 3b20696c4f8..55da6a8b70b 100644 --- a/rostests/winetests/msvcrt/msvcrt.rbuild +++ b/rostests/winetests/msvcrt/msvcrt.rbuild @@ -1,16 +1,18 @@ - . - - kernel32 - ntdll - cpp.c - dir.c - environ.c - file.c - heap.c - printf.c - scanf.c - string.c - testlist.c - time.c + . + + kernel32 + ntdll + cpp.c + data.c + dir.c + environ.c + file.c + headers.c + heap.c + printf.c + scanf.c + string.c + testlist.c + time.c diff --git a/rostests/winetests/msvcrt/printf.c b/rostests/winetests/msvcrt/printf.c index aa4efaf7a72..7d53c3a4bee 100644 --- a/rostests/winetests/msvcrt/printf.c +++ b/rostests/winetests/msvcrt/printf.c @@ -17,9 +17,14 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +/* With Visual Studio >= 2005, swprintf() takes an extra parameter unless + * the following macro is defined. + */ +#define _CRT_NON_CONFORMING_SWPRINTFS + #include #include "wine/test.h" @@ -187,6 +192,18 @@ static void test_sprintf( void ) r = sprintf(buffer,format,(LONGLONG)100); ok(!strcmp(buffer,"+00100 ") && r==8,"#-+ 08.5I64d failed: '%s'\n", buffer); + format = "%.80I64d"; + r = sprintf(buffer,format,(LONGLONG)1); + ok(r==80,"%s format failed\n", format); + + format = "% .80I64d"; + r = sprintf(buffer,format,(LONGLONG)1); + ok(r==81,"%s format failed\n", format); + + format = "% .80d"; + r = sprintf(buffer,format,1); + ok(r==81,"%s format failed\n", format); + format = "%lld"; r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff); ok(!strcmp(buffer, "1"), "Problem with \"ll\" interpretation\n"); @@ -267,6 +284,11 @@ static void test_sprintf( void ) ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer); ok( r==1, "return count wrong\n"); + format = "%*s"; + r = sprintf(buffer,format,-5,"foo"); + ok(!strcmp(buffer,"foo "),"Negative field width ignored \"%s\"\n",buffer); + ok( r==5, "return count wrong\n"); + format = "%#-012p"; r = sprintf(buffer,format,(void *)57); ok(!strcmp(buffer,"0X00000039 "),"Pointer formatted incorrectly\n"); @@ -469,8 +491,11 @@ static void test_swprintf( void ) double pnumber=789456123; const wchar_t TwentyThreePoint15e[]= {'%','+','#','2','3','.','1','5','e',0}; const wchar_t e008[] = {'e','+','0','0','8',0}; - const char string[]={'s','t','r','i','n','g',0}; + const wchar_t string_w[] = {'s','t','r','i','n','g',0}; + const char string[] = "string"; const wchar_t S[]={'%','S',0}; + const wchar_t hs[] = {'%', 'h', 's', 0}; + swprintf(buffer,TwentyThreePoint15e,pnumber); todo_wine { @@ -480,6 +505,8 @@ static void test_swprintf( void ) ok(wcslen(buffer) == 11,"Problem with long long\n"); swprintf(buffer,S,string); ok(wcslen(buffer) == 6,"Problem with \"%%S\" interpretation\n"); + swprintf(buffer, hs, string); + ok( wcscmp(string_w,buffer) == 0, "swprintf failed with %%hs\n"); } static void test_fwprintf( void ) @@ -487,7 +514,8 @@ static void test_fwprintf( void ) const char *string="not a wide string"; todo_wine { - ok(fwprintf(fopen("nul","r+"),(wchar_t *)string) == -1,"Non-wide string should not be printed by fwprintf\n"); + ok(fwprintf(fopen("nul","r+"),(const wchar_t *)string) == -1, + "Non-wide string should not be printed by fwprintf\n"); } } @@ -524,47 +552,96 @@ 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 ); - todo_wine { - ok( 0 == strcmp(str,""), "bad return\n"); - ok( -3 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( -3 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); str = _fcvt(0.0001, -10, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,""), "bad return\n"); - ok( -3 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( -3 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); str = _fcvt(0.0001, 10, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,"1000000"), "bad return\n"); - ok( -3 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,"1000000"), "bad return '%s'\n", str); + ok( -3 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + /* Basic sign test */ str = _fcvt(-111.0001, 5, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,"11100010"), "bad return\n"); - ok( 3 == dec, "dec wrong\n"); - } - ok( 1 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); str = _fcvt(111.0001, 5, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,"11100010"), "bad return\n"); + ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str); ok( 3 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == sign, "sign wrong\n"); + /* 0.0 with different precisions */ str = _fcvt(0.0, 5, &dec, &sign ); - todo_wine { - ok( 0 == strcmp(str,"00000"), "bad return\n"); - ok( 0 == dec, "dec wrong\n"); - } - ok( 0 == sign, "dec wrong\n"); + ok( 0 == strcmp(str,"00000"), "bad return '%s'\n", str); + ok( 0 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.0, 0, &dec, &sign ); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( 0 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.0, -1, &dec, &sign ); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( 0 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + /* Numbers > 1.0 with 0 or -ve precision */ + str = _fcvt(-123.0001, 0, &dec, &sign ); + ok( 0 == strcmp(str,"123"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); + + str = _fcvt(-123.0001, -1, &dec, &sign ); + ok( 0 == strcmp(str,"12"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); + + str = _fcvt(-123.0001, -2, &dec, &sign ); + ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); + + str = _fcvt(-123.0001, -3, &dec, &sign ); + ok( 0 == strcmp(str,""), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 1 == sign, "sign wrong\n"); + + /* Numbers > 1.0, but with rounding at the point of precision */ + str = _fcvt(99.99, 1, &dec, &sign ); + ok( 0 == strcmp(str,"1000"), "bad return '%s'\n", str); + ok( 3 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + /* Numbers < 1.0 where rounding occurs at the point of precision */ + str = _fcvt(0.00636, 2, &dec, &sign ); + ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str); + ok( -1 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.00636, 3, &dec, &sign ); + ok( 0 == strcmp(str,"6"), "bad return '%s'\n", str); + ok( -2 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.09999999996, 2, &dec, &sign ); + ok( 0 == strcmp(str,"10"), "bad return '%s'\n", str); + ok( 0 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); + + str = _fcvt(0.6, 0, &dec, &sign ); + ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str); + ok( 1 == dec, "dec wrong %d\n", dec); + ok( 0 == sign, "sign wrong\n"); } START_TEST(printf) diff --git a/rostests/winetests/msvcrt/scanf.c b/rostests/winetests/msvcrt/scanf.c index 2482825e1ff..65bea469036 100644 --- a/rostests/winetests/msvcrt/scanf.c +++ b/rostests/winetests/msvcrt/scanf.c @@ -15,7 +15,7 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -52,6 +52,11 @@ static void test_sscanf( void ) ok( sscanf(buffer, "%x", &result) == 1, "sscanf failed\n" ); ok( result == 0x51, "sscanf reads %x instead of %x\n", result, 0x51 ); + result = 0; + ret = sscanf("-1", "%x", &result); + ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret); + ok(result == -1, "Read %d, expected -1\n", result); + /* check % followed by any char */ strcpy(buffer,"\"%12@"); strcpy(format,"%\"%%%d%@"); /* work around gcc format check */ @@ -93,9 +98,41 @@ static void test_sscanf( void ) ret = sscanf(buffer, "%i", &result); ok(ret == 1, "Wrong number of arguments read: %d\n", ret); ok(result == 123, "Wrong number read\n"); + result = 0; + ret = sscanf("-1", "%i", &result); + ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret); + ok(result == -1, "Read %d, expected -1\n", result); ret = sscanf(buffer, "%d", &result); ok(ret == 1, "Wrong number of arguments read: %d\n", ret); ok(result == 123, "Wrong number read\n"); + result = 0; + ret = sscanf("-1", "%d", &result); + ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret); + ok(result == -1, "Read %d, expected -1\n", result); + + /* Check %i for octal and hexadecimal input */ + result = 0; + strcpy(buffer,"017"); + ret = sscanf(buffer, "%i", &result); + ok(ret == 1, "Wrong number of arguments read: %d\n", ret); + ok(result == 15, "Wrong number read\n"); + result = 0; + strcpy(buffer,"0x17"); + ret = sscanf(buffer, "%i", &result); + ok(ret == 1, "Wrong number of arguments read: %d\n", ret); + ok(result == 23, "Wrong number read\n"); + + /* %o */ + result = 0; + ret = sscanf("-1", "%o", &result); + ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret); + ok(result == -1, "Read %d, expected -1\n", result); + + /* %u */ + result = 0; + ret = sscanf("-1", "%u", &result); + ok(ret == 1, "Wrong number of arguments read: %d (expected 1)\n", ret); + ok(result == -1, "Read %d, expected -1\n", result); /* Check %c */ strcpy(buffer,"a"); @@ -125,6 +162,12 @@ static void test_sscanf( void ) ok(strcmp(buffer1,"def")==0, "Second %%s read incorrectly: %s\n", buffer1); ok(number_so_far==6, "%%n yielded wrong result: %d\n", number_so_far); ok(ret == 2, "%%n shouldn't count as a conversion: %d\n", ret); + + /* Check where %n matches to EOF in buffer */ + strcpy(buffer, "3:45"); + ret = sscanf(buffer, "%d:%d%n", &hour, &min, &number_so_far); + ok(ret == 2, "Wrong number of arguments read: %d\n", ret); + ok(number_so_far == 4, "%%n yielded wrong result: %d\n", number_so_far); } START_TEST(scanf) diff --git a/rostests/winetests/msvcrt/string.c b/rostests/winetests/msvcrt/string.c index 0e1a7fa7f58..4febeea2d27 100644 --- a/rostests/winetests/msvcrt/string.c +++ b/rostests/winetests/msvcrt/string.c @@ -15,7 +15,7 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "wine/test.h" @@ -23,7 +23,28 @@ #include #include #include +#include #include +#include + +size_t _mbstrlen(const char*); + +static char *buf_to_string(const unsigned char *bin, int len, int nr) +{ + static char buf[2][1024]; + char *w = buf[nr]; + int i; + + for (i = 0; i < len; i++) + { + sprintf(w, "%02x ", (unsigned char)bin[i]); + w += strlen(w); + } + return buf[nr]; +} + +#define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); } +#define expect_bin(buf, value, len) { ok(memcmp((buf), value, len) == 0, "Binary buffer mismatch - expected %s, got %s\n", buf_to_string((unsigned char *)value, len, 1), buf_to_string((buf), len, 0)); } static void* (*pmemcpy)(void *, const void *, size_t n); static int* (*pmemcmp)(void *, const void *, size_t n); @@ -31,6 +52,8 @@ static int* (*pmemcmp)(void *, const void *, size_t n); #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y) #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y) +HMODULE hMsvcrt; + static void test_swab( void ) { char original[] = "BADCFEHGJILKNMPORQTSVUXWZY@#"; char expected1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ@#"; @@ -75,13 +98,260 @@ static void test_swab( void ) { ok(memcmp(to,expected3,testsize) == 0, "Testing small size %d returned '%*.*s'\n", testsize, testsize, testsize, to); } -void test_ismbblead(void) +#if 0 /* use this to generate more tests */ + +static void test_codepage(int cp) { - unsigned int s = '\354'; + int i; + int prev; + int count = 1; + + ok(_setmbcp(cp) == 0, "Couldn't set mbcp\n"); + + prev = _mbctype[0]; + printf("static int result_cp_%d_mbctype[] = { ", cp); + for (i = 1; i < 257; i++) + { + if (_mbctype[i] != prev) + { + printf("0x%x,%d, ", prev, count); + prev = _mbctype[i]; + count = 1; + } + else + count++; + } + printf("0x%x,%d };\n", prev, count); +} + +#define test_codepage_todo(cp, todo) test_codepage(cp) + +#else + +/* RLE-encoded mbctype tables for given codepages */ +static int result_cp_932_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4, + 0x0,1, 0x8,1, 0xc,31, 0x8,1, 0xa,5, 0x9,58, 0xc,29, 0,3 }; +static int result_cp_936_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,6, + 0xc,126, 0,1 }; +static int result_cp_949_mbctype[] = { 0x0,66, 0x18,26, 0x8,6, 0x28,26, 0x8,6, 0xc,126, + 0,1 }; +static int result_cp_950_mbctype[] = { 0x0,65, 0x8,1, 0x18,26, 0x8,6, 0x28,26, 0x8,4, + 0x0,2, 0x4,32, 0xc,94, 0,1 }; + +static int todo_none[] = { -2 }; +static int todo_cp_932[] = { 254, -2 }; +#if 0 +void test_cp_table(int cp, int *result, int *todo) +{ + int i; + int count = 0; + int curr = 0; + _setmbcp(cp); + for (i = 0; i < 256; i++) + { + if (count == 0) + { + curr = result[0]; + count = result[1]; + result += 2; + } + if (i == *todo + 1) + { + todo_wine ok(_mbctype[i] == curr, "CP%d: Mismatch in ctype for character %d - %d instead of %d\n", cp, i-1, _mbctype[i], curr); + todo++; + } + else + ok(_mbctype[i] == curr, "CP%d: Mismatch in ctype for character %d - %d instead of %d\n", cp, i-1, _mbctype[i], curr); + count--; + } +} + +#define test_codepage(num) test_cp_table(num, result_cp_##num##_mbctype, todo_none); +#define test_codepage_todo(num, todo) test_cp_table(num, result_cp_##num##_mbctype, todo); +#endif +#endif + +static void test_mbcp(void) +{ + int mb_orig_max = __mb_cur_max; + int curr_mbcp = _getmbcp(); + unsigned char *mbstring = (unsigned char *)"\xb0\xb1\xb2 \xb3\xb4 \xb5"; /* incorrect string */ + unsigned char *mbstring2 = (unsigned char *)"\xb0\xb1\xb2\xb3Q\xb4\xb5"; /* correct string */ + unsigned char *mbsonlylead = (unsigned char *)"\xb0\0\xb1\xb2 \xb3"; + unsigned char buf[16]; + int step; + + /* _mbtype tests */ + + /* An SBCS codepage test. The ctype of characters on e.g. CP1252 or CP1250 differs slightly + * between versions of Windows. Also Windows 9x seems to ignore the codepage and always uses + * CP1252 (or the ACP?) so we test only a few ASCII characters */ + _setmbcp(1252); + expect_eq(_mbctype[10], 0, char, "%x"); + expect_eq(_mbctype[50], 0, char, "%x"); + expect_eq(_mbctype[66], _SBUP, char, "%x"); + expect_eq(_mbctype[100], _SBLOW, char, "%x"); + expect_eq(_mbctype[128], 0, char, "%x"); + _setmbcp(1250); + expect_eq(_mbctype[10], 0, char, "%x"); + expect_eq(_mbctype[50], 0, char, "%x"); + expect_eq(_mbctype[66], _SBUP, char, "%x"); + expect_eq(_mbctype[100], _SBLOW, char, "%x"); + expect_eq(_mbctype[128], 0, char, "%x"); + + /* double byte code pages */ + //test_codepage_todo(932, todo_cp_932); + //test_codepage(936); + //test_codepage(949); + //test_codepage(950); _setmbcp(936); - todo_wine ok(_ismbblead(s), "got result %d\n", _ismbblead(s)); - _setmbcp(1252); + ok(__mb_cur_max == mb_orig_max, "__mb_cur_max shouldn't be updated (is %d != %d)\n", __mb_cur_max, mb_orig_max); + ok(_ismbblead('\354'), "\354 should be a lead byte\n"); + ok(_ismbblead(' ') == FALSE, "' ' should not be a lead byte\n"); + ok(_ismbblead(0x1234b0), "0x1234b0 should not be a lead byte\n"); + ok(_ismbblead(0x123420) == FALSE, "0x123420 should not be a lead byte\n"); + ok(_ismbbtrail('\xb0'), "\xa0 should be a trail byte\n"); + ok(_ismbbtrail(' ') == FALSE, "' ' should not be a trail byte\n"); + + /* _ismbslead */ + expect_eq(_ismbslead(mbstring, &mbstring[0]), -1, int, "%d"); + expect_eq(_ismbslead(mbstring, &mbstring[1]), FALSE, int, "%d"); + expect_eq(_ismbslead(mbstring, &mbstring[2]), -1, int, "%d"); + expect_eq(_ismbslead(mbstring, &mbstring[3]), FALSE, int, "%d"); + expect_eq(_ismbslead(mbstring, &mbstring[4]), -1, int, "%d"); + expect_eq(_ismbslead(mbstring, &mbstring[5]), FALSE, int, "%d"); + expect_eq(_ismbslead(mbstring, &mbstring[6]), FALSE, int, "%d"); + expect_eq(_ismbslead(mbstring, &mbstring[7]), -1, int, "%d"); + expect_eq(_ismbslead(mbstring, &mbstring[8]), FALSE, int, "%d"); + + expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[0]), -1, int, "%d"); + expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[1]), FALSE, int, "%d"); + expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d"); + expect_eq(_ismbslead(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d"); + + /* _ismbstrail */ + expect_eq(_ismbstrail(mbstring, &mbstring[0]), FALSE, int, "%d"); + expect_eq(_ismbstrail(mbstring, &mbstring[1]), -1, int, "%d"); + expect_eq(_ismbstrail(mbstring, &mbstring[2]), FALSE, int, "%d"); + expect_eq(_ismbstrail(mbstring, &mbstring[3]), -1, int, "%d"); + expect_eq(_ismbstrail(mbstring, &mbstring[4]), FALSE, int, "%d"); + expect_eq(_ismbstrail(mbstring, &mbstring[5]), -1, int, "%d"); + expect_eq(_ismbstrail(mbstring, &mbstring[6]), FALSE, int, "%d"); + expect_eq(_ismbstrail(mbstring, &mbstring[7]), FALSE, int, "%d"); + expect_eq(_ismbstrail(mbstring, &mbstring[8]), -1, int, "%d"); + + expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[0]), FALSE, int, "%d"); + expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[1]), -1, int, "%d"); + expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[2]), FALSE, int, "%d"); + expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[3]), FALSE, int, "%d"); + expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[4]), FALSE, int, "%d"); + expect_eq(_ismbstrail(mbsonlylead, &mbsonlylead[5]), FALSE, int, "%d"); + + /* _mbsbtype */ + expect_eq(_mbsbtype(mbstring, 0), _MBC_LEAD, int, "%d"); + expect_eq(_mbsbtype(mbstring, 1), _MBC_TRAIL, int, "%d"); + expect_eq(_mbsbtype(mbstring, 2), _MBC_LEAD, int, "%d"); + expect_eq(_mbsbtype(mbstring, 3), _MBC_ILLEGAL, int, "%d"); + expect_eq(_mbsbtype(mbstring, 4), _MBC_LEAD, int, "%d"); + expect_eq(_mbsbtype(mbstring, 5), _MBC_TRAIL, int, "%d"); + expect_eq(_mbsbtype(mbstring, 6), _MBC_SINGLE, int, "%d"); + expect_eq(_mbsbtype(mbstring, 7), _MBC_LEAD, int, "%d"); + expect_eq(_mbsbtype(mbstring, 8), _MBC_ILLEGAL, int, "%d"); + + expect_eq(_mbsbtype(mbsonlylead, 0), _MBC_LEAD, int, "%d"); + expect_eq(_mbsbtype(mbsonlylead, 1), _MBC_ILLEGAL, int, "%d"); + expect_eq(_mbsbtype(mbsonlylead, 2), _MBC_ILLEGAL, int, "%d"); + expect_eq(_mbsbtype(mbsonlylead, 3), _MBC_ILLEGAL, int, "%d"); + expect_eq(_mbsbtype(mbsonlylead, 4), _MBC_ILLEGAL, int, "%d"); + expect_eq(_mbsbtype(mbsonlylead, 5), _MBC_ILLEGAL, int, "%d"); + + /* _mbsnextc */ + expect_eq(_mbsnextc(mbstring), 0xb0b1, int, "%x"); + expect_eq(_mbsnextc(&mbstring[2]), 0xb220, int, "%x"); /* lead + invalid tail */ + expect_eq(_mbsnextc(&mbstring[3]), 0x20, int, "%x"); /* single char */ + + /* _mbclen/_mbslen */ + expect_eq(_mbclen(mbstring), 2, int, "%d"); + expect_eq(_mbclen(&mbstring[2]), 2, int, "%d"); + expect_eq(_mbclen(&mbstring[3]), 1, int, "%d"); + expect_eq(_mbslen(mbstring2), 4, int, "%d"); + expect_eq(_mbslen(mbsonlylead), 0, int, "%d"); /* lead + NUL not counted as character */ + expect_eq(_mbslen(mbstring), 4, int, "%d"); /* lead + invalid trail counted */ + + /* _mbccpy/_mbsncpy */ + memset(buf, 0xff, sizeof(buf)); + _mbccpy(buf, mbstring); + expect_bin(buf, "\xb0\xb1\xff", 3); + + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 1); + expect_bin(buf, "\xb0\xb1\xff", 3); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 2); + expect_bin(buf, "\xb0\xb1\xb2 \xff", 5); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 3); + expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4\xff", 7); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 4); + expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \xff", 8); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbstring, 5); + expect_bin(buf, "\xb0\xb1\xb2 \xb3\xb4 \0\0\xff", 10); + memset(buf, 0xff, sizeof(buf)); + _mbsncpy(buf, mbsonlylead, 6); + expect_bin(buf, "\0\0\0\0\0\0\0\xff", 8); + + memset(buf, 0xff, sizeof(buf)); + _mbsnbcpy(buf, mbstring2, 2); + expect_bin(buf, "\xb0\xb1\xff", 3); + _mbsnbcpy(buf, mbstring2, 3); + expect_bin(buf, "\xb0\xb1\0\xff", 4); + _mbsnbcpy(buf, mbstring2, 4); + expect_bin(buf, "\xb0\xb1\xb2\xb3\xff", 5); + memset(buf, 0xff, sizeof(buf)); + _mbsnbcpy(buf, mbsonlylead, 5); + expect_bin(buf, "\0\0\0\0\0\xff", 6); + + /* _mbsinc/mbsdec */ + step = _mbsinc(mbstring) - mbstring; + ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step); + step = _mbsinc(&mbstring[2]) - &mbstring[2]; /* lead + invalid tail */ + ok(step == 2, "_mbsinc adds %d (exp. 2)\n", step); + + step = _mbsninc(mbsonlylead, 1) - mbsonlylead; + ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step); + step = _mbsninc(mbsonlylead, 2) - mbsonlylead; /* lead + NUL byte + lead + char */ + ok(step == 0, "_mbsninc adds %d (exp. 0)\n", step); + step = _mbsninc(mbstring2, 0) - mbstring2; + ok(step == 0, "_mbsninc adds %d (exp. 2)\n", step); + step = _mbsninc(mbstring2, 1) - mbstring2; + ok(step == 2, "_mbsninc adds %d (exp. 2)\n", step); + step = _mbsninc(mbstring2, 2) - mbstring2; + ok(step == 4, "_mbsninc adds %d (exp. 4)\n", step); + step = _mbsninc(mbstring2, 3) - mbstring2; + ok(step == 5, "_mbsninc adds %d (exp. 5)\n", step); + step = _mbsninc(mbstring2, 4) - mbstring2; + ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step); + step = _mbsninc(mbstring2, 5) - mbstring2; + ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step); + step = _mbsninc(mbstring2, 17) - mbstring2; + ok(step == 7, "_mbsninc adds %d (exp. 7)\n", step); + + /* functions that depend on locale codepage, not mbcp. + * we hope the current locale to be SBCS because setlocale(LC_ALL, ".1252") seems not to work yet + * (as of Wine 0.9.43) + */ + if (__mb_cur_max == 1) + { + expect_eq(mblen((char *)mbstring, 3), 1, int, "%x"); + expect_eq(_mbstrlen((char *)mbstring2), 7, int, "%d"); + } + else + skip("Current locale has double-byte charset - could leave to false positives\n"); + + _setmbcp(curr_mbcp); } static void test_mbsspn( void) @@ -99,30 +369,61 @@ static void test_mbsspn( void) ok( ret==0, "_mbsspn returns %d should be 0\n", ret); } +static void test_mbsspnp( void) +{ + unsigned char str1[]="cabernet"; + unsigned char str2[]="shiraz"; + unsigned char set[]="abc"; + unsigned char empty[]=""; + unsigned char full[]="abcenrt"; + unsigned char* ret; + ret=_mbsspnp( str1, set); + ok( ret[0]=='e', "_mbsspnp returns %c should be e\n", ret[0]); + ret=_mbsspnp( str2, set); + ok( ret[0]=='s', "_mbsspnp returns %c should be s\n", ret[0]); + ret=_mbsspnp( str1, empty); + ok( ret[0]=='c', "_mbsspnp returns %c should be c\n", ret[0]); + ret=_mbsspnp( str1, full); + ok( ret==NULL, "_mbsspnp returns %p should be NULL\n", ret); +} + +static void test_strdup(void) +{ + char *str; + str = _strdup( 0 ); + ok( str == 0, "strdup returns %s should be 0\n", str); + free( str ); +} + START_TEST(string) { - void *mem; + char mem[100]; static const char xilstring[]="c:/xilinx"; - int nLen=strlen(xilstring); - HMODULE hMsvcrt = LoadLibraryA("msvcrt.dll"); - ok(hMsvcrt != 0, "LoadLibraryA failed\n"); + int nLen; + + hMsvcrt = GetModuleHandleA("msvcrt.dll"); + if (!hMsvcrt) + hMsvcrt = GetModuleHandleA("msvcrtd.dll"); + ok(hMsvcrt != 0, "GetModuleHandleA failed\n"); SET(pmemcpy,"memcpy"); SET(pmemcmp,"memcmp"); /* MSVCRT memcpy behaves like memmove for overlapping moves, MFC42 CString::Insert seems to rely on that behaviour */ - mem = malloc(100); - ok(mem != NULL, "memory not allocated for size 0\n"); - strcpy((char*)mem,xilstring); - pmemcpy((char*)mem+5, mem,nLen+1); - ok(pmemcmp((char*)mem+5,xilstring, nLen) == 0, - "Got result %s\n",(char*)mem+5); + strcpy(mem,xilstring); + nLen=strlen(xilstring); + pmemcpy(mem+5, mem,nLen+1); + ok(pmemcmp(mem+5,xilstring, nLen) == 0, + "Got result %s\n",mem+5); /* Test _swab function */ test_swab(); /* Test ismbblead*/ - test_ismbblead(); + test_mbcp(); /* test _mbsspn */ test_mbsspn(); + test_mbsspnp(); + /* test _strdup */ + test_strdup(); } diff --git a/rostests/winetests/msvcrt/testlist.c b/rostests/winetests/msvcrt/testlist.c index 16d1e45f4f6..db41945d89d 100644 --- a/rostests/winetests/msvcrt/testlist.c +++ b/rostests/winetests/msvcrt/testlist.c @@ -7,6 +7,7 @@ #include "wine/test.h" extern void func_cpp(void); +extern void func_data(void); extern void func_dir(void); extern void func_environ(void); extern void func_file(void); @@ -20,10 +21,11 @@ extern void func_time(void); const struct test winetest_testlist[] = { { "cpp", func_cpp }, + { "data", func_data }, { "dir", func_dir }, { "environ", func_environ }, { "file", func_file }, -// { "headers", func_headers }, + { "headers", func_headers }, { "heap", func_heap }, { "printf", func_printf }, { "scanf", func_scanf }, diff --git a/rostests/winetests/msvcrt/time.c b/rostests/winetests/msvcrt/time.c index 1b4ad41beee..30f49fe1036 100644 --- a/rostests/winetests/msvcrt/time.c +++ b/rostests/winetests/msvcrt/time.c @@ -15,7 +15,7 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "wine/test.h" @@ -44,10 +44,10 @@ static void test_gmtime(void) (gmt_tm->tm_mday == 1) && (gmt_tm->tm_wday == 4) && (gmt_tm->tm_hour == 0) && (gmt_tm->tm_min == 0) && (gmt_tm->tm_sec == 0) && (gmt_tm->tm_isdst == 0)), "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n", - gmt_tm->tm_year, gmt_tm->tm_mon, gmt_tm->tm_yday, gmt_tm->tm_mday, gmt_tm->tm_wday, - gmt_tm->tm_hour, gmt_tm->tm_min, gmt_tm->tm_sec, gmt_tm->tm_isdst); - + gmt_tm->tm_year, gmt_tm->tm_mon, gmt_tm->tm_yday, gmt_tm->tm_mday, gmt_tm->tm_wday, + gmt_tm->tm_hour, gmt_tm->tm_min, gmt_tm->tm_sec, gmt_tm->tm_isdst); } + static void test_mktime(void) { TIME_ZONE_INFORMATION tzinfo; @@ -59,9 +59,7 @@ static void test_mktime(void) ok (res != TIME_ZONE_ID_INVALID, "GetTimeZoneInformation failed\n"); /* Bias may be positive or negative, to use offset of one day */ - secs= SECSPERDAY - (tzinfo.Bias + - ( res == TIME_ZONE_ID_STANDARD ? tzinfo.StandardBias : - ( res == TIME_ZONE_ID_DAYLIGHT ? tzinfo.DaylightBias : 0 ))) * SECSPERMIN; + secs= SECSPERDAY - tzinfo.Bias * SECSPERMIN; my_tm.tm_mday = 1 + secs/SECSPERDAY; secs = secs % SECSPERDAY; my_tm.tm_hour = secs / SECSPERHOUR; @@ -77,17 +75,19 @@ static void test_mktime(void) sav_tm = my_tm; local_time = mktime(&my_tm); - ok(((DWORD)local_time == SECSPERDAY), "mktime returned 0x%08lx\n",(DWORD)local_time); + ok(((DWORD)local_time == SECSPERDAY), "mktime returned %u, expected %u\n", + (DWORD)local_time, SECSPERDAY); /* now test some unnormalized struct tm's */ my_tm = sav_tm; my_tm.tm_sec += 60; my_tm.tm_min -= 1; local_time = mktime(&my_tm); - ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time); + ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned %u, expected %u\n", + (DWORD)local_time, SECSPERDAY); ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon && my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour && - my_tm.tm_sec == sav_tm.tm_sec - , "mktime returned %3d-%02d-%02d %02d:%02d expected %3d-%02d-%02d %02d:%02d.\n", + my_tm.tm_sec == sav_tm.tm_sec, + "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n", my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday, my_tm.tm_hour,my_tm.tm_sec, sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday, @@ -96,11 +96,12 @@ static void test_mktime(void) my_tm.tm_min -= 60; my_tm.tm_hour += 1; local_time = mktime(&my_tm); - ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time); + ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned %u, expected %u\n", + (DWORD)local_time, SECSPERDAY); ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon && my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour && - my_tm.tm_sec == sav_tm.tm_sec - , "mktime returned %3d-%02d-%02d %02d:%02d expected %3d-%02d-%02d %02d:%02d.\n", + my_tm.tm_sec == sav_tm.tm_sec, + "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n", my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday, my_tm.tm_hour,my_tm.tm_sec, sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday, @@ -109,11 +110,12 @@ static void test_mktime(void) my_tm.tm_mon -= 12; my_tm.tm_year += 1; local_time = mktime(&my_tm); - ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time); + ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned %u, expected %u\n", + (DWORD)local_time, SECSPERDAY); ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon && my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour && - my_tm.tm_sec == sav_tm.tm_sec - , "mktime returned %3d-%02d-%02d %02d:%02d expected %3d-%02d-%02d %02d:%02d.\n", + my_tm.tm_sec == sav_tm.tm_sec, + "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n", my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday, my_tm.tm_hour,my_tm.tm_sec, sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday, @@ -122,11 +124,12 @@ static void test_mktime(void) my_tm.tm_mon += 12; my_tm.tm_year -= 1; local_time = mktime(&my_tm); - ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned 0x%08lx\n",(DWORD)local_time); + ok(((DWORD)local_time == SECSPERDAY), "Unnormalized mktime returned %u, expected %u\n", + (DWORD)local_time, SECSPERDAY); ok( my_tm.tm_year == sav_tm.tm_year && my_tm.tm_mon == sav_tm.tm_mon && my_tm.tm_mday == sav_tm.tm_mday && my_tm.tm_hour == sav_tm.tm_hour && - my_tm.tm_sec == sav_tm.tm_sec - , "mktime returned %3d-%02d-%02d %02d:%02d expected %3d-%02d-%02d %02d:%02d.\n", + my_tm.tm_sec == sav_tm.tm_sec, + "mktime returned %2d-%02d-%02d %02d:%02d expected %2d-%02d-%02d %02d:%02d\n", my_tm.tm_year,my_tm.tm_mon,my_tm.tm_mday, my_tm.tm_hour,my_tm.tm_sec, sav_tm.tm_year,sav_tm.tm_mon,sav_tm.tm_mday, @@ -135,7 +138,7 @@ static void test_mktime(void) my_tm = sav_tm; my_tm.tm_year -= 1; local_time = mktime(&my_tm); - ok((local_time == -1), "(bad time) mktime returned 0x%08lx\n",(DWORD)local_time); + ok((local_time == -1), "(bad time) mktime returned %d, expected -1\n", (int)local_time); my_tm = sav_tm; /* TEST that we are independent from the TZ variable */ @@ -143,16 +146,15 @@ static void test_mktime(void) _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):"")); putenv("TZ=GMT"); nulltime = mktime(&my_tm); - ok(((DWORD)nulltime == SECSPERDAY),"mktime returned 0x%08lx\n",(DWORD)nulltime); + ok(((DWORD)nulltime == SECSPERDAY),"mktime returned 0x%08x\n",(DWORD)nulltime); putenv(TZ_env); } + static void test_localtime(void) { TIME_ZONE_INFORMATION tzinfo; DWORD res = GetTimeZoneInformation(&tzinfo); - time_t gmt = (time_t)(SECSPERDAY + (tzinfo.Bias + - ( res == TIME_ZONE_ID_STANDARD ? tzinfo.StandardBias : - ( res == TIME_ZONE_ID_DAYLIGHT ? tzinfo.DaylightBias : 0 ))) * SECSPERMIN); + time_t gmt = (time_t)(SECSPERDAY + tzinfo.Bias * SECSPERMIN); char TZ_env[256]; struct tm* lt; @@ -161,24 +163,35 @@ static void test_localtime(void) lt = localtime(&gmt); ok(((lt->tm_year == 70) && (lt->tm_mon == 0) && (lt->tm_yday == 1) && (lt->tm_mday == 2) && (lt->tm_wday == 5) && (lt->tm_hour == 0) && - (lt->tm_min == 0) && (lt->tm_sec == 0) && (lt->tm_isdst == - (res == TIME_ZONE_ID_DAYLIGHT))), - "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n", - lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour, - lt->tm_min, lt->tm_sec, lt->tm_isdst); + (lt->tm_min == 0) && (lt->tm_sec == 0) && (lt->tm_isdst == 0)), + "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n", + lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour, + lt->tm_min, lt->tm_sec, lt->tm_isdst); _snprintf(TZ_env,255,"TZ=%s",(getenv("TZ")?getenv("TZ"):"")); putenv("TZ=GMT"); lt = localtime(&gmt); ok(((lt->tm_year == 70) && (lt->tm_mon == 0) && (lt->tm_yday == 1) && (lt->tm_mday == 2) && (lt->tm_wday == 5) && (lt->tm_hour == 0) && - (lt->tm_min == 0) && (lt->tm_sec == 0) && (lt->tm_isdst == - (res == TIME_ZONE_ID_DAYLIGHT))), - "Wrong date:Year %4d mon %2d yday %3d mday %2d wday %1d hour%2d min %2d sec %2d dst %2d\n", - lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour, - lt->tm_min, lt->tm_sec, lt->tm_isdst); + (lt->tm_min == 0) && (lt->tm_sec == 0) && (lt->tm_isdst == 0)), + "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n", + lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour, + lt->tm_min, lt->tm_sec, lt->tm_isdst); putenv(TZ_env); + + /* June 22 */ + gmt += 201 * SECSPERDAY; + lt = localtime(&gmt); + gmt += (lt->tm_isdst ? tzinfo.DaylightBias : tzinfo.StandardBias) * SECSPERMIN; + lt = localtime(&gmt); + ok(((lt->tm_year == 70) && (lt->tm_mon == 6) && (lt->tm_yday == 202) && + (lt->tm_mday == 22) && (lt->tm_wday == 3) && (lt->tm_hour == 0) && + (lt->tm_min == 0) && (lt->tm_sec == 0)), + "Wrong date:Year %d mon %d yday %d mday %d wday %d hour %d min %d sec %d dst %d\n", + lt->tm_year, lt->tm_mon, lt->tm_yday, lt->tm_mday, lt->tm_wday, lt->tm_hour, + lt->tm_min, lt->tm_sec, lt->tm_isdst); } + static void test_strdate(void) { char date[16], * result; @@ -191,6 +204,7 @@ static void test_strdate(void) count = sscanf(date, "%02d/%02d/%02d", &month, &day, &year); ok(count == 3, "Wrong format: count = %d, should be 3\n", count); } + static void test_strtime(void) { char time[16], * result; @@ -203,6 +217,7 @@ static void test_strtime(void) count = sscanf(time, "%02d:%02d:%02d", &hour, &minute, &second); ok(count == 3, "Wrong format: count = %d, should be 3\n", count); } + static void test_wstrdate(void) { wchar_t date[16], * result; @@ -216,6 +231,7 @@ static void test_wstrdate(void) count = swscanf(date, format, &month, &day, &year); ok(count == 3, "Wrong format: count = %d, should be 3\n", count); } + static void test_wstrtime(void) { wchar_t time[16], * result;