Piotr Caban : msvcp120/tests: Added _Pad class tests.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Feb 24 11:01:42 CST 2016
Module: wine
Branch: master
Commit: 00210255acfe13df1c5d51f5a4dc15b962d57877
URL: http://source.winehq.org/git/wine.git/?a=commit;h=00210255acfe13df1c5d51f5a4dc15b962d57877
Author: Piotr Caban <piotr at codeweavers.com>
Date: Tue Feb 23 13:13:28 2016 +0100
msvcp120/tests: Added _Pad class tests.
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/msvcp120/tests/msvcp120.c | 205 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 204 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcp120/tests/msvcp120.c b/dlls/msvcp120/tests/msvcp120.c
index 682b4d1..c310b89 100644
--- a/dlls/msvcp120/tests/msvcp120.c
+++ b/dlls/msvcp120/tests/msvcp120.c
@@ -24,6 +24,54 @@
#include "wine/test.h"
#include "winbase.h"
+#undef __thiscall
+#ifdef __i386__
+#define __thiscall __stdcall
+#else
+#define __thiscall __cdecl
+#endif
+
+/* Emulate a __thiscall */
+#ifdef __i386__
+
+#include "pshpack1.h"
+struct thiscall_thunk
+{
+ BYTE pop_eax; /* popl %eax (ret addr) */
+ BYTE pop_edx; /* popl %edx (func) */
+ BYTE pop_ecx; /* popl %ecx (this) */
+ BYTE push_eax; /* pushl %eax */
+ WORD jmp_edx; /* jmp *%edx */
+};
+#include "poppack.h"
+
+static void * (WINAPI *call_thiscall_func1)( void *func, void *this );
+static void * (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
+
+static void init_thiscall_thunk(void)
+{
+ struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk),
+ MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+ thunk->pop_eax = 0x58; /* popl %eax */
+ thunk->pop_edx = 0x5a; /* popl %edx */
+ thunk->pop_ecx = 0x59; /* popl %ecx */
+ thunk->push_eax = 0x50; /* pushl %eax */
+ thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
+ call_thiscall_func1 = (void *)thunk;
+ call_thiscall_func2 = (void *)thunk;
+}
+
+#define call_func1(func,_this) call_thiscall_func1(func,_this)
+#define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
+
+#else
+
+#define init_thiscall_thunk()
+#define call_func1(func,_this) func(_this)
+#define call_func2(func,_this,a) func(_this,a)
+
+#endif /* __i386__ */
+
static inline float __port_infinity(void)
{
static const unsigned __inf_bytes = 0x7f800000;
@@ -170,7 +218,30 @@ static _Thrd_t __cdecl i386_Thrd_current(void)
#endif
/* mtx */
-typedef void *_Mtx_t;
+typedef struct cs_queue
+{
+ struct cs_queue *next;
+ BOOL free;
+ int unknown;
+} cs_queue;
+
+typedef struct
+{
+ ULONG_PTR unk_thread_id;
+ cs_queue unk_active;
+ void *unknown[2];
+ cs_queue *head;
+ void *tail;
+} critical_section;
+
+typedef struct
+{
+ DWORD flags;
+ critical_section cs;
+ DWORD thread_id;
+ DWORD count;
+} *_Mtx_t;
+
static int (__cdecl *p__Mtx_init)(_Mtx_t*, int);
static void (__cdecl *p__Mtx_destroy)(_Mtx_t*);
static int (__cdecl *p__Mtx_lock)(_Mtx_t*);
@@ -186,6 +257,23 @@ static int (__cdecl *p__Cnd_timedwait)(_Cnd_t*, _Mtx_t*, const xtime*);
static int (__cdecl *p__Cnd_broadcast)(_Cnd_t*);
static int (__cdecl *p__Cnd_signal)(_Cnd_t*);
+/* _Pad */
+typedef void (*vtable_ptr)(void);
+
+typedef struct
+{
+ const vtable_ptr *vtable;
+ _Cnd_t cnd;
+ _Mtx_t mtx;
+ MSVCP_bool launched;
+} _Pad;
+
+static _Pad* (__thiscall *p__Pad_ctor)(_Pad*);
+static _Pad* (__thiscall *p__Pad_copy_ctor)(_Pad*, const _Pad*);
+static void (__thiscall *p__Pad_dtor)(_Pad*);
+static _Pad* (__thiscall *p__Pad_op_assign)(_Pad*, const _Pad*);
+static void (__thiscall *p__Pad__Launch)(_Pad*, _Thrd_t*);
+static void (__thiscall *p__Pad__Release)(_Pad*);
static HMODULE msvcp;
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
@@ -282,6 +370,18 @@ static BOOL init(void)
"?_Unlink at sys@tr2 at std@@YAHPEBD at Z");
SET(p__Thrd_current,
"_Thrd_current");
+ SET(p__Pad_ctor,
+ "??0_Pad at std@@QEAA at XZ");
+ SET(p__Pad_copy_ctor,
+ "??0_Pad at std@@QEAA at AEBV01@@Z");
+ SET(p__Pad_dtor,
+ "??1_Pad at std@@QEAA at XZ");
+ SET(p__Pad_op_assign,
+ "??4_Pad at std@@QEAAAEAV01 at AEBV01@@Z");
+ SET(p__Pad__Launch,
+ "?_Launch at _Pad@std@@QEAAXPEAU_Thrd_imp_t@@@Z");
+ SET(p__Pad__Release,
+ "?_Release at _Pad@std@@QEAAXXZ");
} else {
SET(p_tr2_sys__File_size,
"?_File_size at sys@tr2 at std@@YA_KPBD at Z");
@@ -347,9 +447,33 @@ static BOOL init(void)
SET(p_i386_Thrd_current,
"_Thrd_current");
p__Thrd_current = i386_Thrd_current;
+ SET(p__Pad_ctor,
+ "??0_Pad at std@@QAE at XZ");
+ SET(p__Pad_copy_ctor,
+ "??0_Pad at std@@QAE at ABV01@@Z");
+ SET(p__Pad_dtor,
+ "??1_Pad at std@@QAE at XZ");
+ SET(p__Pad_op_assign,
+ "??4_Pad at std@@QAEAAV01 at ABV01@@Z");
+ SET(p__Pad__Launch,
+ "?_Launch at _Pad@std@@QAEXPAU_Thrd_imp_t@@@Z");
+ SET(p__Pad__Release,
+ "?_Release at _Pad@std@@QAEXXZ");
#else
SET(p__Thrd_current,
"_Thrd_current");
+ SET(p__Pad_ctor,
+ "??0_Pad at std@@QAA at XZ");
+ SET(p__Pad_copy_ctor,
+ "??0_Pad at std@@QAA at ABV01@@Z");
+ SET(p__Pad_dtor,
+ "??1_Pad at std@@QAA at XZ");
+ SET(p__Pad_op_assign,
+ "??4_Pad at std@@QAAAAV01 at ABV01@@Z");
+ SET(p__Pad__Launch,
+ "?_Launch at _Pad@std@@QAAXPAU_Thrd_imp_t@@@Z");
+ SET(p__Pad__Release,
+ "?_Release at _Pad@std@@QAAXXZ");
#endif
}
SET(p__Thrd_equal,
@@ -389,6 +513,8 @@ static BOOL init(void)
p_setlocale = (void*)GetProcAddress(msvcr, "setlocale");
p__setmbcp = (void*)GetProcAddress(msvcr, "_setmbcp");
p_isleadbyte = (void*)GetProcAddress(msvcr, "isleadbyte");
+
+ init_thiscall_thunk();
return TRUE;
}
@@ -1805,6 +1931,82 @@ static void test_vbtable_size_exports(void)
}
}
+HANDLE _Pad__Launch_returned;
+_Pad pad;
+#ifdef __i386__
+/* TODO: this should be a __thiscall function */
+static unsigned int __stdcall vtbl_func__Go(void)
+#else
+static unsigned int __cdecl vtbl_func__Go(_Pad *this)
+#endif
+{
+ DWORD ret;
+
+ ret = WaitForSingleObject(_Pad__Launch_returned, 100);
+ ok(ret == WAIT_TIMEOUT, "WiatForSingleObject returned %x\n", ret);
+ ok(!pad.mtx->count, "pad.mtx.count = %d\n", pad.mtx->count);
+ ok(!pad.launched, "pad.launched = %x\n", pad.launched);
+ call_func1(p__Pad__Release, &pad);
+ ok(pad.launched, "pad.launched = %x\n", pad.launched);
+ ret = WaitForSingleObject(_Pad__Launch_returned, 100);
+ ok(ret == WAIT_OBJECT_0, "WiatForSingleObject returned %x\n", ret);
+ ok(pad.mtx->count == 1, "pad.mtx.count = %d\n", pad.mtx->count);
+ return 0;
+}
+
+static void test__Pad(void)
+{
+ _Pad pad_copy;
+ _Thrd_t thrd;
+ vtable_ptr pfunc = (vtable_ptr)&vtbl_func__Go;
+
+ _Pad__Launch_returned = CreateEventW(NULL, FALSE, FALSE, NULL);
+
+ pad.vtable = (void*)1;
+ pad.cnd = (void*)2;
+ pad.mtx = (void*)3;
+ pad.launched = TRUE;
+ memset(&pad_copy, 0, sizeof(pad_copy));
+ call_func2(p__Pad_copy_ctor, &pad_copy, &pad);
+ ok(pad_copy.vtable != (void*)1, "pad_copy.vtable was not set\n");
+ ok(pad_copy.cnd == (void*)2, "pad_copy.cnd = %p\n", pad_copy.cnd);
+ ok(pad_copy.mtx == (void*)3, "pad_copy.mtx = %p\n", pad_copy.mtx);
+ ok(pad_copy.launched, "pad_copy.launched = %x\n", pad_copy.launched);
+
+ memset(&pad_copy, 0xde, sizeof(pad_copy));
+ pad_copy.vtable = (void*)4;
+ pad_copy.cnd = (void*)5;
+ pad_copy.mtx = (void*)6;
+ pad_copy.launched = FALSE;
+ call_func2(p__Pad_op_assign, &pad_copy, &pad);
+ ok(pad_copy.vtable == (void*)4, "pad_copy.vtable was set\n");
+ ok(pad_copy.cnd == (void*)2, "pad_copy.cnd = %p\n", pad_copy.cnd);
+ ok(pad_copy.mtx == (void*)3, "pad_copy.mtx = %p\n", pad_copy.mtx);
+ ok(pad_copy.launched, "pad_copy.launched = %x\n", pad_copy.launched);
+
+ call_func1(p__Pad_ctor, &pad);
+ call_func2(p__Pad_copy_ctor, &pad_copy, &pad);
+ ok(pad.vtable == pad_copy.vtable, "pad.vtable = %p, pad_copy.vtable = %p\n", pad.vtable, pad_copy.vtable);
+ ok(pad.cnd == pad_copy.cnd, "pad.cnd = %p, pad_copy.cnd = %p\n", pad.cnd, pad_copy.cnd);
+ ok(pad.mtx == pad_copy.mtx, "pad.mtx = %p, pad_copy.mtx = %p\n", pad.mtx, pad_copy.mtx);
+ ok(pad.launched == pad_copy.launched, "pad.launched = %x, pad_copy.launched = %x\n", pad.launched, pad_copy.launched);
+ call_func1(p__Pad_dtor, &pad);
+ /* call_func1(p__Pad_dtor, &pad_copy); - copy constructor is broken, this causes a crash */
+
+ memset(&pad, 0xfe, sizeof(pad));
+ call_func1(p__Pad_ctor, &pad);
+ ok(!pad.launched, "pad.launched = %x\n", pad.launched);
+ ok(pad.mtx->count == 1, "pad.mtx.count = %d\n", pad.mtx->count);
+
+ pad.vtable = &pfunc;
+ call_func2(p__Pad__Launch, &pad, &thrd);
+ SetEvent(_Pad__Launch_returned);
+ ok(!p__Thrd_join(thrd, NULL), "_Thrd_join failed\n");
+
+ call_func1(p__Pad_dtor, &pad);
+ CloseHandle(_Pad__Launch_returned);
+}
+
START_TEST(msvcp120)
{
if(!init()) return;
@@ -1835,6 +2037,7 @@ START_TEST(msvcp120)
test_thrd();
test_cnd();
+ test__Pad();
test_vbtable_size_exports();
More information about the wine-cvs
mailing list