mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-14 21:25:43 +00:00
msvcr120: Add tests for _StructuredTaskCollection.
Signed-off-by: Torge Matthies <tmatthies@codeweavers.com> Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
970405df1c
commit
821dd844ea
|
@ -162,6 +162,27 @@ typedef struct {
|
|||
Context *ctx;
|
||||
} _Context;
|
||||
|
||||
typedef struct _StructuredTaskCollection
|
||||
{
|
||||
void *unk1;
|
||||
unsigned int unk2;
|
||||
void *unk3;
|
||||
Context *context;
|
||||
volatile LONG count;
|
||||
volatile LONG finished;
|
||||
void *unk4;
|
||||
void *event;
|
||||
} _StructuredTaskCollection;
|
||||
|
||||
typedef struct _UnrealizedChore
|
||||
{
|
||||
const vtable_ptr *vtable;
|
||||
void (__cdecl *proc)(struct _UnrealizedChore*);
|
||||
struct _StructuredTaskCollection *task_collection;
|
||||
void (__cdecl *proc_wrapper)(struct _UnrealizedChore*);
|
||||
void *unk[6];
|
||||
} _UnrealizedChore;
|
||||
|
||||
static char* (CDECL *p_setlocale)(int category, const char* locale);
|
||||
static struct MSVCRT_lconv* (CDECL *p_localeconv)(void);
|
||||
static size_t (CDECL *p_wcstombs_s)(size_t *ret, char* dest, size_t sz, const wchar_t* src, size_t max);
|
||||
|
@ -225,6 +246,11 @@ static void (__thiscall *p__Condition_variable_notify_all)(_Condition_variable*)
|
|||
static Context* (__cdecl *p_Context_CurrentContext)(void);
|
||||
static _Context* (__cdecl *p__Context__CurrentContext)(_Context*);
|
||||
|
||||
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*);
|
||||
|
||||
#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)
|
||||
|
||||
|
@ -279,6 +305,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 +347,14 @@ 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_dtor,
|
||||
"??1_StructuredTaskCollection@details@Concurrency@@QAA@XZ");
|
||||
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 +386,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,
|
||||
|
@ -1270,6 +1320,224 @@ static void test_CurrentContext(void)
|
|||
ok(ret == &_ctx, "expected %p, got %p\n", &_ctx, ret);
|
||||
}
|
||||
|
||||
static void _UnrealizedChore_ctor(_UnrealizedChore *chore, void (__cdecl *proc)(_UnrealizedChore*))
|
||||
{
|
||||
memset(chore, 0, sizeof(*chore));
|
||||
chore->proc = proc;
|
||||
}
|
||||
|
||||
struct chore
|
||||
{
|
||||
_UnrealizedChore chore;
|
||||
BOOL executed;
|
||||
HANDLE start_event;
|
||||
HANDLE set_event;
|
||||
HANDLE wait_event;
|
||||
DWORD main_tid;
|
||||
};
|
||||
|
||||
static void __cdecl chore_proc(_UnrealizedChore *_this)
|
||||
{
|
||||
struct chore *chore = CONTAINING_RECORD(_this, struct chore, chore);
|
||||
|
||||
if (chore->start_event)
|
||||
{
|
||||
DWORD ret = WaitForSingleObject(chore->start_event, 5000);
|
||||
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", ret);
|
||||
}
|
||||
|
||||
ok(!chore->executed, "Chore was already executed\n");
|
||||
|
||||
if (chore->main_tid)
|
||||
{
|
||||
ok(GetCurrentThreadId() == chore->main_tid,
|
||||
"Main chore is not running on the main thread: 0x%lx != 0x%lx\n",
|
||||
GetCurrentThreadId(), chore->main_tid);
|
||||
}
|
||||
|
||||
if (!chore->wait_event)
|
||||
chore->executed = TRUE;
|
||||
|
||||
if (chore->set_event)
|
||||
{
|
||||
BOOL b = SetEvent(chore->set_event);
|
||||
ok(b, "SetEvent failed\n");
|
||||
}
|
||||
|
||||
if (chore->wait_event)
|
||||
{
|
||||
DWORD ret = WaitForSingleObject(chore->wait_event, 5000);
|
||||
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", ret);
|
||||
chore->executed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void chore_ctor(struct chore *chore)
|
||||
{
|
||||
memset(chore, 0, sizeof(*chore));
|
||||
_UnrealizedChore_ctor(&chore->chore, chore_proc);
|
||||
}
|
||||
|
||||
static void test_StructuredTaskCollection(void)
|
||||
{
|
||||
HANDLE chore_start_evt, chore_evt1, chore_evt2;
|
||||
_StructuredTaskCollection task_coll;
|
||||
struct chore chore1, chore2;
|
||||
DWORD main_thread_id;
|
||||
Context *context;
|
||||
int status;
|
||||
DWORD ret;
|
||||
BOOL b;
|
||||
|
||||
main_thread_id = GetCurrentThreadId();
|
||||
context = p_Context_CurrentContext();
|
||||
|
||||
memset(&task_coll, 0x55, sizeof(task_coll));
|
||||
if (!call_func2(p__StructuredTaskCollection_ctor, &task_coll, NULL))
|
||||
{
|
||||
skip("_StructuredTaskCollection constructor not implemented\n");
|
||||
return;
|
||||
}
|
||||
ok(task_coll.unk2 == 0x1fffffff,
|
||||
"_StructuredTaskCollection ctor set wrong unk2: 0x%x != 0x1fffffff\n", task_coll.unk2);
|
||||
ok(task_coll.unk3 == NULL,
|
||||
"_StructuredTaskCollection ctor set wrong unk3: %p != NULL\n", task_coll.unk3);
|
||||
ok(task_coll.context == NULL,
|
||||
"_StructuredTaskCollection ctor set wrong context: %p != NULL\n", task_coll.context);
|
||||
ok(task_coll.count == 0,
|
||||
"_StructuredTaskCollection ctor set wrong count: %ld != 0\n", task_coll.count);
|
||||
ok(task_coll.finished == LONG_MIN,
|
||||
"_StructuredTaskCollection ctor set wrong finished: %ld != %ld\n", task_coll.finished, LONG_MIN);
|
||||
ok(task_coll.unk4 == NULL,
|
||||
"_StructuredTaskCollection ctor set wrong unk4: %p != NULL\n", task_coll.unk4);
|
||||
|
||||
chore_start_evt = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
ok(chore_start_evt != NULL, "CreateEvent failed: 0x%lx\n", GetLastError());
|
||||
chore_evt1 = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
ok(chore_evt1 != NULL, "CreateEvent failed: 0x%lx\n", GetLastError());
|
||||
chore_evt2 = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
ok(chore_evt2 != NULL, "CreateEvent failed: 0x%lx\n", GetLastError());
|
||||
|
||||
/* test running chores (only main) */
|
||||
chore_ctor(&chore1);
|
||||
chore1.main_tid = main_thread_id;
|
||||
|
||||
status = p__StructuredTaskCollection__RunAndWait(&task_coll, &chore1.chore);
|
||||
ok(status == 1, "_StructuredTaskCollection::_RunAndWait failed: %d\n", status);
|
||||
ok(chore1.executed, "Scheduled chore was not executed\n");
|
||||
call_func1(p__StructuredTaskCollection_dtor, &task_coll);
|
||||
|
||||
/* test running chores (main + scheduled) */
|
||||
call_func2(p__StructuredTaskCollection_ctor, &task_coll, NULL);
|
||||
ResetEvent(chore_start_evt);
|
||||
chore_ctor(&chore1);
|
||||
chore1.start_event = chore_start_evt;
|
||||
chore_ctor(&chore2);
|
||||
chore2.main_tid = main_thread_id;
|
||||
|
||||
call_func2(p__StructuredTaskCollection__Schedule, &task_coll, &chore1.chore);
|
||||
ok(chore1.chore.task_collection == &task_coll, "Wrong chore #1 task_collection: expected %p, actual %p\n",
|
||||
&task_coll, chore1.chore.task_collection);
|
||||
ok(chore1.chore.proc_wrapper != NULL, "Chore #1 proc_wrapper was not set\n");
|
||||
ok(task_coll.count == 1, "Wrong chore count: %ld != 1\n", task_coll.count);
|
||||
ok(task_coll.context == context, "Unexpected context: %p != %p\n", task_coll.context, context);
|
||||
|
||||
b = SetEvent(chore_start_evt);
|
||||
ok(b, "SetEvent failed\n");
|
||||
|
||||
status = p__StructuredTaskCollection__RunAndWait(&task_coll, &chore2.chore);
|
||||
ok(status == 1, "_StructuredTaskCollection::_RunAndWait failed: %d\n", status);
|
||||
ok(chore1.executed, "Scheduled chore was not executed\n");
|
||||
ok(chore2.executed, "Main chore was not executed\n");
|
||||
call_func1(p__StructuredTaskCollection_dtor, &task_coll);
|
||||
|
||||
/* test that scheduled chores may run in parallel */
|
||||
call_func2(p__StructuredTaskCollection_ctor, &task_coll, NULL);
|
||||
ResetEvent(chore_start_evt);
|
||||
chore_ctor(&chore1);
|
||||
chore1.start_event = chore_start_evt;
|
||||
chore1.set_event = chore_evt2;
|
||||
chore1.wait_event = chore_evt1;
|
||||
chore_ctor(&chore2);
|
||||
chore2.start_event = chore_start_evt;
|
||||
chore2.set_event = chore_evt1;
|
||||
chore2.wait_event = chore_evt2;
|
||||
|
||||
call_func2(p__StructuredTaskCollection__Schedule, &task_coll, &chore1.chore);
|
||||
ok(chore1.chore.task_collection == &task_coll, "Wrong chore #1 task_collection: expected %p, actual %p\n",
|
||||
&task_coll, chore1.chore.task_collection);
|
||||
ok(chore1.chore.proc_wrapper != NULL, "Chore #1 proc_wrapper was not set\n");
|
||||
ok(task_coll.count == 1, "Wrong chore count: %ld != 1\n", task_coll.count);
|
||||
ok(task_coll.context == context, "Unexpected context: %p != %p\n", task_coll.context, context);
|
||||
|
||||
call_func2(p__StructuredTaskCollection__Schedule, &task_coll, &chore2.chore);
|
||||
ok(chore2.chore.task_collection == &task_coll, "Wrong chore #2 task_collection: expected %p, actual %p\n",
|
||||
&task_coll, chore2.chore.task_collection);
|
||||
ok(chore2.chore.proc_wrapper != NULL, "Chore #2 proc_wrapper was not set\n");
|
||||
ok(task_coll.count == 2, "Wrong chore count: %ld != 2\n", task_coll.count);
|
||||
ok(task_coll.context == context, "Unexpected context: %p != %p\n", task_coll.context, context);
|
||||
|
||||
b = SetEvent(chore_start_evt);
|
||||
ok(b, "SetEvent failed\n");
|
||||
|
||||
status = p__StructuredTaskCollection__RunAndWait(&task_coll, NULL);
|
||||
ok(status == 1, "_StructuredTaskCollection::_RunAndWait failed: %d\n", status);
|
||||
ok(chore1.executed, "Chore #1 was not executed\n");
|
||||
ok(chore2.executed, "Chore #2 was not executed\n");
|
||||
call_func1(p__StructuredTaskCollection_dtor, &task_coll);
|
||||
|
||||
/* test that scheduled chores are executed even if _RunAndWait is not called */
|
||||
call_func2(p__StructuredTaskCollection_ctor, &task_coll, NULL);
|
||||
ResetEvent(chore_start_evt);
|
||||
chore_ctor(&chore1);
|
||||
chore1.start_event = chore_start_evt;
|
||||
chore1.set_event = chore_evt1;
|
||||
|
||||
call_func2(p__StructuredTaskCollection__Schedule, &task_coll, &chore1.chore);
|
||||
ok(chore1.chore.task_collection == &task_coll, "Wrong chore #1 task_collection: expected %p, actual %p\n",
|
||||
&task_coll, chore1.chore.task_collection);
|
||||
ok(chore1.chore.proc_wrapper != NULL, "Chore #1 proc_wrapper was not set\n");
|
||||
ok(task_coll.count == 1, "Wrong chore count: %ld != 1\n", task_coll.count);
|
||||
ok(task_coll.context == context, "Unexpected context: %p != %p\n", task_coll.context, context);
|
||||
|
||||
b = SetEvent(chore_start_evt);
|
||||
ok(b, "SetEvent failed\n");
|
||||
|
||||
ret = WaitForSingleObject(chore_evt1, 5000);
|
||||
ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %ld\n", ret);
|
||||
ok(chore1.executed, "Chore was not executed\n");
|
||||
|
||||
status = p__StructuredTaskCollection__RunAndWait(&task_coll, NULL);
|
||||
ok(status == 1, "_StructuredTaskCollection::_RunAndWait failed: %d\n", status);
|
||||
ok(chore1.chore.task_collection == NULL, "Chore's task collection was not reset after execution\n");
|
||||
call_func1(p__StructuredTaskCollection_dtor, &task_coll);
|
||||
|
||||
/* test that finished chores can be scheduled again */
|
||||
call_func2(p__StructuredTaskCollection_ctor, &task_coll, NULL);
|
||||
ResetEvent(chore_start_evt);
|
||||
chore1.set_event = NULL;
|
||||
chore1.executed = FALSE;
|
||||
|
||||
call_func2(p__StructuredTaskCollection__Schedule, &task_coll, &chore1.chore);
|
||||
ok(chore1.chore.task_collection == &task_coll, "Wrong chore #1 task_collection: expected %p, actual %p\n",
|
||||
&task_coll, chore1.chore.task_collection);
|
||||
ok(chore1.chore.proc_wrapper != NULL, "Chore #1 proc_wrapper was not set\n");
|
||||
ok(task_coll.count == 1, "Wrong chore count: %ld != 1\n", task_coll.count);
|
||||
ok(task_coll.context == context, "Unexpected context: %p != %p\n", task_coll.context, context);
|
||||
|
||||
b = SetEvent(chore_start_evt);
|
||||
ok(b, "SetEvent failed\n");
|
||||
|
||||
status = p__StructuredTaskCollection__RunAndWait(&task_coll, NULL);
|
||||
ok(status == 1, "_StructuredTaskCollection::_RunAndWait failed: %d\n", status);
|
||||
ok(chore1.executed, "Chore was not executed\n");
|
||||
call_func1(p__StructuredTaskCollection_dtor, &task_coll);
|
||||
|
||||
CloseHandle(chore_start_evt);
|
||||
CloseHandle(chore_evt1);
|
||||
CloseHandle(chore_evt2);
|
||||
}
|
||||
|
||||
START_TEST(msvcr120)
|
||||
{
|
||||
if (!init()) return;
|
||||
|
@ -1292,4 +1560,5 @@ START_TEST(msvcr120)
|
|||
test_nexttoward();
|
||||
test_towctrans();
|
||||
test_CurrentContext();
|
||||
test_StructuredTaskCollection();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue