Add test utility class
[platform/core/uifw/stt.git] / tests / src / test_util.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <app_manager_extension.h>
19 #include <tzplatform_config.h>
20 #include <system_info.h>
21 #include <vconf.h>
22 #include <gtest/gtest.h>
23 #include <Ecore.h>
24
25 #include "test_util.h"
26
27
28 SttTestUtility::SttTestUtility()
29 {
30         mHandle = nullptr;
31         mCurrentState = STT_STATE_CREATED;
32         mErrorOccured = false;
33         mResultReceived = false;
34         mErrorMessage = nullptr;
35
36         mPCMData = nullptr;
37         mPCMSize = 0;
38
39         CreateHandle();
40 }
41
42 SttTestUtility::~SttTestUtility()
43 {
44         UnsetTestMode();
45         DestroyHandle();
46
47         free(mErrorMessage);
48         mErrorMessage = nullptr;
49
50         free(mPCMData);
51         mPCMData = nullptr;
52         mPCMSize = 0;
53 }
54
55 void SttTestUtility::StateChangedCallback(stt_h tts, stt_state_e previous, stt_state_e current, void *user_data)
56 {
57         auto instance = reinterpret_cast<SttTestUtility *>(user_data);
58         instance->mCurrentState = current;
59 }
60
61 void SttTestUtility::ErrorCallback(stt_h stt, stt_error_e reason, void *user_data)
62 {
63         auto instance = reinterpret_cast<SttTestUtility *>(user_data);
64         instance->mErrorOccured = true;
65
66         char *errorMessage = nullptr;
67         ASSERT_EQ(stt_get_error_message(instance->mHandle, &errorMessage), STT_ERROR_NONE);
68
69         free(instance->mErrorMessage);
70         instance->mErrorMessage = errorMessage;
71 }
72
73 void SttTestUtility::RecognitionResultCallback(stt_h stt, stt_result_event_e event, const char** data, int data_count, const char* msg, void *user_data)
74 {
75         auto instance = reinterpret_cast<SttTestUtility *>(user_data);
76         instance->mResultReceived = true;
77 }
78
79
80 void SttTestUtility::TerminateCurrentEngine()
81 {
82         char* engineId = vconf_get_str(VCONFKEY_STT_ENGINE_DEFAULT);
83
84         app_context_h context = nullptr;
85         app_manager_get_app_context(engineId, &context);
86         free(engineId);
87
88         ASSERT_NE(context, nullptr);
89
90         EXPECT_EQ(app_manager_terminate_app(context), APP_MANAGER_ERROR_NONE);
91         EXPECT_EQ(app_context_destroy(context), APP_MANAGER_ERROR_NONE);
92 }
93
94 void SttTestUtility::WaitUntilEngineTerminated(int duration)
95 {
96         auto engineChcker = [](void) {
97                 bool is_running = false;
98
99                 char* engineId = vconf_get_str(VCONFKEY_STT_ENGINE_DEFAULT);
100                 app_manager_is_running(engineId, &is_running);
101                 free(engineId);
102
103                 return !is_running;
104         };
105
106         WaitCondtion(engineChcker, duration);
107 }
108
109 bool SttTestUtility::IsFeatureSupported()
110 {
111         bool isSttSupported = false;
112         if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool("http://tizen.org/feature/speech.recognition", &isSttSupported)) {
113                 return false;
114         }
115
116         bool isMicSupported = false;
117         if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_bool("http://tizen.org/feature/microphone", &isMicSupported)) {
118                 return false;
119         }
120
121         return isSttSupported && isMicSupported;
122 }
123
124 void SttTestUtility::GetTestPCMData()
125 {
126         static const char* PCM_PATH = tzplatform_mkpath(tzplatform_getid("TZ_SYS_RO_APP"), "/org.tizen.stt-unittests/res/test_pcm.dat");
127
128         FILE* fp_in = fopen(PCM_PATH, "rb");
129         if (fp_in == nullptr) {
130                 return;
131         }
132
133         fseek(fp_in, 0, SEEK_END);
134         long size = ftell(fp_in);
135         fseek(fp_in, 0, SEEK_SET);
136         if (size <= 0) {
137                 fclose(fp_in);
138                 return;
139         }
140
141         char* data = reinterpret_cast<char *>(calloc(sizeof(char), size));
142         if (NULL == data) {
143                 fclose(fp_in);
144                 return;
145         }
146
147         size_t read_size = fread(data, sizeof(char), size, fp_in);
148         fclose(fp_in);
149
150         if (read_size <= 0) {
151                 free(data);
152                 return;
153         }
154
155         mPCMSize = size;
156         mPCMData = data;
157 }
158
159 void SttTestUtility::CreateHandle()
160 {
161         if (IsFeatureSupported() == false) {
162                 mHandle = nullptr;
163                 return;
164         }
165
166         stt_create(&mHandle);
167         ASSERT_NE(mHandle, nullptr);
168
169         EXPECT_EQ(stt_set_state_changed_cb(mHandle, StateChangedCallback, this), STT_ERROR_NONE);
170         EXPECT_EQ(stt_set_error_cb(mHandle, ErrorCallback, this), STT_ERROR_NONE);
171 }
172
173 void SttTestUtility::DestroyHandle()
174 {
175         if (nullptr != mHandle) {
176                 EXPECT_EQ(stt_destroy(mHandle), STT_ERROR_NONE);
177                 mHandle = nullptr;
178         }
179 }
180
181 void SttTestUtility::SetTestMode()
182 {
183         stt_state_e state = STT_STATE_CREATED;
184         ASSERT_EQ(stt_get_state(mHandle, &state), STT_ERROR_NONE);
185         ASSERT_EQ(state, STT_STATE_READY);
186         EXPECT_EQ(stt_set_private_data(mHandle, "stt_verification", "true"), STT_ERROR_NONE);
187 }
188
189 void SttTestUtility::UnsetTestMode()
190 {
191         stt_state_e state = STT_STATE_CREATED;
192         stt_get_state(mHandle, &state);
193         if (STT_STATE_READY != state) {
194                 return;
195         }
196
197         stt_set_private_data(mHandle, "stt_verification", "false");
198 }
199
200 bool SttTestUtility::IsStateChanged(stt_state_e targetState, int duration)
201 {
202         auto stateChecker = std::bind([](SttTestUtility *instance, stt_state_e target) {
203                 return target == instance->mCurrentState;
204         }, this, targetState);
205
206         return WaitCondtion(stateChecker, duration);
207 }
208
209 bool SttTestUtility::IsErrorOccurring(int duration)
210 {
211         auto errorChecker = std::bind([](SttTestUtility *instance) {
212                 return instance->mErrorOccured;
213         }, this);
214
215         return WaitCondtion(errorChecker, duration);
216 }
217
218 bool SttTestUtility::IsResultReceived(int duration)
219 {
220         auto resultChecker = std::bind([](SttTestUtility *instance) {
221                 return instance->mResultReceived;
222         }, this);
223
224         return WaitCondtion(resultChecker, duration);
225 }
226
227 bool SttTestUtility::Prepare()
228 {
229         stt_state_e state = STT_STATE_CREATED;
230         stt_get_state(mHandle, &state);
231         if (STT_STATE_CREATED != state) {
232                 return false;
233         }
234
235         stt_prepare(mHandle);
236         return IsStateChanged(STT_STATE_READY, 5);
237 }
238
239 bool SttTestUtility::Unprepare()
240 {
241         stt_state_e state = STT_STATE_CREATED;
242         stt_get_state(mHandle, &state);
243         if (STT_STATE_READY != state) {
244                 return false;
245         }
246
247         stt_unprepare(mHandle);
248         return IsStateChanged(STT_STATE_CREATED, 5);
249 }
250
251 bool SttTestUtility::Start(const char* language, const char* type)
252 {
253         EXPECT_EQ(stt_start(mHandle, language, type), STT_ERROR_NONE);
254         return IsStateChanged(STT_STATE_RECORDING, 5);
255 }
256
257 bool SttTestUtility::Stop()
258 {
259         EXPECT_EQ(stt_stop(mHandle), STT_ERROR_NONE);
260         return IsStateChanged(STT_STATE_PROCESSING, 5);
261 }
262
263 bool SttTestUtility::StartAudioStreaming(const char* language, const char* type)
264 {
265         EXPECT_EQ(stt_start_audio_streaming(mHandle, language, type), STT_ERROR_NONE);
266         return IsStateChanged(STT_STATE_RECORDING, 5);
267 }
268
269 bool SttTestUtility::StopAudioStreaming()
270 {
271         EXPECT_EQ(stt_stop_audio_streaming(mHandle), STT_ERROR_NONE);
272         return IsStateChanged(STT_STATE_PROCESSING, 5);
273 }
274
275 bool SttTestUtility::Cancel()
276 {
277         stt_state_e state = STT_STATE_CREATED;
278         stt_get_state(mHandle, &state);
279         if (STT_STATE_READY == state || STT_STATE_CREATED == state) {
280                 return false;
281         }
282
283         EXPECT_EQ(stt_cancel(mHandle), STT_ERROR_NONE);
284         return IsStateChanged(STT_STATE_READY, 5);
285 }
286
287
288 bool SttTestUtility::WaitCondtion(std::function<bool(void)> checker, int duration)
289 {
290         auto mainLoopQuitTimer = ecore_timer_add(static_cast<double>(duration), [](void *data) -> Eina_Bool {
291                 ecore_main_loop_quit();
292                 return EINA_FALSE;
293         }, nullptr);
294
295         auto checkerTimer = ecore_timer_add(0.0, [](void *data) -> Eina_Bool {
296                 auto &checker = *reinterpret_cast<std::function<bool()> *>(data);
297                 if (false == checker()) {
298                         return EINA_TRUE;
299                 }
300
301                 ecore_main_loop_quit();
302                 return EINA_FALSE;
303         }, &checker);
304
305         if (nullptr == mainLoopQuitTimer || nullptr == checkerTimer) {
306                 return false;
307         }
308
309         ecore_main_loop_begin();
310
311         ecore_timer_del(mainLoopQuitTimer);
312         mainLoopQuitTimer = nullptr;
313
314         ecore_timer_del(checkerTimer);
315         checkerTimer = nullptr;
316
317         return checker();
318 }