From 67a644b56f40dc96a24b71f38aa239c306a19051 Mon Sep 17 00:00:00 2001 From: Suyeon Hwang Date: Tue, 3 Jan 2023 12:33:06 +0900 Subject: [PATCH] Fix rpc port creation timing - Issue: Even if the tidl connection is out, client lib may ignore connect request. And also, the tidl can not re-connect synchronously right after the tidl is disconnected. - Solution: TIDL connect request is up to connected flag variable in tidl info structure. However, the connected flag is only set by connected, rejected, and disconnected event callback. And also, tidl can not re-connect synchronously right after the disconnect() of tidl is invoked. So, current client lib can not connect to stub in some specific situation. To solve this issue, this patch changes the rpc port creation timing. Through this patch, tts_tidl module always reset the rpc port when the io error occurs. And also, tts_tidl module can assure the connection by creating new rpc port when the client want to prepare. Change-Id: I8cfc143aebb331389d1fb205b7526b43f0301fee Signed-off-by: Suyeon Hwang --- client/tts_tidl.c | 221 +++++++++++++++++++++++++++----------------- tests/src/tts_unittests.cpp | 2 + 2 files changed, 140 insertions(+), 83 deletions(-) diff --git a/client/tts_tidl.c b/client/tts_tidl.c index dd10bc8..1cca1e9 100644 --- a/client/tts_tidl.c +++ b/client/tts_tidl.c @@ -195,24 +195,6 @@ static void __get_engine_app_id(int size, char* app_id) SLOG(LOG_INFO, TAG_TTSC, "engine app id : %s", app_id); } -static rpc_port_proxy_tts_h __create_rpc_port(unsigned int uid, const char* engine_app_id) -{ - rpc_port_proxy_tts_callback_s rpc_callback = { - .connected = __on_connected, - .disconnected = __on_disconnected, - .rejected = __on_rejected - }; - - rpc_port_proxy_tts_h handle = NULL; - uintptr_t ptr_uid = uid; - if (RPC_PORT_ERROR_NONE != rpc_port_proxy_tts_create(engine_app_id, &rpc_callback, (void*)ptr_uid, &handle)) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create proxy"); - return NULL; - } - - return handle; -} - int tts_tidl_open_connection(unsigned int uid) { SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_open_connection"); @@ -226,21 +208,31 @@ int tts_tidl_open_connection(unsigned int uid) return TTS_ERROR_OUT_OF_MEMORY; } - char engine_app_id[TTS_ENGINE_APPID_LEN] = {0, }; - __get_engine_app_id(TTS_ENGINE_APPID_LEN, engine_app_id); + info->uid = uid; + g_tidl_infos = g_list_append(g_tidl_infos, info); + + SLOG(LOG_ERROR, TAG_TTSC, "[TIDL] uid(%u)", uid); + return TTS_ERROR_NONE; +} + +static inline int __destroy_rpc_port(tts_tidl_info_s* info) +{ + RETVM_IF(NULL == info->rpc_h, TTS_ERROR_NONE, "[TIDL] Handle is already destroyed"); - info->rpc_h = __create_rpc_port(uid, engine_app_id); - if (NULL == info->rpc_h) { - SLOG(LOG_ERROR, TAG_TTSC, "[TIDL ERROR] Fail to create proxy"); - free(info); + if (RPC_PORT_ERROR_NONE != rpc_port_proxy_tts_destroy(info->rpc_h)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy handle"); return TTS_ERROR_OPERATION_FAILED; } + info->rpc_h = NULL; + info->notify_cb_h = NULL; - info->engine_app_id = strdup(engine_app_id); - info->uid = uid; - g_tidl_infos = g_list_append(g_tidl_infos, info); + free(info->engine_app_id); + info->engine_app_id = NULL; + + info->register_callback_invoked = false; + info->connection_requesting = false; + info->connected = false; - SLOG(LOG_ERROR, TAG_TTSC, "[TIDL] uid(%u) rpc_h(%p), engine_app_id(%s)", uid, info->rpc_h, info->engine_app_id); return TTS_ERROR_NONE; } @@ -254,14 +246,11 @@ int tts_tidl_close_connection(unsigned int uid) tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - if (RPC_PORT_ERROR_NONE != rpc_port_proxy_tts_destroy(info->rpc_h)) { + if (TTS_ERROR_NONE != __destroy_rpc_port(info)) { SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to disconnect"); return TTS_ERROR_OPERATION_FAILED; } - info->rpc_h = NULL; - info->notify_cb_h = NULL; - free(info->engine_app_id); info->engine_app_id = NULL; @@ -333,6 +322,78 @@ static int __invoke_register_callback(int pid, tts_mode_e mode, int registered_e return TTS_ERROR_NONE; } +static inline bool __is_rpc_port_valid(tts_tidl_info_s* info, const char* engine_id) +{ + if (NULL == info->rpc_h || NULL == info->engine_app_id) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Handle is empty"); + return false; + } + + if (NULL == engine_id) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine ID is null"); + return false; + } + + if (0 != strncmp(info->engine_app_id, engine_id, TTS_ENGINE_APPID_LEN)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Engine id is not current engine"); + return false; + } + + return true; +} + +static inline int __create_rpc_port(tts_tidl_info_s* info, const char* engine_id) +{ + RETVM_IF(NULL != info->rpc_h, TTS_ERROR_NONE, "[TIDL] Handle is already created"); + + rpc_port_proxy_tts_callback_s rpc_callback = { + .connected = __on_connected, + .disconnected = __on_disconnected, + .rejected = __on_rejected + }; + + rpc_port_proxy_tts_h handle = NULL; + uintptr_t ptr_uid = info->uid; + if (RPC_PORT_ERROR_NONE != rpc_port_proxy_tts_create(engine_id, &rpc_callback, (void*)ptr_uid, &handle) || NULL == handle) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create proxy"); + return TTS_ERROR_OPERATION_FAILED; + } + + info->rpc_h = handle; + info->engine_app_id = strdup(engine_id); + + return TTS_ERROR_NONE; +} + +static int __reset_rpc_port(tts_tidl_info_s* info, const char* engine_id) +{ + if (TTS_ERROR_NONE != __destroy_rpc_port(info)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy old rpc port"); + return TTS_ERROR_OPERATION_FAILED; + } + + if (TTS_ERROR_NONE != __create_rpc_port(info, engine_id)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create new rpc port"); + return TTS_ERROR_OPERATION_FAILED; + } + + SLOG(LOG_INFO, TAG_TTSC, "[TIDL] Reset rpc port. uid(%u). engine ID(%s)", info->uid, engine_id); + return TTS_ERROR_NONE; +} + +static int __check_and_prepare_rpc_port(tts_tidl_info_s* info) +{ + char engine_id[TTS_ENGINE_APPID_LEN] = {0, }; + __get_engine_app_id(TTS_ENGINE_APPID_LEN, engine_id); + + if (__is_rpc_port_valid(info, engine_id)) { + SLOG(LOG_INFO, TAG_TTSC, "[TIDL] Current rpc port is valid"); + return TTS_ERROR_NONE; + } + + return __reset_rpc_port(info, engine_id); +} + int tts_tidl_request_hello(unsigned int uid, tts_mode_e mode, int registered_event_mask) { SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_hello"); @@ -343,26 +404,9 @@ int tts_tidl_request_hello(unsigned int uid, tts_mode_e mode, int registered_eve tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - char engine_app_id[TTS_ENGINE_APPID_LEN] = {0, }; - __get_engine_app_id(TTS_ENGINE_APPID_LEN, engine_app_id); - - if (NULL == info->engine_app_id || 0 != strncmp(info->engine_app_id, engine_app_id, TTS_ENGINE_APPID_LEN)) { - SLOG(LOG_ERROR, TAG_TTSC, "[TIDL] tts engine is changed from (%s) to (%s)", info->engine_app_id, engine_app_id); - if (RPC_PORT_ERROR_NONE != rpc_port_proxy_tts_destroy(info->rpc_h)) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy old rpc_port"); - return TTS_ERROR_OPERATION_FAILED; - } - info->notify_cb_h = NULL; - info->register_callback_invoked = false; - - info->rpc_h = __create_rpc_port(uid, engine_app_id); - if (NULL == info->rpc_h) { - SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to create proxy"); - return TTS_ERROR_OPERATION_FAILED; - } - free(info->engine_app_id); - info->engine_app_id = strdup(engine_app_id); - info->connection_requesting = false; + if (TTS_ERROR_NONE != __check_and_prepare_rpc_port(info)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to prepare rpc port"); + return TTS_ERROR_OPERATION_FAILED; } if (!info->connected) { @@ -392,10 +436,12 @@ static int __request_tidl_connect_sync(tts_tidl_info_s* info) return TTS_ERROR_OPERATION_FAILED; } -static int __convert_unhandled_error(int ret) +static int __convert_and_handle_tidl_error(int ret, tts_tidl_info_s* info) { switch (ret) { case RPC_PORT_ERROR_IO_ERROR: + SLOG(LOG_INFO, TAG_TTSC, "[INFO] IO error occurs. Destroy old rpc port"); + __destroy_rpc_port(info); return TTS_ERROR_IO_ERROR; case RPC_PORT_ERROR_OUT_OF_MEMORY: @@ -423,7 +469,7 @@ static int __invoke_register_callback_sync(int pid, tts_tidl_info_s* info) ret = rpc_port_proxy_tts_invoke_register_cb_sync(info->rpc_h, pid, info->uid, info->notify_cb_h); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } info->register_callback_invoked = false; @@ -445,6 +491,11 @@ int tts_tidl_request_hello_sync(unsigned int uid) tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); + if (TTS_ERROR_NONE != __check_and_prepare_rpc_port(info)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to prepare rpc port"); + return TTS_ERROR_OPERATION_FAILED; + } + if (!info->connected) { SLOG(LOG_WARN, TAG_TTSC, "[WARNNING] Stub is not Connected. Try to connect.."); int ret = __request_tidl_connect_sync(info); @@ -476,13 +527,13 @@ int tts_tidl_request_initialize(unsigned int uid, tts_mode_e mode, int registere tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); bool temp; int ret = rpc_port_proxy_tts_invoke_initialize(info->rpc_h, client->pid, uid, (int)mode, registered_event_mask, &temp); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts initialize : ret(%d/%s)", ret, get_error_message(ret)); @@ -499,28 +550,34 @@ int tts_tidl_request_initialize(unsigned int uid, tts_mode_e mode, int registere int tts_tidl_request_finalize(unsigned int uid) { - SLOG(LOG_DEBUG, TAG_TTSC, "[TIDL] tts_tidl_request_finalize"); + SLOG(LOG_INFO, TAG_TTSC, "[TIDL] tts_tidl_request_finalize"); tts_client_s* client = tts_client_get_by_uid(uid); - RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client"); + RETVM_IF(NULL == client, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get client"); tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); int ret = rpc_port_proxy_tts_invoke_finalize(info->rpc_h, uid); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } - SLOG(LOG_ERROR, TAG_TTSC, ">>>> Request tts finalize. ret(%d/%s)", ret, get_error_message(ret)); if (TTS_ERROR_NONE != ret) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to tts finalize. ret(%d/%s)", ret, get_error_message(ret)); return ret; } tts_client_set_start_listening(uid, false); + if (TTS_ERROR_NONE != __destroy_rpc_port(info)) { + SLOG(LOG_ERROR, TAG_TTSC, "[ERROR] Fail to destroy rpc port. ret(%d)", ret); + return TTS_ERROR_OPERATION_FAILED; + } + SLOG(LOG_ERROR, TAG_TTSC, ">>>> Success tts finalize. uid(%u)", uid); + return TTS_ERROR_NONE; } @@ -536,14 +593,13 @@ int tts_tidl_request_add_text(unsigned int uid, const char* text, const char* la RETVM_IF(NULL == text || NULL == lang, TTS_ERROR_INVALID_PARAMETER, "Input parameter is NULL"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); - + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); const char *not_null_credential = NULL == credential ? "NULL" : credential; int ret = rpc_port_proxy_tts_invoke_add_text(info->rpc_h, uid, text, lang, vctype, speed, uttid, not_null_credential); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { @@ -566,13 +622,12 @@ int tts_tidl_request_set_private_data(unsigned int uid, const char* key, const c RETVM_IF(NULL == key || NULL == data, TTS_ERROR_INVALID_PARAMETER, "Input parameter is NULL"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); - + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); int ret = rpc_port_proxy_tts_invoke_set_private(info->rpc_h, uid, key, data); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { @@ -595,13 +650,13 @@ int tts_tidl_request_get_private_data(unsigned int uid, const char* key, char** RETVM_IF(NULL == key || NULL == data, TTS_ERROR_INVALID_PARAMETER, "Input parameter is NULL"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); char *tmp = NULL; int ret = rpc_port_proxy_tts_invoke_get_private(info->rpc_h, uid, key, &tmp); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { @@ -626,13 +681,13 @@ int tts_tidl_request_play(unsigned int uid, const char* credential) tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); const char *not_null_credential = NULL == credential ? "NULL" : credential; int ret = rpc_port_proxy_tts_invoke_play(info->rpc_h, uid, not_null_credential); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { @@ -655,12 +710,12 @@ int tts_tidl_request_stop(unsigned int uid) tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); int ret = rpc_port_proxy_tts_invoke_stop(info->rpc_h, uid); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { @@ -682,12 +737,12 @@ int tts_tidl_request_pause(unsigned int uid) tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); int ret = rpc_port_proxy_tts_invoke_pause(info->rpc_h, uid); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { @@ -710,12 +765,12 @@ int tts_tidl_request_play_pcm(unsigned int uid) tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); int ret = rpc_port_proxy_tts_invoke_play_pcm(info->rpc_h, uid); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { @@ -738,12 +793,12 @@ int tts_tidl_request_stop_pcm(unsigned int uid) tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); int ret = rpc_port_proxy_tts_invoke_stop_pcm(info->rpc_h, uid); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { @@ -766,7 +821,7 @@ int tts_tidl_request_add_pcm(unsigned int uid, int event, const char* data, int tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); rpc_port_proxy_array_char_h pcm_data = NULL; rpc_port_proxy_array_char_create(&pcm_data); @@ -785,7 +840,7 @@ int tts_tidl_request_add_pcm(unsigned int uid, int event, const char* data, int rpc_port_proxy_array_char_destroy(pcm_data); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { @@ -808,13 +863,13 @@ int tts_tidl_request_get_service_state(unsigned int uid, tts_service_state_e* se tts_tidl_info_s* info = __get_tidl_info_s(uid); RETVM_IF(NULL == info, TTS_ERROR_INVALID_PARAMETER, "[ERROR] Fail to get tidl info"); - RETVM_IF(!info->connected, TTS_ERROR_OPERATION_FAILED, "[ERROR] Not Connected"); + RETVM_IF(!info->connected, TTS_ERROR_IO_ERROR, "[ERROR] Not Connected"); int state = (int)TTS_SERVICE_STATE_READY; int ret = rpc_port_proxy_tts_invoke_get_service_state(info->rpc_h, uid, &state); int exception = get_last_result(); if (RPC_PORT_ERROR_NONE != exception) { - ret = __convert_unhandled_error(exception); + ret = __convert_and_handle_tidl_error(exception, info); } if (TTS_ERROR_NONE != ret) { diff --git a/tests/src/tts_unittests.cpp b/tests/src/tts_unittests.cpp index b629c78..e6ef3f9 100644 --- a/tests/src/tts_unittests.cpp +++ b/tests/src/tts_unittests.cpp @@ -675,6 +675,7 @@ TEST_F(TTSTest, utc_tts_prepare_p2) EXPECT_EQ(__is_state_changed(TTS_STATE_READY, 5), true); EXPECT_EQ(tts_unprepare(g_tts), TTS_ERROR_NONE); + sleep(1); g_current_state = TTS_STATE_CREATED; EXPECT_EQ(tts_prepare(g_tts), TTS_ERROR_NONE); @@ -823,6 +824,7 @@ TEST_F(TTSTest, utc_tts_prepare_sync_p2) EXPECT_EQ(state, TTS_STATE_READY); EXPECT_EQ(tts_unprepare(g_tts), TTS_ERROR_NONE); + sleep(1); state = TTS_STATE_CREATED; EXPECT_EQ(tts_prepare_sync(g_tts), TTS_ERROR_NONE); -- 2.7.4