-- v4: rtworkq: Support putting work on RTWQ_CALLBACK_QUEUE_UNDEFINED. rtworkq/tests: Add a test for putting work on RTWQ_CALLBACK_QUEUE_UNDEFINED.
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mfplat/tests/mfplat.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 2b17b069d1d..15c93a7e747 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -2879,6 +2879,15 @@ static void test_MFCreateMFByteStreamOnStream(void) ok(res == 0, "got %#lx\n", res); IMFAsyncResult_Release(result);
+ hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_UNDEFINED, &test_callback->IMFAsyncCallback_iface, NULL); + todo_wine + ok(hr == S_OK, "got %#lx\n", hr); + res = wait_async_callback_result(&test_callback->IMFAsyncCallback_iface, 100, &result); + todo_wine + ok(res == 0, "got %#lx\n", res); + if (result) + IMFAsyncResult_Release(result); + test_stream_complete_read(stream); res = wait_async_callback_result(&read_callback->IMFAsyncCallback_iface, 1000, &result); ok(res == 0, "got %#lx\n", res);
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/rtworkq/tests/rtworkq.c | 142 +++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+)
diff --git a/dlls/rtworkq/tests/rtworkq.c b/dlls/rtworkq/tests/rtworkq.c index 2ff74d57b84..66dd1014e1a 100644 --- a/dlls/rtworkq/tests/rtworkq.c +++ b/dlls/rtworkq/tests/rtworkq.c @@ -19,12 +19,123 @@ #include <stdarg.h> #include <string.h>
+#define COBJMACROS + #include "windef.h" #include "winbase.h" +#include "initguid.h" #include "rtworkq.h"
#include "wine/test.h"
+/* Should be kept in sync with corresponding MFASYNC_CALLBACK_ constants. */ +enum rtwq_callback_queue_id +{ + RTWQ_CALLBACK_QUEUE_UNDEFINED = 0x00000000, + RTWQ_CALLBACK_QUEUE_STANDARD = 0x00000001, + RTWQ_CALLBACK_QUEUE_RT = 0x00000002, + RTWQ_CALLBACK_QUEUE_IO = 0x00000003, + RTWQ_CALLBACK_QUEUE_TIMER = 0x00000004, + RTWQ_CALLBACK_QUEUE_MULTITHREADED = 0x00000005, + RTWQ_CALLBACK_QUEUE_LONG_FUNCTION = 0x00000007, + RTWQ_CALLBACK_QUEUE_PRIVATE_MASK = 0xffff0000, + RTWQ_CALLBACK_QUEUE_ALL = 0xffffffff, +}; + +struct test_callback +{ + IRtwqAsyncCallback IRtwqAsyncCallback_iface; + LONG refcount; + HANDLE event; + IRtwqAsyncResult *result; +}; + +static struct test_callback *impl_from_IRtwqAsyncCallback(IRtwqAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct test_callback, IRtwqAsyncCallback_iface); +} + +static HRESULT WINAPI testcallback_QueryInterface(IRtwqAsyncCallback *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IRtwqAsyncCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IRtwqAsyncCallback_AddRef(iface); + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI testcallback_AddRef(IRtwqAsyncCallback *iface) +{ + struct test_callback *callback = impl_from_IRtwqAsyncCallback(iface); + return InterlockedIncrement(&callback->refcount); +} + +static ULONG WINAPI testcallback_Release(IRtwqAsyncCallback *iface) +{ + struct test_callback *callback = impl_from_IRtwqAsyncCallback(iface); + ULONG refcount = InterlockedDecrement(&callback->refcount); + + if (!refcount) + { + CloseHandle(callback->event); + free(callback); + } + + return refcount; +} + +static HRESULT WINAPI testcallback_GetParameters(IRtwqAsyncCallback *iface, DWORD *flags, DWORD *queue) +{ + ok(flags != NULL && queue != NULL, "Unexpected arguments.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testcallback_Invoke(IRtwqAsyncCallback *iface, IRtwqAsyncResult *result) +{ + struct test_callback *callback = impl_from_IRtwqAsyncCallback(iface); + + callback->result = result; + SetEvent(callback->event); + + return S_OK; +} + +static const IRtwqAsyncCallbackVtbl testcallbackvtbl = +{ + testcallback_QueryInterface, + testcallback_AddRef, + testcallback_Release, + testcallback_GetParameters, + testcallback_Invoke, +}; + +static struct test_callback * create_test_callback(void) +{ + struct test_callback *callback = calloc(1, sizeof(*callback)); + + callback->IRtwqAsyncCallback_iface.lpVtbl = &testcallbackvtbl; + callback->refcount = 1; + callback->event = CreateEventA(NULL, FALSE, FALSE, NULL); + + return callback; +} + +static DWORD wait_async_callback_result(IRtwqAsyncCallback *iface, DWORD timeout, IRtwqAsyncResult **result) +{ + struct test_callback *callback = impl_from_IRtwqAsyncCallback(iface); + DWORD res = WaitForSingleObject(callback->event, timeout); + + *result = callback->result; + callback->result = NULL; + + return res; +} + static void test_platform_init(void) { APTTYPEQUALIFIER qualifier; @@ -101,7 +212,38 @@ static void test_platform_init(void) ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr); }
+static void test_work_queue(void) +{ + IRtwqAsyncResult *result, *callback_result; + struct test_callback *test_callback; + HRESULT hr; + DWORD res; + + hr = RtwqStartup(); + ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr); + + test_callback = create_test_callback(); + + hr = RtwqCreateAsyncResult(NULL, &test_callback->IRtwqAsyncCallback_iface, NULL, &result); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = RtwqPutWorkItem(RTWQ_CALLBACK_QUEUE_UNDEFINED, 0, result); + ok(hr == S_OK, "got %#lx\n", hr); + res = wait_async_callback_result(&test_callback->IRtwqAsyncCallback_iface, 100, &callback_result); + todo_wine + ok(res == 0, "got %#lx\n", res); + todo_wine + ok(callback_result == result, "Expected result %p, got %p.\n", result, callback_result); + IRtwqAsyncResult_Release(result); + + IRtwqAsyncCallback_Release(&test_callback->IRtwqAsyncCallback_iface); + + hr = RtwqShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr); +} + START_TEST(rtworkq) { test_platform_init(); + test_work_queue(); }
From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mfplat/tests/mfplat.c | 5 +---- dlls/rtworkq/queue.c | 4 ++++ dlls/rtworkq/tests/rtworkq.c | 2 -- 3 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 15c93a7e747..8d033285a02 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -2880,13 +2880,10 @@ static void test_MFCreateMFByteStreamOnStream(void) IMFAsyncResult_Release(result);
hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_UNDEFINED, &test_callback->IMFAsyncCallback_iface, NULL); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); res = wait_async_callback_result(&test_callback->IMFAsyncCallback_iface, 100, &result); - todo_wine ok(res == 0, "got %#lx\n", res); - if (result) - IMFAsyncResult_Release(result); + IMFAsyncResult_Release(result);
test_stream_complete_read(stream); res = wait_async_callback_result(&read_callback->IMFAsyncCallback_iface, 1000, &result); diff --git a/dlls/rtworkq/queue.c b/dlls/rtworkq/queue.c index 9046a70b359..8b9bb631202 100644 --- a/dlls/rtworkq/queue.c +++ b/dlls/rtworkq/queue.c @@ -298,6 +298,10 @@ static struct queue *get_system_queue(DWORD queue_id) { switch (queue_id) { + case RTWQ_CALLBACK_QUEUE_UNDEFINED: + /* Works in native Windows. Undocumented, but seems to use standard. */ + queue_id = RTWQ_CALLBACK_QUEUE_STANDARD; + /* fall through */ case RTWQ_CALLBACK_QUEUE_STANDARD: case RTWQ_CALLBACK_QUEUE_RT: case RTWQ_CALLBACK_QUEUE_IO: diff --git a/dlls/rtworkq/tests/rtworkq.c b/dlls/rtworkq/tests/rtworkq.c index 66dd1014e1a..6cf415646eb 100644 --- a/dlls/rtworkq/tests/rtworkq.c +++ b/dlls/rtworkq/tests/rtworkq.c @@ -230,9 +230,7 @@ static void test_work_queue(void) hr = RtwqPutWorkItem(RTWQ_CALLBACK_QUEUE_UNDEFINED, 0, result); ok(hr == S_OK, "got %#lx\n", hr); res = wait_async_callback_result(&test_callback->IRtwqAsyncCallback_iface, 100, &callback_result); - todo_wine ok(res == 0, "got %#lx\n", res); - todo_wine ok(callback_result == result, "Expected result %p, got %p.\n", result, callback_result); IRtwqAsyncResult_Release(result);
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=151199
Your paranoid android.
=== w8 (32 bit report) ===
mfplat: mfplat.c:1324: Test failed: Unexpected refcount 3
=== w8adm (32 bit report) ===
mfplat: mfplat.c:1324: Test failed: Unexpected refcount 3
=== w1064v1507 (64 bit report) ===
mfplat: mfplat.c:1324: Test failed: Unexpected refcount 3
=== debian11 (32 bit report) ===
Report validation errors: mfplat:mfplat crashed (c0000028)
=== debian11b (32 bit WoW report) ===
Report validation errors: mfplat:mfplat crashed (c0000028)
=== debian11b (64 bit WoW report) ===
user32: input.c:4306: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000000AC00F8, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032
Added `enum rtwq_callback_queue_id` definition to rtworkq tests since !7174 adds them anyway.