Piotr Caban : msvcr120: Add _Condition_variable tests.
Alexandre Julliard
julliard at winehq.org
Thu Nov 17 17:45:58 CST 2016
Module: wine
Branch: master
Commit: ccda9bbba43f642f9f1cb631c18adfbc59019a18
URL: http://source.winehq.org/git/wine.git/?a=commit;h=ccda9bbba43f642f9f1cb631c18adfbc59019a18
Author: Piotr Caban <piotr at codeweavers.com>
Date: Thu Nov 17 09:56:21 2016 -0600
msvcr120: Add _Condition_variable tests.
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/msvcr120/tests/msvcr120.c | 125 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 125 insertions(+)
diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c
index 4ecea51..e631738 100644
--- a/dlls/msvcr120/tests/msvcr120.c
+++ b/dlls/msvcr120/tests/msvcr120.c
@@ -46,6 +46,8 @@ struct thiscall_thunk
static ULONG_PTR (WINAPI *call_thiscall_func1)( void *func, void *this );
static ULONG_PTR (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
+static ULONG_PTR (WINAPI *call_thiscall_func3)( void *func,
+ void *this, const void *a, const void *b );
static void init_thiscall_thunk(void)
{
@@ -58,16 +60,19 @@ static void init_thiscall_thunk(void)
thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
call_thiscall_func1 = (void *)thunk;
call_thiscall_func2 = (void *)thunk;
+ call_thiscall_func3 = (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))
+#define call_func3(func,_this,a,b) call_thiscall_func3(func,_this,(const void*)(a),(const void*)(b))
#else
#define init_thiscall_thunk()
#define call_func1(func,_this) func(_this)
#define call_func2(func,_this,a) func(_this,a)
+#define call_func3(func,_this,a,b) func(_this,a,b)
#endif /* __i386__ */
@@ -103,6 +108,11 @@ typedef struct
int unknown2[2];
} critical_section_scoped_lock;
+typedef struct {
+ void *chain;
+ critical_section lock;
+} _Condition_variable;
+
static inline float __port_infinity(void)
{
static const unsigned __inf_bytes = 0x7f800000;
@@ -188,6 +198,13 @@ static critical_section_scoped_lock* (__thiscall *p_critical_section_scoped_lock
(critical_section_scoped_lock*, critical_section *);
static void (__thiscall *p_critical_section_scoped_lock_dtor)(critical_section_scoped_lock*);
+static _Condition_variable* (__thiscall *p__Condition_variable_ctor)(_Condition_variable*);
+static void (__thiscall *p__Condition_variable_dtor)(_Condition_variable*);
+static void (__thiscall *p__Condition_variable_wait)(_Condition_variable*, critical_section*);
+static MSVCRT_bool (__thiscall *p__Condition_variable_wait_for)(_Condition_variable*, critical_section*, unsigned int);
+static void (__thiscall *p__Condition_variable_notify_one)(_Condition_variable*);
+static void (__thiscall *p__Condition_variable_notify_all)(_Condition_variable*);
+
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y)
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
@@ -240,6 +257,18 @@ static BOOL init(void)
"??0scoped_lock at critical_section@Concurrency@@QEAA at AEAV12@@Z");
SET(p_critical_section_scoped_lock_dtor,
"??1scoped_lock at critical_section@Concurrency@@QEAA at XZ");
+ SET(p__Condition_variable_ctor,
+ "??0_Condition_variable at details@Concurrency@@QEAA at XZ");
+ SET(p__Condition_variable_dtor,
+ "??1_Condition_variable at details@Concurrency@@QEAA at XZ");
+ SET(p__Condition_variable_wait,
+ "?wait at _Condition_variable@details at Concurrency@@QEAAXAEAVcritical_section at 3@@Z");
+ SET(p__Condition_variable_wait_for,
+ "?wait_for at _Condition_variable@details at Concurrency@@QEAA_NAEAVcritical_section at 3@I at Z");
+ SET(p__Condition_variable_notify_one,
+ "?notify_one at _Condition_variable@details at Concurrency@@QEAAXXZ");
+ SET(p__Condition_variable_notify_all,
+ "?notify_all at _Condition_variable@details at Concurrency@@QEAAXXZ");
} else {
#ifdef __arm__
SET(p_critical_section_ctor,
@@ -260,6 +289,18 @@ static BOOL init(void)
"??0scoped_lock at critical_section@Concurrency@@QAA at AAV12@@Z");
SET(p_critical_section_scoped_lock_dtor,
"??1scoped_lock at critical_section@Concurrency@@QAA at XZ");
+ SET(p__Condition_variable_ctor,
+ "??0_Condition_variable at details@Concurrency@@QAA at XZ");
+ SET(p__Condition_variable_dtor,
+ "??1_Condition_variable at details@Concurrency@@QAA at XZ");
+ SET(p__Condition_variable_wait,
+ "?wait at _Condition_variable@details at Concurrency@@QAAXAAVcritical_section at 3@@Z");
+ SET(p__Condition_variable_wait_for,
+ "?wait_for at _Condition_variable@details at Concurrency@@QAA_NAAVcritical_section at 3@I at Z");
+ SET(p__Condition_variable_notify_one,
+ "?notify_one at _Condition_variable@details at Concurrency@@QAAXXZ");
+ SET(p__Condition_variable_notify_all,
+ "?notify_all at _Condition_variable@details at Concurrency@@QAAXXZ");
#else
SET(p_critical_section_ctor,
"??0critical_section at Concurrency@@QAE at XZ");
@@ -279,6 +320,18 @@ static BOOL init(void)
"??0scoped_lock at critical_section@Concurrency@@QAE at AAV12@@Z");
SET(p_critical_section_scoped_lock_dtor,
"??1scoped_lock at critical_section@Concurrency@@QAE at XZ");
+ SET(p__Condition_variable_ctor,
+ "??0_Condition_variable at details@Concurrency@@QAE at XZ");
+ SET(p__Condition_variable_dtor,
+ "??1_Condition_variable at details@Concurrency@@QAE at XZ");
+ SET(p__Condition_variable_wait,
+ "?wait at _Condition_variable@details at Concurrency@@QAEXAAVcritical_section at 3@@Z");
+ SET(p__Condition_variable_wait_for,
+ "?wait_for at _Condition_variable@details at Concurrency@@QAE_NAAVcritical_section at 3@I at Z");
+ SET(p__Condition_variable_notify_one,
+ "?notify_one at _Condition_variable@details at Concurrency@@QAEXXZ");
+ SET(p__Condition_variable_notify_all,
+ "?notify_all at _Condition_variable@details at Concurrency@@QAEXXZ");
#endif
}
@@ -758,6 +811,77 @@ static void test__wcreate_locale(void)
ok(errno == -1, "expected errno -1, but got %i\n", e);
}
+struct wait_thread_arg
+{
+ critical_section *cs;
+ _Condition_variable *cv;
+ HANDLE thread_initialized;
+};
+
+static DWORD WINAPI condition_variable_wait_thread(void *varg)
+{
+ struct wait_thread_arg *arg = varg;
+
+ call_func1(p_critical_section_lock, arg->cs);
+ SetEvent(arg->thread_initialized);
+ call_func2(p__Condition_variable_wait, arg->cv, arg->cs);
+ call_func1(p_critical_section_unlock, arg->cs);
+ return 0;
+}
+
+static void test__Condition_variable(void)
+{
+ critical_section cs;
+ _Condition_variable cv;
+ HANDLE thread_initialized = CreateEventW(NULL, FALSE, FALSE, NULL);
+ struct wait_thread_arg wait_thread_arg = { &cs, &cv, thread_initialized };
+ HANDLE threads[2];
+ DWORD ret;
+ MSVCRT_bool b;
+
+ ok(thread_initialized != NULL, "CreateEvent failed\n");
+
+ call_func1(p_critical_section_ctor, &cs);
+ call_func1(p__Condition_variable_ctor, &cv);
+
+ call_func1(p__Condition_variable_notify_one, &cv);
+ call_func1(p__Condition_variable_notify_all, &cv);
+
+ threads[0] = CreateThread(0, 0, condition_variable_wait_thread,
+ &wait_thread_arg, 0, 0);
+ ok(threads[0] != NULL, "CreateThread failed\n");
+ WaitForSingleObject(thread_initialized, INFINITE);
+ call_func1(p_critical_section_lock, &cs);
+ call_func1(p_critical_section_unlock, &cs);
+
+ threads[1] = CreateThread(0, 0, condition_variable_wait_thread,
+ &wait_thread_arg, 0, 0);
+ ok(threads[1] != NULL, "CreateThread failed\n");
+ WaitForSingleObject(thread_initialized, INFINITE);
+ call_func1(p_critical_section_lock, &cs);
+ call_func1(p_critical_section_unlock, &cs);
+
+ call_func1(p__Condition_variable_notify_one, &cv);
+ ret = WaitForSingleObject(threads[1], 500);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
+ call_func1(p__Condition_variable_notify_one, &cv);
+ ret = WaitForSingleObject(threads[0], 500);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", ret);
+
+ CloseHandle(threads[0]);
+ CloseHandle(threads[1]);
+
+ call_func1(p_critical_section_lock, &cs);
+ b = call_func3(p__Condition_variable_wait_for, &cv, &cs, 1);
+ ok(!b, "_Condition_variable_wait_for returned TRUE\n");
+ call_func1(p_critical_section_unlock, &cs);
+
+ call_func1(p_critical_section_dtor, &cs);
+ call_func1(p__Condition_variable_dtor, &cv);
+
+ CloseHandle(thread_initialized);
+}
+
START_TEST(msvcr120)
{
if (!init()) return;
@@ -773,4 +897,5 @@ START_TEST(msvcr120)
test_critical_section();
test_fegetenv();
test__wcreate_locale();
+ test__Condition_variable();
}
More information about the wine-cvs
mailing list