Signed-off-by: Bernhard Kölbl <besentv(a)gmail.com>
---
v4: Fix races in tests, leaks and implement stubs. + Some rework.
---
dlls/windows.media.speech/tests/speech.c | 136 +++++++++++++++++++----
1 file changed, 112 insertions(+), 24 deletions(-)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c
index ef75178f8c1..7fca3fa6179 100644
--- a/dlls/windows.media.speech/tests/speech.c
+++ b/dlls/windows.media.speech/tests/speech.c
@@ -239,8 +239,8 @@ struct compilation_handler
IAsyncHandler_Compilation IAsyncHandler_Compilation_iface;
LONG ref;
+ HANDLE event_block;
HANDLE event_finished;
- BOOLEAN sleeping;
DWORD thread_id;
};
@@ -290,7 +290,9 @@ HRESULT WINAPI compilation_handler_Invoke( IAsyncHandler_Compilation *iface,
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);
+ /* Block handler until event is set. */
+ if (impl->event_block) WaitForSingleObject(impl->event_block, INFINITE);
+ /* Signal finishing of the handler. */
if (impl->event_finished) SetEvent(impl->event_finished);
return S_OK;
@@ -813,6 +815,39 @@ static void test_VoiceInformation(void)
RoUninitialize();
}
+struct async_operation_block_param
+{
+ IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult *handler;
+ IAsyncOperation_SpeechRecognitionCompilationResult *operation;
+};
+
+static DWORD WINAPI async_operation_block_thread(void *arg)
+{
+ struct async_operation_block_param *param = arg;
+ HRESULT hr;
+
+ hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(param->operation, param->handler);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ return 0;
+}
+
+struct async_operation_close_param
+{
+ IAsyncInfo *info;
+};
+
+static DWORD WINAPI async_operation_close_thread(void *arg)
+{
+ struct async_operation_close_param *param = arg;
+ HRESULT hr;
+
+ hr = IAsyncInfo_Close(param->info);
+ ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ return 0;
+}
+
static void test_SpeechRecognizer(void)
{
static const WCHAR *speech_recognition_name = L"Windows.Media.SpeechRecognition.SpeechRecognizer";
@@ -824,21 +859,24 @@ static void test_SpeechRecognizer(void)
ISpeechRecognizerFactory *sr_factory = NULL;
ISpeechRecognizerStatics *sr_statics = NULL;
ISpeechRecognizerStatics2 *sr_statics2 = NULL;
- ISpeechRecognizer *recognizer = NULL;
+ ISpeechRecognizer *recognizer = NULL, *recognizer_2 = NULL;
ISpeechRecognizer2 *recognizer2 = NULL;
IActivationFactory *factory = NULL;
- IInspectable *inspectable = NULL;
+ IInspectable *inspectable = NULL, *inspectable_2 = NULL;
IClosable *closable = NULL;
ILanguage *language = NULL;
IAsyncInfo *info = NULL;
+ struct compilation_handler compilation_handler, compilation_handler2, compilation_handler3;
struct completed_event_handler completed_handler;
struct recognition_result_handler result_handler;
- struct compilation_handler compilation_handler;
- struct compilation_handler compilation_handler2;
+ struct async_operation_block_param block_param;
+ struct async_operation_close_param close_param;
SpeechRecognitionResultStatus result_status;
EventRegistrationToken token = { .value = 0 };
+ HANDLE close_thread, blocked_thread;
AsyncStatus async_status;
HSTRING hstr, hstr_lang;
+ DWORD thread_status;
HRESULT hr;
UINT32 id;
LONG ref;
@@ -945,6 +983,7 @@ static void test_SpeechRecognizer(void)
ok(ref == 1, "Got unexpected ref %lu.\n", ref);
compilation_handler_create_static(&compilation_handler);
+ compilation_handler.event_block = NULL;
compilation_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL);
compilation_handler.thread_id = GetCurrentThreadId();
@@ -965,9 +1004,8 @@ static void test_SpeechRecognizer(void)
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);
+ todo_wine ok(!WaitForSingleObject(compilation_handler.event_finished, 1000), "Wait for event_finished failed.\n");
CloseHandle(compilation_handler.event_finished);
hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, NULL);
@@ -976,7 +1014,7 @@ static void test_SpeechRecognizer(void)
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);
+ todo_wine ok(handler == NULL || broken(handler != NULL), "Handler had value %p.\n", handler); /* Broken on Win10 1507 x32... */
hr = IAsyncOperation_SpeechRecognitionCompilationResult_GetResults(operation, &compilation_result);
todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
@@ -1048,7 +1086,7 @@ static void test_SpeechRecognizer(void)
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");
+ todo_wine 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);
@@ -1057,23 +1095,10 @@ static void test_SpeechRecognizer(void)
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);
+ todo_wine ok(!WaitForSingleObject(compilation_handler2.event_finished, 1000), "Wait for event_finished failed.\n");
CloseHandle(compilation_handler2.event_finished);
async_status = 0xdeadbeef;
@@ -1081,10 +1106,73 @@ static void test_SpeechRecognizer(void)
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 = IAsyncInfo_Release(info);
+ todo_wine ok(ref == 1, "Got unexpected ref %lu.\n", ref);
+ ref = IAsyncOperation_SpeechRecognitionCompilationResult_Release(operation);
+ todo_wine ok(!ref, "Got unexpected ref %lu.\n", ref);
+
+ /* Test if AsyncInfo_Close waits for the handler to finish. */
+ hr = RoActivateInstance(hstr, &inspectable_2);
+ todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ hr = IInspectable_QueryInterface(inspectable_2, &IID_ISpeechRecognizer, (void **)&recognizer_2);
+ todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ compilation_handler_create_static(&compilation_handler3);
+ compilation_handler3.event_block = CreateEventW(NULL, FALSE, FALSE, NULL);
+ compilation_handler3.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL);
+ compilation_handler3.thread_id = GetCurrentThreadId();
+
+ todo_wine ok(compilation_handler3.event_finished != NULL, "Finished event wasn't created.\n");
+
+ hr = ISpeechRecognizer_CompileConstraintsAsync(recognizer_2, &operation);
+ todo_wine ok(hr == S_OK, "ISpeechRecognizer_CompileConstraintsAsync failed, hr %#lx.\n", hr);
+
+ block_param.handler = &compilation_handler3.IAsyncHandler_Compilation_iface;
+ block_param.operation = operation;
+ blocked_thread = CreateThread(NULL, 0, async_operation_block_thread, &block_param, 0, NULL);
+ thread_status = WaitForSingleObject(blocked_thread, 1000);
+ todo_wine ok(thread_status == WAIT_TIMEOUT || broken(thread_status == WAIT_OBJECT_0), "Wait for block_thread didn't time out.\n"); /* Broken on Win10 1507 x32... */
+
+ if (thread_status == WAIT_TIMEOUT)
+ {
+ todo_wine ok(compilation_handler3.ref == 3, "Got unexpected ref %lu.\n", compilation_handler3.ref);
+ todo_wine check_refcount(operation, 3);
+
+ hr = IAsyncOperation_SpeechRecognitionCompilationResult_QueryInterface(operation, &IID_IAsyncInfo, (void **)&info);
+ todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+
+ close_param.info = info;
+ close_thread = CreateThread(NULL, 0, async_operation_close_thread, &close_param, 0, NULL);
+ todo_wine ok(!WaitForSingleObject(close_thread, 100), "Wait for close_thread failed.\n");
+
+ CloseHandle(close_thread);
+ }
+
+ SetEvent(compilation_handler3.event_block);
+ todo_wine ok(!WaitForSingleObject(compilation_handler3.event_finished, 500), "Wait for event_finished failed.\n");
+ todo_wine ok(!WaitForSingleObject(blocked_thread, 1000), "Wait for block_thread failed.\n");
+
+ CloseHandle(blocked_thread);
+ CloseHandle(compilation_handler3.event_block);
+ CloseHandle(compilation_handler3.event_finished);
+
+ ref = IAsyncInfo_Release(info);
+ todo_wine ok(ref == 1, "Got unexpected ref %lu.\n", ref);
+
skip_operation:
ref = IAsyncOperation_SpeechRecognitionCompilationResult_Release(operation);
ok(!ref, "Got unexpected ref %lu.\n", ref);
+ if (recognizer_2)
+ {
+ ref = ISpeechRecognizer_Release(recognizer_2);
+ ok(ref == 1, "Got unexpected ref %lu.\n", ref);
+
+ ref = IInspectable_Release(inspectable_2);
+ ok(!ref, "Got unexpected ref %lu.\n", ref);
+ }
+
ref = ISpeechContinuousRecognitionSession_Release(session);
ok(ref == 1, "Got unexpected ref %lu.\n", ref);
--
2.35.1