[PATCH 3/3] mfplat/tests: Add some tests for COM initialization in work queues threads.
Nikolay Sivov
nsivov at codeweavers.com
Fri Feb 14 04:01:10 CST 2020
Based on patch by Derek Lesho.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfplat/tests/mfplat.c | 158 ++++++++++++++++++++++++++++++++++++-
1 file changed, 155 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 66524f1b48..ec84c6c261 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -63,6 +63,8 @@ static HRESULT (WINAPI *pD3D11CreateDevice)(IDXGIAdapter *adapter, D3D_DRIVER_TY
const D3D_FEATURE_LEVEL *feature_levels, UINT levels, UINT sdk_version, ID3D11Device **device_out,
D3D_FEATURE_LEVEL *obtained_feature_level, ID3D11DeviceContext **immediate_context);
+static HRESULT (WINAPI *pCoGetApartmentType)(APTTYPE *type, APTTYPEQUALIFIER *qualifier);
+
static HRESULT (WINAPI *pMFCopyImage)(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride,
DWORD width, DWORD lines);
static HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager);
@@ -86,6 +88,7 @@ static HRESULT (WINAPI *pMFTRegisterLocalByCLSID)(REFCLSID clsid, REFGUID catego
const MFT_REGISTER_TYPE_INFO *output_types);
static HRESULT (WINAPI *pMFTUnregisterLocal)(IClassFactory *factory);
static HRESULT (WINAPI *pMFTUnregisterLocalByCLSID)(CLSID clsid);
+static HRESULT (WINAPI *pMFAllocateWorkQueueEx)(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue);
static const WCHAR mp4file[] = {'t','e','s','t','.','m','p','4',0};
static const WCHAR fileschemeW[] = {'f','i','l','e',':','/','/',0};
@@ -122,6 +125,7 @@ struct test_callback
{
IMFAsyncCallback IMFAsyncCallback_iface;
HANDLE event;
+ DWORD param;
};
static struct test_callback *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
@@ -651,6 +655,7 @@ static void init_functions(void)
#define X(f) p##f = (void*)GetProcAddress(mod, #f)
X(MFAddPeriodicCallback);
X(MFAllocateSerialWorkQueue);
+ X(MFAllocateWorkQueueEx);
X(MFCopyImage);
X(MFCreateDXGIDeviceManager);
X(MFCreateSourceResolver);
@@ -666,13 +671,17 @@ static void init_functions(void)
X(MFTRegisterLocalByCLSID);
X(MFTUnregisterLocal);
X(MFTUnregisterLocalByCLSID);
-#undef X
if ((mod = LoadLibraryA("d3d11.dll")))
{
- pD3D11CreateDevice = (void *)GetProcAddress(mod, "D3D11CreateDevice");
+ X(D3D11CreateDevice);
}
+ mod = GetModuleHandleA("ole32.dll");
+
+ X(CoGetApartmentType);
+#undef X
+
is_win8_plus = pMFPutWaitingWorkItem != NULL;
}
@@ -4079,12 +4088,154 @@ static void test_MFTRegisterLocal(void)
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
}
+static void test_queue_com(void)
+{
+ static int system_queues[] =
+ {
+ MFASYNC_CALLBACK_QUEUE_STANDARD,
+ MFASYNC_CALLBACK_QUEUE_RT,
+ MFASYNC_CALLBACK_QUEUE_IO,
+ MFASYNC_CALLBACK_QUEUE_TIMER,
+ MFASYNC_CALLBACK_QUEUE_MULTITHREADED,
+ MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION,
+ };
+
+ static int user_queues[] =
+ {
+ MF_STANDARD_WORKQUEUE,
+ MF_WINDOW_WORKQUEUE,
+ MF_MULTITHREADED_WORKQUEUE,
+ };
+
+ char path_name[MAX_PATH];
+ PROCESS_INFORMATION info;
+ STARTUPINFOA startup;
+ char **argv;
+ int i;
+
+ if (!pCoGetApartmentType)
+ {
+ win_skip("CoGetApartmentType() is not available.\n");
+ return;
+ }
+
+ winetest_get_mainargs(&argv);
+
+ for (i = 0; i < ARRAY_SIZE(system_queues); ++i)
+ {
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ sprintf(path_name, "%s mfplat s%d", argv[0], system_queues[i]);
+ ok(CreateProcessA( NULL, path_name, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info),
+ "CreateProcess failed.\n" );
+ winetest_wait_child_process(info.hProcess);
+ CloseHandle(info.hProcess);
+ CloseHandle(info.hThread);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(user_queues); ++i)
+ {
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ sprintf(path_name, "%s mfplat u%d", argv[0], user_queues[i]);
+ ok(CreateProcessA( NULL, path_name, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info),
+ "CreateProcess failed.\n" );
+ winetest_wait_child_process(info.hProcess);
+ CloseHandle(info.hProcess);
+ CloseHandle(info.hThread);
+ }
+}
+
+static HRESULT WINAPI test_queue_com_state_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
+{
+ struct test_callback *callback = impl_from_IMFAsyncCallback(iface);
+ APTTYPEQUALIFIER qualifier;
+ APTTYPE com_type;
+ HRESULT hr;
+
+ hr = pCoGetApartmentType(&com_type, &qualifier);
+ ok(SUCCEEDED(hr), "Failed to get apartment type, hr %#x.\n", hr);
+ if (SUCCEEDED(hr))
+ {
+ todo_wine {
+ if (callback->param == MFASYNC_CALLBACK_QUEUE_LONG_FUNCTION)
+ ok(com_type == APTTYPE_MAINSTA && qualifier == APTTYPEQUALIFIER_NONE,
+ "%#x: unexpected type %u, qualifier %u.\n", callback->param, com_type, qualifier);
+ else
+ ok(com_type == APTTYPE_MTA && qualifier == APTTYPEQUALIFIER_NONE,
+ "%#x: unexpected type %u, qualifier %u.\n", callback->param, com_type, qualifier);
+ }
+ }
+
+ SetEvent(callback->event);
+ return S_OK;
+}
+
+static const IMFAsyncCallbackVtbl test_queue_com_state_callback_vtbl =
+{
+ testcallback_QueryInterface,
+ testcallback_AddRef,
+ testcallback_Release,
+ testcallback_GetParameters,
+ test_queue_com_state_callback_Invoke,
+};
+
+static void test_queue_com_state(const char *name)
+{
+ struct test_callback callback = { { &test_queue_com_state_callback_vtbl } };
+ DWORD queue, queue_type;
+ HRESULT hr;
+
+ callback.event = CreateEventA(NULL, FALSE, FALSE, NULL);
+
+ hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
+ ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
+
+ if (name[0] == 's')
+ {
+ callback.param = name[1] - '0';
+ hr = MFPutWorkItem(callback.param, &callback.IMFAsyncCallback_iface, NULL);
+ ok(SUCCEEDED(hr), "Failed to queue work item, hr %#x.\n", hr);
+ WaitForSingleObject(callback.event, INFINITE);
+ }
+ else if (name[0] == 'u')
+ {
+ queue_type = name[1] - '0';
+
+ hr = pMFAllocateWorkQueueEx(queue_type, &queue);
+ ok(hr == S_OK, "Failed to allocate a queue, hr %#x.\n", hr);
+
+ callback.param = queue;
+ hr = MFPutWorkItem(queue, &callback.IMFAsyncCallback_iface, NULL);
+ ok(SUCCEEDED(hr), "Failed to queue work item, hr %#x.\n", hr);
+ WaitForSingleObject(callback.event, INFINITE);
+
+ hr = MFUnlockWorkQueue(queue);
+ ok(hr == S_OK, "Failed to unlock the queue, hr %#x.\n", hr);
+ }
+
+ CloseHandle(callback.event);
+
+ hr = MFShutdown();
+ ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
+}
+
START_TEST(mfplat)
{
- CoInitialize(NULL);
+ char **argv;
+ int argc;
init_functions();
+ argc = winetest_get_mainargs(&argv);
+ if (argc >= 3)
+ {
+ test_queue_com_state(argv[2]);
+ return;
+ }
+
+ CoInitialize(NULL);
+
test_startup();
test_register();
test_media_type();
@@ -4119,6 +4270,7 @@ START_TEST(mfplat)
test_dxgi_device_manager();
test_MFCreateTransformActivate();
test_MFTRegisterLocal();
+ test_queue_com();
CoUninitialize();
}
--
2.25.0
More information about the wine-devel
mailing list