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