Signed-off-by: Torge Matthies tmatthies@codeweavers.com --- v5 -> v6: Fixed calling convention of _StructuredTaskCollection::_RunAndWait.
dlls/msvcr120/tests/msvcr120.c | 131 +++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+)
diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index a3161266db41..1fde3afed4a8 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -95,6 +95,31 @@ typedef struct cs_queue int unknown; } cs_queue;
+typedef struct UnrealizedChore +{ + void *unk1; + void (__cdecl *callback)(struct UnrealizedChore *_this, void *unk); + void *unk2; + void *unk3; + void *unk4; + void *unk5; + void *unk6; + void *unk7; + void *unk8; + void *unk9; +} UnrealizedChore; + +typedef struct +{ + void *unk1; + unsigned int unk2; + void *unk3; + void *volatile unk_chores; + unsigned int count; + unsigned int unk5; + void *unk6; +} StructuredTaskCollection; + typedef struct { ULONG_PTR unk_thread_id; @@ -204,6 +229,11 @@ static wint_t (__cdecl *p_towctrans)(wint_t, wctrans_t); #undef errno #define errno (*p_errno())
+static StructuredTaskCollection* (__thiscall *p__StructuredTaskCollection_ctor)(StructuredTaskCollection*, void*); +static void (__thiscall *p__StructuredTaskCollection_dtor)(StructuredTaskCollection*); +static void (__thiscall *p__StructuredTaskCollection__Schedule)(StructuredTaskCollection*, UnrealizedChore*); +static int (__stdcall *p__StructuredTaskCollection__RunAndWait)(StructuredTaskCollection*, UnrealizedChore*); + static critical_section* (__thiscall *p_critical_section_ctor)(critical_section*); static void (__thiscall *p_critical_section_dtor)(critical_section*); static void (__thiscall *p_critical_section_lock)(critical_section*); @@ -279,6 +309,14 @@ static BOOL init(void) SET(p_towctrans, "towctrans"); SET(p__Context__CurrentContext, "?_CurrentContext@_Context@details@Concurrency@@SA?AV123@XZ"); if(sizeof(void*) == 8) { /* 64-bit initialization */ + SET(p__StructuredTaskCollection_ctor, + "??0_StructuredTaskCollection@details@Concurrency@@QEAA@PEAV_CancellationTokenState@12@@Z"); + SET(p__StructuredTaskCollection_dtor, + "??1_StructuredTaskCollection@details@Concurrency@@QEAA@XZ"); + SET(p__StructuredTaskCollection__Schedule, + "?_Schedule@_StructuredTaskCollection@details@Concurrency@@QEAAXPEAV_UnrealizedChore@23@@Z"); + SET(p__StructuredTaskCollection__RunAndWait, + "?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QEAA?AW4_TaskCollectionStatus@23@PEAV_UnrealizedChore@23@@Z"); SET(p_critical_section_ctor, "??0critical_section@Concurrency@@QEAA@XZ"); SET(p_critical_section_dtor, @@ -313,6 +351,12 @@ static BOOL init(void) "?CurrentContext@Context@Concurrency@@SAPEAV12@XZ"); } else { #ifdef __arm__ + SET(p__StructuredTaskCollection_ctor, + "??0_StructuredTaskCollection@details@Concurrency@@QAA@PAV_CancellationTokenState@12@@Z"); + SET(p__StructuredTaskCollection__Schedule, + "?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@@Z"); + SET(p__StructuredTaskCollection__RunAndWait, + "?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z"); SET(p_critical_section_ctor, "??0critical_section@Concurrency@@QAA@XZ"); SET(p_critical_section_dtor, @@ -344,6 +388,14 @@ static BOOL init(void) SET(p__Condition_variable_notify_all, "?notify_all@_Condition_variable@details@Concurrency@@QAAXXZ"); #else + SET(p__StructuredTaskCollection_ctor, + "??0_StructuredTaskCollection@details@Concurrency@@QAE@PAV_CancellationTokenState@12@@Z"); + SET(p__StructuredTaskCollection_dtor, + "??1_StructuredTaskCollection@details@Concurrency@@QAE@XZ"); + SET(p__StructuredTaskCollection__Schedule, + "?_Schedule@_StructuredTaskCollection@details@Concurrency@@QAEXPAV_UnrealizedChore@23@@Z"); + SET(p__StructuredTaskCollection__RunAndWait, + "?_RunAndWait@_StructuredTaskCollection@details@Concurrency@@QAG?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@23@@Z"); SET(p_critical_section_ctor, "??0critical_section@Concurrency@@QAE@XZ"); SET(p_critical_section_dtor, @@ -738,6 +790,84 @@ static unsigned __stdcall test_critical_section_scoped_lock(void *arg) return 0; }
+static void setup_chore(UnrealizedChore *chore, void (__cdecl *callback)(struct UnrealizedChore *_this, void *unk)) +{ + chore->unk1 = (void*)0xdeadbeef; + chore->callback = callback; + chore->unk2 = NULL; + chore->unk3 = (void*)0xdead0000; + chore->unk4 = (void*)0xdead1000; + chore->unk5 = (void*)0xdead2000; + chore->unk6 = (void*)0xdead3000; + chore->unk7 = (void*)0xdead4000; + chore->unk8 = (void*)0xdead5000; + chore->unk9 = (void*)0xdead6000; +} + +static HANDLE chore_evt1; +static HANDLE chore_evt2; +static BOOL chore1_executed; +static BOOL chore2_executed; +static BOOL main_chore_executed; + +void __cdecl chore1_cb(struct UnrealizedChore *_this, void *unk) +{ + BOOL b; + DWORD ret; + b = SetEvent(chore_evt1); + ok(b, "SetEvent failed\n"); + ret = WaitForSingleObject(chore_evt2, 5000); + ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", ret); + chore1_executed = TRUE; +} + +void __cdecl chore2_cb(struct UnrealizedChore *_this, void *unk) +{ + BOOL b; + DWORD ret; + b = SetEvent(chore_evt2); + ok(b, "SetEvent failed\n"); + ret = WaitForSingleObject(chore_evt1, 5000); + ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", ret); + chore2_executed = TRUE; +} + +void __cdecl main_chore_cb(struct UnrealizedChore *_this, void *unk) +{ + main_chore_executed = TRUE; +} + +static void test_StructuredTaskCollection(void) +{ + StructuredTaskCollection task_coll; + UnrealizedChore chore1, chore2, main_chore; + int status; + + chore_evt1 = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(chore_evt1 != NULL, "CreateEvent failed\n"); + chore_evt2 = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(chore_evt2 != NULL, "CreateEvent failed\n"); + + call_func2(p__StructuredTaskCollection_ctor, &task_coll, NULL); + + /* test that all chores are run in parallel */ + setup_chore(&chore1, chore1_cb); + setup_chore(&chore2, chore2_cb); + setup_chore(&main_chore, main_chore_cb); + call_func2(p__StructuredTaskCollection__Schedule, &task_coll, &chore1); + call_func2(p__StructuredTaskCollection__Schedule, &task_coll, &chore2); + status = p__StructuredTaskCollection__RunAndWait(&task_coll, &main_chore); + ok(status == 1, "_StructuredTaskCollection::_RunAndWait failed: %d\n", status); + todo_wine ok(chore1_executed, "_StructuredTaskCollection::_RunAndWait did not execute chore1\n"); + todo_wine ok(chore2_executed, "_StructuredTaskCollection::_RunAndWait did not execute chore2\n"); + todo_wine ok(main_chore_executed, "_StructuredTaskCollection::_RunAndWait did not execute the main chore\n"); + + call_func1(p__StructuredTaskCollection_dtor, &task_coll); + + CloseHandle(chore_evt1); + CloseHandle(chore_evt2); +} + static void test_critical_section(void) { HANDLE thread; @@ -1282,6 +1412,7 @@ START_TEST(msvcr120) test_gettnames(p__Gettnames); test__strtof(); test_remainder(); + test_StructuredTaskCollection(); test_critical_section(); test_feenv(); test__wcreate_locale();