--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <app_manager_extension.h>
+#include <tzplatform_config.h>
+#include <system_info.h>
+#include <vconf.h>
+#include <gtest/gtest.h>
+#include <Ecore.h>
+
+#include "test_util.h"
+
+
+SttTestUtility::SttTestUtility()
+{
+ mHandle = nullptr;
+ mCurrentState = STT_STATE_CREATED;
+ mErrorOccured = false;
+ mResultReceived = false;
+ mErrorMessage = nullptr;
+
+ mPCMData = nullptr;
+ mPCMSize = 0;
+
+ CreateHandle();
+}
+
+SttTestUtility::~SttTestUtility()
+{
+ UnsetTestMode();
+ DestroyHandle();
+
+ free(mErrorMessage);
+ mErrorMessage = nullptr;
+
+ free(mPCMData);
+ mPCMData = nullptr;
+ mPCMSize = 0;
+}
+
+void SttTestUtility::StateChangedCallback(stt_h tts, stt_state_e previous, stt_state_e current, void *user_data)
+{
+ auto instance = reinterpret_cast<SttTestUtility *>(user_data);
+ instance->mCurrentState = current;
+}
+
+void SttTestUtility::ErrorCallback(stt_h stt, stt_error_e reason, void *user_data)
+{
+ auto instance = reinterpret_cast<SttTestUtility *>(user_data);
+ instance->mErrorOccured = true;
+
+ char *errorMessage = nullptr;
+ ASSERT_EQ(stt_get_error_message(instance->mHandle, &errorMessage), STT_ERROR_NONE);
+
+ free(instance->mErrorMessage);
+ instance->mErrorMessage = errorMessage;
+}
+
+void SttTestUtility::RecognitionResultCallback(stt_h stt, stt_result_event_e event, const char** data, int data_count, const char* msg, void *user_data)
+{
+ auto instance = reinterpret_cast<SttTestUtility *>(user_data);
+ instance->mResultReceived = true;
+}
+
+
+void SttTestUtility::TerminateCurrentEngine()
+{
+ char* engineId = vconf_get_str(VCONFKEY_STT_ENGINE_DEFAULT);
+
+ app_context_h context = nullptr;
+ app_manager_get_app_context(engineId, &context);
+ free(engineId);
+
+ ASSERT_NE(context, nullptr);
+
+ EXPECT_EQ(app_manager_terminate_app(context), APP_MANAGER_ERROR_NONE);
+ EXPECT_EQ(app_context_destroy(context), APP_MANAGER_ERROR_NONE);
+}
+
+void SttTestUtility::WaitUntilEngineTerminated(int duration)
+{
+ auto engineChcker = [](void) {
+ bool is_running = false;
+
+ char* engineId = vconf_get_str(VCONFKEY_STT_ENGINE_DEFAULT);
+ app_manager_is_running(engineId, &is_running);
+ free(engineId);
+
+ return !is_running;
+ };
+
+ WaitCondtion(engineChcker, duration);
+}
+
+bool SttTestUtility::IsFeatureSupported()
+{
+ bool isSttSupported = false;
+ if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool("http://tizen.org/feature/speech.recognition", &isSttSupported)) {
+ return false;
+ }
+
+ bool isMicSupported = false;
+ if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool("http://tizen.org/feature/microphone", &isMicSupported)) {
+ return false;
+ }
+
+ return isSttSupported && isMicSupported;
+}
+
+void SttTestUtility::GetTestPCMData()
+{
+ static const char* PCM_PATH = tzplatform_mkpath(tzplatform_getid("TZ_SYS_RO_APP"), "/org.tizen.stt-unittests/res/test_pcm.dat");
+
+ FILE* fp_in = fopen(PCM_PATH, "rb");
+ if (fp_in == nullptr) {
+ return;
+ }
+
+ fseek(fp_in, 0, SEEK_END);
+ long size = ftell(fp_in);
+ fseek(fp_in, 0, SEEK_SET);
+ if (size <= 0) {
+ fclose(fp_in);
+ return;
+ }
+
+ char* data = reinterpret_cast<char *>(calloc(sizeof(char), size));
+ if (NULL == data) {
+ fclose(fp_in);
+ return;
+ }
+
+ size_t read_size = fread(data, sizeof(char), size, fp_in);
+ fclose(fp_in);
+
+ if (read_size <= 0) {
+ free(data);
+ return;
+ }
+
+ mPCMSize = size;
+ mPCMData = data;
+}
+
+void SttTestUtility::CreateHandle()
+{
+ if (IsFeatureSupported() == false) {
+ mHandle = nullptr;
+ return;
+ }
+
+ stt_create(&mHandle);
+ ASSERT_NE(mHandle, nullptr);
+
+ EXPECT_EQ(stt_set_state_changed_cb(mHandle, StateChangedCallback, this), STT_ERROR_NONE);
+ EXPECT_EQ(stt_set_error_cb(mHandle, ErrorCallback, this), STT_ERROR_NONE);
+}
+
+void SttTestUtility::DestroyHandle()
+{
+ if (nullptr != mHandle) {
+ EXPECT_EQ(stt_destroy(mHandle), STT_ERROR_NONE);
+ mHandle = nullptr;
+ }
+}
+
+void SttTestUtility::SetTestMode()
+{
+ stt_state_e state = STT_STATE_CREATED;
+ ASSERT_EQ(stt_get_state(mHandle, &state), STT_ERROR_NONE);
+ ASSERT_EQ(state, STT_STATE_READY);
+ EXPECT_EQ(stt_set_private_data(mHandle, "stt_verification", "true"), STT_ERROR_NONE);
+}
+
+void SttTestUtility::UnsetTestMode()
+{
+ stt_state_e state = STT_STATE_CREATED;
+ stt_get_state(mHandle, &state);
+ if (STT_STATE_READY != state) {
+ return;
+ }
+
+ stt_set_private_data(mHandle, "stt_verification", "false");
+}
+
+bool SttTestUtility::IsStateChanged(stt_state_e targetState, int duration)
+{
+ auto stateChecker = std::bind([](SttTestUtility *instance, stt_state_e target) {
+ return target == instance->mCurrentState;
+ }, this, targetState);
+
+ return WaitCondtion(stateChecker, duration);
+}
+
+bool SttTestUtility::IsErrorOccurring(int duration)
+{
+ auto errorChecker = std::bind([](SttTestUtility *instance) {
+ return instance->mErrorOccured;
+ }, this);
+
+ return WaitCondtion(errorChecker, duration);
+}
+
+bool SttTestUtility::IsResultReceived(int duration)
+{
+ auto resultChecker = std::bind([](SttTestUtility *instance) {
+ return instance->mResultReceived;
+ }, this);
+
+ return WaitCondtion(resultChecker, duration);
+}
+
+bool SttTestUtility::Prepare()
+{
+ stt_state_e state = STT_STATE_CREATED;
+ stt_get_state(mHandle, &state);
+ if (STT_STATE_CREATED != state) {
+ return false;
+ }
+
+ stt_prepare(mHandle);
+ return IsStateChanged(STT_STATE_READY, 5);
+}
+
+bool SttTestUtility::Unprepare()
+{
+ stt_state_e state = STT_STATE_CREATED;
+ stt_get_state(mHandle, &state);
+ if (STT_STATE_READY != state) {
+ return false;
+ }
+
+ stt_unprepare(mHandle);
+ return IsStateChanged(STT_STATE_CREATED, 5);
+}
+
+bool SttTestUtility::Start(const char* language, const char* type)
+{
+ EXPECT_EQ(stt_start(mHandle, language, type), STT_ERROR_NONE);
+ return IsStateChanged(STT_STATE_RECORDING, 5);
+}
+
+bool SttTestUtility::Stop()
+{
+ EXPECT_EQ(stt_stop(mHandle), STT_ERROR_NONE);
+ return IsStateChanged(STT_STATE_PROCESSING, 5);
+}
+
+bool SttTestUtility::StartAudioStreaming(const char* language, const char* type)
+{
+ EXPECT_EQ(stt_start_audio_streaming(mHandle, language, type), STT_ERROR_NONE);
+ return IsStateChanged(STT_STATE_RECORDING, 5);
+}
+
+bool SttTestUtility::StopAudioStreaming()
+{
+ EXPECT_EQ(stt_stop_audio_streaming(mHandle), STT_ERROR_NONE);
+ return IsStateChanged(STT_STATE_PROCESSING, 5);
+}
+
+bool SttTestUtility::Cancel()
+{
+ stt_state_e state = STT_STATE_CREATED;
+ stt_get_state(mHandle, &state);
+ if (STT_STATE_READY == state || STT_STATE_CREATED == state) {
+ return false;
+ }
+
+ EXPECT_EQ(stt_cancel(mHandle), STT_ERROR_NONE);
+ return IsStateChanged(STT_STATE_READY, 5);
+}
+
+
+bool SttTestUtility::WaitCondtion(std::function<bool(void)> checker, int duration)
+{
+ auto mainLoopQuitTimer = ecore_timer_add(static_cast<double>(duration), [](void *data) -> Eina_Bool {
+ ecore_main_loop_quit();
+ return EINA_FALSE;
+ }, nullptr);
+
+ auto checkerTimer = ecore_timer_add(0.0, [](void *data) -> Eina_Bool {
+ auto &checker = *reinterpret_cast<std::function<bool()> *>(data);
+ if (false == checker()) {
+ return EINA_TRUE;
+ }
+
+ ecore_main_loop_quit();
+ return EINA_FALSE;
+ }, &checker);
+
+ if (nullptr == mainLoopQuitTimer || nullptr == checkerTimer) {
+ return false;
+ }
+
+ ecore_main_loop_begin();
+
+ ecore_timer_del(mainLoopQuitTimer);
+ mainLoopQuitTimer = nullptr;
+
+ ecore_timer_del(checkerTimer);
+ checkerTimer = nullptr;
+
+ return checker();
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __STT_TEST_UTIL_H__
+#define __STT_TEST_UTIL_H__
+
+
+#include <functional>
+
+#include <stt.h>
+#include <stt_internal.h>
+
+
+class SttTestUtility {
+public:
+ static void StateChangedCallback(stt_h stt, stt_state_e previous, stt_state_e current, void *user_data);
+ static void ErrorCallback(stt_h stt, stt_error_e reason, void *user_data);
+ static void RecognitionResultCallback(stt_h stt, stt_result_event_e event, const char** data, int data_count, const char* msg, void *user_data);
+
+ static void TerminateCurrentEngine();
+ static void WaitUntilEngineTerminated(int duration);
+ static bool IsFeatureSupported();
+
+public:
+ SttTestUtility();
+ ~SttTestUtility();
+
+ void GetTestPCMData();
+
+ void CreateHandle();
+ void DestroyHandle();
+ void SetTestMode();
+ void UnsetTestMode();
+
+ bool Prepare();
+ bool Unprepare();
+
+ bool Start(const char* language, const char* type);
+ bool Stop();
+ bool StartAudioStreaming(const char* language, const char* type);
+ bool StopAudioStreaming();
+ bool Cancel();
+
+ bool IsStateChanged(stt_state_e targetState, int duration);
+ bool IsErrorOccurring(int duration);
+ bool IsResultReceived(int duration);
+
+public:
+ stt_h mHandle;
+ stt_state_e mCurrentState;
+
+ bool mErrorOccured;
+ bool mResultReceived;
+ char *mErrorMessage;
+
+ char* mPCMData;
+ size_t mPCMSize;
+
+private:
+ static bool WaitCondtion(std::function<bool(void)> checker, int duration);
+};
+
+
+#endif /* __STT_TEST_UTIL_H__ */