From 4926bb148b049f1b60e57091f4aa87a3957aa69e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bernhard=20K=C3=B6lbl?= Date: Wed, 6 Apr 2022 18:28:41 +0200 Subject: [PATCH] windows.media.speech: Add tests for IAsyncOperation. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Bernhard Kölbl Signed-off-by: Rémi Bernon Signed-off-by: Alexandre Julliard --- dlls/windows.media.speech/tests/speech.c | 241 ++++++++++++++++++++++++++++++- 1 file changed, 239 insertions(+), 2 deletions(-) diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 8093c4b95b8..96029a0f833 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -38,6 +38,8 @@ #include "wine/test.h" +#define AsyncStatus_Closed 4 + #define SPERR_WINRT_INTERNAL_ERROR 0x800455a0 #define IHandler_RecognitionResult ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionResultGeneratedEventArgs @@ -52,6 +54,12 @@ #define impl_from_IHandler_RecognitionCompleted impl_from_ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgs #define IHandler_RecognitionCompleted_iface ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgs_iface +#define IAsyncHandler_Compilation IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult +#define IAsyncHandler_CompilationVtbl IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResultVtbl +#define IID_IAsyncHandler_Compilation IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult +#define impl_from_IAsyncHandler_Compilation impl_from_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult +#define IAsyncHandler_Compilation_iface IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult_iface + HRESULT WINAPI (*pDllGetActivationFactory)(HSTRING, IActivationFactory **); static BOOL is_win10_1507 = FALSE; @@ -226,6 +234,87 @@ static HRESULT WINAPI recognition_result_handler_create_static( struct recogniti return S_OK; } +struct compilation_handler +{ + IAsyncHandler_Compilation IAsyncHandler_Compilation_iface; + LONG ref; + + HANDLE event_finished; + BOOLEAN sleeping; + DWORD thread_id; +}; + +static inline struct compilation_handler *impl_from_IAsyncHandler_Compilation( IAsyncHandler_Compilation *iface ) +{ + return CONTAINING_RECORD(iface, struct compilation_handler, IAsyncHandler_Compilation_iface); +} + +HRESULT WINAPI compilation_handler_QueryInterface( IAsyncHandler_Compilation *iface, + REFIID iid, + void **out ) +{ + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IAgileObject) || + IsEqualGUID(iid, &IID_IAsyncHandler_Compilation)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + trace("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +ULONG WINAPI compilation_handler_AddRef( IAsyncHandler_Compilation *iface ) +{ + struct compilation_handler *impl = impl_from_IAsyncHandler_Compilation(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + return ref; +} + +ULONG WINAPI compilation_handler_Release( IAsyncHandler_Compilation *iface ) +{ + struct compilation_handler *impl = impl_from_IAsyncHandler_Compilation(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + return ref; +} + +HRESULT WINAPI compilation_handler_Invoke( IAsyncHandler_Compilation *iface, + IAsyncOperation_SpeechRecognitionCompilationResult *info, + AsyncStatus status ) +{ + struct compilation_handler *impl = impl_from_IAsyncHandler_Compilation(iface); + DWORD id = GetCurrentThreadId(); + trace("Iface %p, info %p, status %d.\n", iface, info, status); + trace("Caller thread id %lu callback thread id %lu.\n", impl->thread_id, id); + + ok(status != Started, "Got unexpected status %#x.\n", status); + if (impl->event_finished) SetEvent(impl->event_finished); + + return S_OK; +} + +static const struct IAsyncHandler_CompilationVtbl compilation_handler_vtbl = +{ + /* IUnknown methods */ + compilation_handler_QueryInterface, + compilation_handler_AddRef, + compilation_handler_Release, + /* IAsyncOperationCompletedHandler methods */ + compilation_handler_Invoke +}; + + +static HRESULT WINAPI compilation_handler_create_static( struct compilation_handler *impl ) +{ + impl->IAsyncHandler_Compilation_iface.lpVtbl = &compilation_handler_vtbl; + impl->ref = 1; + + return S_OK; +} + struct iterator_hstring { IIterator_HSTRING IIterator_HSTRING_iface; @@ -421,8 +510,6 @@ static HRESULT WINAPI iterable_hstring_First( IIterable_HSTRING *iface, IIterato struct iterable_hstring *impl = impl_from_Iterable_HSTRING(iface); struct iterator_hstring *impl_iter = impl_from_IIterator_HSTRING(impl->iterator); - trace("iface %p, value %p.\n", iface, value); - impl_iter->index = 0; IIterator_HSTRING_AddRef((*value = impl->iterator)); return S_OK; @@ -729,6 +816,9 @@ static void test_VoiceInformation(void) static void test_SpeechRecognizer(void) { static const WCHAR *speech_recognition_name = L"Windows.Media.SpeechRecognition.SpeechRecognizer"; + IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult *handler = NULL; + IAsyncOperation_SpeechRecognitionCompilationResult *operation = NULL; + ISpeechRecognitionCompilationResult *compilation_result = NULL; IVector_ISpeechRecognitionConstraint *constraints = NULL; ISpeechContinuousRecognitionSession *session = NULL; ISpeechRecognizerFactory *sr_factory = NULL; @@ -740,11 +830,17 @@ static void test_SpeechRecognizer(void) IInspectable *inspectable = NULL; IClosable *closable = NULL; ILanguage *language = NULL; + IAsyncInfo *info = NULL; struct completed_event_handler completed_handler; struct recognition_result_handler result_handler; + struct compilation_handler compilation_handler; + struct compilation_handler compilation_handler2; + SpeechRecognitionResultStatus result_status; EventRegistrationToken token = { .value = 0 }; + AsyncStatus async_status; HSTRING hstr, hstr_lang; HRESULT hr; + UINT32 id; LONG ref; hr = RoInitialize(RO_INIT_MULTITHREADED); @@ -848,6 +944,147 @@ static void test_SpeechRecognizer(void) ref = IVector_ISpeechRecognitionConstraint_Release(constraints); ok(ref == 1, "Got unexpected ref %lu.\n", ref); + compilation_handler_create_static(&compilation_handler); + compilation_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); + compilation_handler.thread_id = GetCurrentThreadId(); + + hr = ISpeechRecognizer_CompileConstraintsAsync(recognizer, &operation); + todo_wine ok(hr == S_OK, "ISpeechRecognizer_CompileConstraintsAsync failed, hr %#lx.\n", hr); + + if (FAILED(hr)) goto skip_operation; + + handler = (void*)0xdeadbeef; + hr = IAsyncOperation_SpeechRecognitionCompilationResult_get_Completed(operation, &handler); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(handler == NULL, "Handler had value %p.\n", handler); + + compilation_result = (void*)0xdeadbeef; + hr = IAsyncOperation_SpeechRecognitionCompilationResult_GetResults(operation, &compilation_result); + todo_wine ok(hr == E_ILLEGAL_METHOD_CALL, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(compilation_result == (void*)0xdeadbeef, "Compilation result had value %p.\n", compilation_result); + + hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, &compilation_handler.IAsyncHandler_Compilation_iface); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine check_refcount(&compilation_handler.IAsyncHandler_Compilation_iface, 1); + + WaitForSingleObject(compilation_handler.event_finished, INFINITE); + CloseHandle(compilation_handler.event_finished); + + hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, NULL); + todo_wine ok(hr == E_ILLEGAL_DELEGATE_ASSIGNMENT, "Got unexpected hr %#lx.\n", hr); + + handler = (void*)0xdeadbeef; + hr = IAsyncOperation_SpeechRecognitionCompilationResult_get_Completed(operation, &handler); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(handler == NULL, "Handler had value %p.\n", handler); + + hr = IAsyncOperation_SpeechRecognitionCompilationResult_GetResults(operation, &compilation_result); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine check_interface(compilation_result, &IID_IAgileObject, TRUE); + + hr = ISpeechRecognitionCompilationResult_get_Status(compilation_result, &result_status); + todo_wine ok(hr == S_OK, "ISpeechRecognitionCompilationResult_get_Status failed, hr %#lx.\n", hr); + todo_wine ok(result_status == SpeechRecognitionResultStatus_Success, "Got unexpected status %#x.\n", result_status); + + ref = ISpeechRecognitionCompilationResult_Release(compilation_result); + todo_wine ok(!ref , "Got unexpected ref %lu.\n", ref); + + hr = IAsyncOperation_SpeechRecognitionCompilationResult_GetResults(operation, &compilation_result); + todo_wine ok(hr == E_UNEXPECTED, "Got unexpected hr %#lx.\n", hr); + + hr = IAsyncOperation_SpeechRecognitionCompilationResult_QueryInterface(operation, &IID_IAsyncInfo, (void **)&info); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* Check if AsyncInfo and AsyncOperation share the same refcount. */ + IAsyncOperation_SpeechRecognitionCompilationResult_AddRef(operation); + todo_wine check_refcount(operation, 3); + todo_wine check_refcount(info, 3); + + IAsyncOperation_SpeechRecognitionCompilationResult_Release(operation); + todo_wine check_refcount(info, 2); + + id = 0xdeadbeef; + hr = IAsyncInfo_get_Id(info, &id); + todo_wine ok(hr == S_OK, "IAsyncInfo_get_Id failed, hr %#lx.\n", hr); + todo_wine ok(id != 0xdeadbeef, "Id was %#x.\n", id); + + async_status = 0xdeadbeef; + hr = IAsyncInfo_get_Status(info, &async_status); + todo_wine ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); + todo_wine ok(async_status == Completed, "Status was %#x.\n", async_status); + + hr = IAsyncInfo_Cancel(info); + todo_wine ok(hr == S_OK, "IAsyncInfo_Cancel failed, hr %#lx.\n", hr); + + async_status = 0xdeadbeef; + hr = IAsyncInfo_get_Status(info, &async_status); + todo_wine ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); + todo_wine ok(async_status == Completed, "Status was %#x.\n", async_status); + + hr = IAsyncInfo_Close(info); + todo_wine ok(hr == S_OK, "IAsyncInfo_Close failed, hr %#lx.\n", hr); + hr = IAsyncInfo_Close(info); + todo_wine ok(hr == S_OK, "IAsyncInfo_Close failed, hr %#lx.\n", hr); + + async_status = 0xdeadbeef; + hr = IAsyncInfo_get_Status(info, &async_status); + todo_wine ok(hr == E_ILLEGAL_METHOD_CALL, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); + todo_wine ok(async_status == AsyncStatus_Closed, "Status was %#x.\n", async_status); + + ref = IAsyncInfo_Release(info); + todo_wine ok(ref == 1, "Got unexpected ref %lu.\n", ref); + + hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, NULL); + todo_wine ok(hr == E_ILLEGAL_METHOD_CALL, "Got unexpected hr %#lx.\n", hr); + + handler = (void*)0xdeadbeef; + hr = IAsyncOperation_SpeechRecognitionCompilationResult_get_Completed(operation, &handler); + todo_wine ok(hr == E_ILLEGAL_METHOD_CALL, "Got unexpected hr %#lx.\n", hr); + + IAsyncOperation_SpeechRecognitionCompilationResult_Release(operation); + + /* Test if AsyncOperation is started immediately. */ + compilation_handler_create_static(&compilation_handler2); + compilation_handler2.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); + compilation_handler2.thread_id = GetCurrentThreadId(); + + ok(compilation_handler2.event_finished != NULL, "Finished event wasn't created.\n"); + + hr = ISpeechRecognizer_CompileConstraintsAsync(recognizer, &operation); + todo_wine ok(hr == S_OK, "ISpeechRecognizer_CompileConstraintsAsync failed, hr %#lx.\n", hr); + todo_wine check_interface(operation, &IID_IAgileObject, TRUE); + + hr = IAsyncOperation_SpeechRecognitionCompilationResult_QueryInterface(operation, &IID_IAsyncInfo, (void **)&info); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* This one can fail, if the async operation had already finished */ + compilation_result = (void*)0xdeadbeef; + hr = IAsyncOperation_SpeechRecognitionCompilationResult_GetResults(operation, &compilation_result); + todo_wine ok(hr == E_ILLEGAL_METHOD_CALL, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(compilation_result == (void*)0xdeadbeef, "Compilation result had value %p.\n", compilation_result); + + async_status = 0xdeadbeef; + hr = IAsyncInfo_get_Status(info, &async_status); + todo_wine ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); + todo_wine ok(async_status == Started || async_status == Completed, "Status was %#x.\n", async_status); + + IAsyncInfo_Release(info); + + hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, &compilation_handler2.IAsyncHandler_Compilation_iface); + todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + WaitForSingleObject(compilation_handler2.event_finished, INFINITE); + CloseHandle(compilation_handler2.event_finished); + + async_status = 0xdeadbeef; + hr = IAsyncInfo_get_Status(info, &async_status); + todo_wine ok(hr == S_OK, "IAsyncInfo_get_Status failed, hr %#lx.\n", hr); + todo_wine ok(async_status == Completed, "Status was %#x.\n", async_status); + + ref = IAsyncOperation_SpeechRecognitionCompilationResult_Release(operation); + ok(!ref, "Got unexpected ref %lu.\n", ref); + +skip_operation: ref = ISpeechContinuousRecognitionSession_Release(session); ok(ref == 1, "Got unexpected ref %lu.\n", ref); -- 2.11.4.GIT