[PATCH 6/6] windows.media.speech/tests: Add tests to check if IAsyncInfo_Close is non blocking.

Rémi Bernon rbernon at codeweavers.com
Thu Apr 21 10:06:30 CDT 2022


On 4/20/22 21:34, Bernhard Kölbl wrote:
> Signed-off-by: Bernhard Kölbl <besentv at gmail.com>
> ---
>   dlls/windows.media.speech/tests/speech.c | 99 ++++++++++++++++++++----
>   1 file changed, 83 insertions(+), 16 deletions(-)
> 
> diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c
> index 908e04bb0c3..3766572177f 100644
> --- a/dlls/windows.media.speech/tests/speech.c
> +++ b/dlls/windows.media.speech/tests/speech.c
> @@ -247,8 +247,8 @@ struct compilation_handler
>       IAsyncHandler_Compilation IAsyncHandler_Compilation_iface;
>       LONG ref;
>   
> +    HANDLE event_block;
>       HANDLE event_finished;
> -    BOOLEAN sleeping;
>       DWORD thread_id;
>   };
>   
> @@ -298,8 +298,10 @@ 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);
> +    /* Signal finishing of the handler. */
>       if (impl->event_finished) SetEvent(impl->event_finished);
> +    /* Block handler until event is set. */
> +    if (impl->event_block) WaitForSingleObject(impl->event_block, INFINITE);
>   
>       return S_OK;
>   }
> @@ -821,6 +823,23 @@ 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;
> +}
> +
>   static void test_SpeechRecognizer(void)
>   {
>       static const WCHAR *speech_recognition_name = L"Windows.Media.SpeechRecognition.SpeechRecognizer";
> @@ -836,17 +855,17 @@ static void test_SpeechRecognizer(void)
>       ISpeechRecognizer2 *recognizer2 = NULL;
>       IActivationFactory *factory = NULL;
>       IInspectable *inspectable = 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;
>       SpeechRecognitionResultStatus result_status;
>       EventRegistrationToken token = { .value = 0 };
>       AsyncStatus async_status;
>       HSTRING hstr, hstr_lang;
> +    HANDLE blocked_thread;
>       HRESULT hr;
>       UINT32 id;
>       LONG ref;
> @@ -918,11 +937,16 @@ static void test_SpeechRecognizer(void)
>           hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechRecognizer2, (void **)&recognizer2);
>           ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
>   
> +        check_interface(inspectable, &IID_IClosable, TRUE);
> +
>           hr = ISpeechRecognizer2_get_ContinuousRecognitionSession(recognizer2, &session);
>           ok(hr == S_OK, "ISpeechRecognizer2_get_ContinuousRecognitionSession failed, hr %#lx.\n", hr);
>           check_refcount(session, 2);
>           check_refcount(inspectable, 3);
>   
> +        ref = ISpeechRecognizer2_Release(recognizer2);
> +        ok(ref == 2, "Got unexpected ref %lu.\n", ref);
> +
>           hr = ISpeechContinuousRecognitionSession_add_Completed(session, NULL, &token);
>           ok(hr == E_INVALIDARG, "ISpeechContinuousRecognitionSession_add_ResultGenerated failed, hr %#lx.\n", hr);
>   
> @@ -947,6 +971,9 @@ static void test_SpeechRecognizer(void)
>           hr = ISpeechContinuousRecognitionSession_remove_ResultGenerated(session, token);
>           ok(hr == S_OK, "ISpeechContinuousRecognitionSession_remove_ResultGenerated failed, hr %#lx.\n", hr);
>   
> +        ref = ISpeechContinuousRecognitionSession_Release(session);
> +        ok(ref == 1, "Got unexpected ref %lu.\n", ref);
> +
>           hr = ISpeechRecognizer_get_Constraints(recognizer, &constraints);
>           ok(hr == S_OK, "ISpeechContinuousRecognitionSession_get_Constraints failed, hr %#lx.\n", hr);
>   
> @@ -1078,22 +1105,62 @@ static void test_SpeechRecognizer(void)
>   
>           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);
> +        todo_wine ok(!ref, "Got unexpected ref %lu.\n", ref);
>   
> -        ref = ISpeechContinuousRecognitionSession_Release(session);
> -        ok(ref == 1, "Got unexpected ref %lu.\n", ref);
> +        ref = ISpeechRecognizer_Release(recognizer);
> +        todo_wine ok(ref == 1, "Got unexpected ref %lu.\n", ref);
>   
> -        hr = IInspectable_QueryInterface(inspectable, &IID_IClosable, (void **)&closable);
> -        ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
> +        ref = IInspectable_Release(inspectable);
> +        todo_wine ok(!ref, "Got unexpected ref %lu.\n", ref);
>   
> -        ref = IClosable_Release(closable);
> -        ok(ref == 3, "Got unexpected ref %lu.\n", ref);
> +        /* Test if AsyncInfo_Close waits for the handler to finish. */
> +        hr = RoActivateInstance(hstr, &inspectable);
> +        todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
>   
> -        ref = ISpeechRecognizer2_Release(recognizer2);
> -        ok(ref == 2, "Got unexpected ref %lu.\n", ref);
> +        hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechRecognizer, (void **)&recognizer);
> +        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, &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);
> +
> +        todo_wine ok(!WaitForSingleObject(compilation_handler3.event_finished, 1000), "Wait for event_finished failed.\n");
> +


According to the results, it seems like this one is not big enough? I 
think thread creation can be unusually slow, and sometimes it's best to 
create them upfront, and instead use an event to start a test. It 
complicates things a bit though, maybe just increasing the timeout to 5s 
would be enough.


> +        todo_wine ok(WaitForSingleObject(blocked_thread, 1000) == WAIT_TIMEOUT, "Wait for block_thread didn't time out.\n");


If you expect a timeout, I think it's best to use lower values, like 
100ms, otherwise it's always going to wait 1s and slow down the entire 
test (1s is not much but they pile up).


> +
> +        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);
> +
> +        hr = IAsyncInfo_Close(info); /* If IAsyncInfo_Close would wait for the handler to finish, the test would get stuck here. */
> +        todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
> +
> +        SetEvent(compilation_handler3.event_block);
> +        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);
>   
>           ref = ISpeechRecognizer_Release(recognizer);
>           ok(ref == 1, "Got unexpected ref %lu.\n", ref);


I still don't see why you need another unique compilation_handler 
variable, but as there's already compilation_handler2 I'm going to 
ignore it.

Looks good otherwise.

-- 
Rémi Bernon <rbernon at codeweavers.com>



More information about the wine-devel mailing list