RTS API Documentation  1.10.11
switch_test.h
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2019, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Chris Rienzo <chris@signalwire.com>
27  * Seven Du <seven@signalwire.com>
28  *
29  * switch_test.h -- FreeSWITCH test macros
30  */
31 #ifndef SWITCH_FST_H
32 #define SWITCH_FST_H
33 
34 #include <switch.h>
35 
36 #include <test/switch_fct.h>
37 
38 /**
39  * Get environment variable and save to var
40  */
41 static char *fst_getenv_default(const char *env, char *default_value, switch_bool_t required)
42 {
43  char *val = getenv(env);
44  if (!val) {
45  if (required) {
46  fprintf(stderr, "Failed to start test: environment variable \"%s\" is not set!\n", env);
47  exit(1);
48  }
49  return default_value;
50  }
51  return val;
52 }
53 
54 /**
55  * Get environment variable and save to var
56  */
57 #define fst_getenv(env, default_value) \
58  char *env = fst_getenv_default(#env, (char *)default_value, SWITCH_FALSE);
59 
60 /**
61  * Get mandatory environment variable and save to var. Exit with error if missing.
62  */
63 #define fst_getenv_required(env) \
64  char *env = fst_getenv_default(#env, NULL, SWITCH_TRUE);
65 
66 /**
67  * initialize FS core from optional configuration dir
68  */
69 static switch_status_t fst_init_core_and_modload(const char *confdir, const char *basedir, int minimal, switch_core_flag_t flags)
70 {
71  switch_status_t status;
72  const char *err;
73  unsigned long pid = switch_getpid();
74  // Let FreeSWITCH core pick these
75  //SWITCH_GLOBAL_dirs.base_dir = strdup("/usr/local/freeswitch");
76  //SWITCH_GLOBAL_dirs.mod_dir = strdup("/usr/local/freeswitch/mod");
77  //SWITCH_GLOBAL_dirs.lib_dir = strdup("/usr/local/freeswitch/lib");
78  //SWITCH_GLOBAL_dirs.temp_dir = strdup("/tmp");
79 
80 #ifdef SWITCH_TEST_BASE_DIR_OVERRIDE
82 #else
83 #define SWITCH_TEST_BASE_DIR_OVERRIDE "."
84 #endif
85 
86  if (zstr(basedir)) {
87  basedir = ".";
88  }
89 
90  // Allow test to define the runtime dir
91  if (!zstr(confdir)) {
92 #ifdef SWITCH_TEST_BASE_DIR_FOR_CONF
93  SWITCH_GLOBAL_dirs.conf_dir = switch_mprintf("%s%s%s", SWITCH_TEST_BASE_DIR_FOR_CONF, SWITCH_PATH_SEPARATOR, confdir);
94 #else
95  if (confdir[0] != '/') {
97  } else {
98  SWITCH_GLOBAL_dirs.conf_dir = strdup(confdir);
99  }
100 #endif
101  } else {
103  }
104 
119 
121 
122  if (!minimal) {
123  status = switch_core_init_and_modload(flags, SWITCH_TRUE, &err);
124  switch_sleep(1 * 1000000);
125  switch_core_set_variable("sound_prefix", "." SWITCH_PATH_SEPARATOR);
126  if (status != SWITCH_STATUS_SUCCESS && err) {
127  fprintf(stderr, "%s", err);
128  }
129  return status;
130  }
131  status = switch_core_init(SCF_MINIMAL, SWITCH_TRUE, &err);
132  if (status != SWITCH_STATUS_SUCCESS && err) {
133  fprintf(stderr, "%s", err);
134  }
135  return status;
136 }
137 
138 /**
139  * Park FreeSWITCH session. This is handy when wanting to use switch_core_session_execute_async() on the test session.
140  * @param session to park
141  */
142 #define fst_session_park(session) \
143  switch_ivr_park_session(session); \
144  switch_channel_wait_for_flag(switch_core_session_get_channel(session), CF_PARK, SWITCH_TRUE, 10000, NULL);
145 
146 /**
147  * check for test requirement - execute teardown on failure
148  */
149 #define fst_requires fct_req
150 
151 /**
152  * check for required module - execute teardown on failure
153  */
154 #define fst_requires_module(modname) fct_req(switch_loadable_module_exists(modname) == SWITCH_STATUS_SUCCESS)
155 
156 /**
157  * test boolean expression - continue test execution on failure
158  */
159 #define fst_check fct_chk
160 
161 /**
162  * test integers for equality - continue test execution on failure
163  */
164 #define fst_check_int_equals fct_chk_eq_int
165 
166 /**
167  * test string for equality - continue test execution on failure
168  */
169 #define fst_check_string_equals fct_chk_eq_str
170 
171 /**
172  * test string for inequality - continue test execution on failure
173  */
174 #define fst_check_string_not_equals fct_chk_neq_str
175 
176 /**
177  * Test string for matching prefix
178 */
179 #define fst_check_string_starts_with fct_chk_startswith_str
180 
181 /**
182  * Test string for matching suffix
183 */
184 #define fst_check_string_ends_with fct_chk_endswith_str
185 
186 /**
187  * Test string for substring
188  */
189 #define fst_check_string_has fct_chk_incl_str
190 
191 /**
192  * Test string for exclusion of substring
193  */
194 #define fst_check_string_does_not_have fct_chk_excl_str
195 
196 /**
197  * Mark reference for time measure
198  */
199 #define fst_time_mark() \
200  fst_time_start = switch_time_now();
201 
202 /**
203  * Check a test /w error message
204  */
205 #define fst_xcheck(expr, error_msg) \
206  (fct_xchk(expr, "%s", error_msg))
207 
208 /**
209  * Fail a test
210  */
211 #define fst_fail(error_msg) \
212  (fct_xchk(0, "%s", error_msg))
213 
214 /**
215  * Check duration relative to test start, last marked time, or last check.
216  */
217 #define fst_check_duration(duration_ms, precision_ms) \
218  { \
219  int actual_duration_ms = (int)((switch_time_now() - fst_time_start) / 1000); \
220  fct_xchk( \
221  abs((actual_duration_ms - duration_ms)) <= precision_ms, \
222  "fst_check_duration: %d != %d +/- %d", \
223  (actual_duration_ms), \
224  (duration_ms), \
225  (precision_ms) \
226  ); \
227  }
228 
229 /**
230  * Check if integer is in range
231  */
232 #define fst_check_int_range(actual, expected, precision) \
233  fct_xchk( \
234  abs((actual - expected)) <= precision, \
235  "fst_check_int_range: %d != %d +/- %d", \
236  (actual), \
237  (expected), \
238  (precision) \
239  )
240 
241 /**
242  * Check if double-precision number is in range
243  */
244 #define fst_check_double_range(actual, expected, precision) \
245  fct_xchk( \
246  fabs((actual - expected)) <= precision, \
247  "fst_check_double_range: %f != %f +/- %f", \
248  (actual), \
249  (expected), \
250  (precision) \
251  )
252 
253 /**
254  * Run test without loading FS core
255  */
256 #define FST_BEGIN() \
257  FCT_BGN() \
258  { \
259  int fst_core = 0; \
260  switch_time_t fst_time_start = 0; \
261  switch_timer_t fst_timer = { 0 }; \
262  switch_memory_pool_t *fst_pool = NULL; \
263  int fst_timer_started = 0; \
264  fst_getenv_default("FST_SUPPRESS_UNUSED_STATIC_WARNING", NULL, SWITCH_FALSE); \
265  if (fst_core) { \
266  fst_init_core_and_modload(NULL, NULL, 0, 0); /* shuts up compiler */ \
267  } \
268  { \
269 
270 
271 #define FST_END() \
272  } \
273  if (fst_time_start) { \
274  /* shut up compiler */ \
275  fst_time_start = 0; \
276  } \
277  } \
278  FCT_END()
279 
280 /**
281  * Define the beginning of a freeswitch core test driver. Only one per test application allowed.
282  * @param confdir directory containing freeswitch.xml configuration
283  */
284 #define FST_CORE_EX_BEGIN(confdir, flags) \
285  FCT_BGN() \
286  { \
287  int fst_core = 0; \
288  switch_time_t fst_time_start = 0; \
289  switch_timer_t fst_timer = { 0 }; \
290  switch_memory_pool_t *fst_pool = NULL; \
291  int fst_timer_started = 0; \
292  fst_getenv_default("FST_SUPPRESS_UNUSED_STATIC_WARNING", NULL, SWITCH_FALSE); \
293  if (fst_init_core_and_modload(confdir, confdir, 0, flags | SCF_LOG_DISABLE) == SWITCH_STATUS_SUCCESS) { \
294  fst_core = 2; \
295  } else { \
296  fprintf(stderr, "Failed to load FS core\n"); \
297  exit(1); \
298  } \
299  {
300 
301 
302 /**
303  * Define the end of a freeswitch core test driver.
304  */
305 #define FST_CORE_END() \
306  switch_core_destroy(); \
307  } \
308  if (fst_time_start) { \
309  /* shut up compiler */ \
310  fst_time_start = 0; \
311  } \
312  } \
313  FCT_END()
314 
315 #define FST_CORE_BEGIN(confdir) FST_CORE_EX_BEGIN(confdir, 0)
316 #define FST_CORE_DB_BEGIN(confdir) FST_CORE_EX_BEGIN(confdir, SCF_USE_SQL)
317 
318 /**
319  * Minimal FS core load
320  */
321 #define FST_MINCORE_BEGIN(confdir) \
322  FCT_BGN() \
323  { \
324  int fst_core = 0; \
325  switch_time_t fst_time_start = 0; \
326  switch_timer_t fst_timer = { 0 }; \
327  switch_memory_pool_t *fst_pool = NULL; \
328  int fst_timer_started = 0; \
329  fst_getenv_default("FST_SUPPRESS_UNUSED_STATIC_WARNING", NULL, SWITCH_FALSE); \
330  if (fst_init_core_and_modload(confdir, NULL, 1, 0 | SCF_LOG_DISABLE) == SWITCH_STATUS_SUCCESS) { /* minimal load */ \
331  fst_core = 1; \
332  } else { \
333  fprintf(stderr, "Failed to load FS core\n"); \
334  exit(1); \
335  } \
336  {
337 
338 #define FST_MINCORE_END FST_CORE_END
339 
340 /**
341  * Define the beginning of a FreeSWITCH module test suite. Loads the module for test.
342  * @param modname name of module to load.
343  * @param suite the name of this test suite
344  */
345 #ifdef WIN32
346 #define FST_MODULE_BEGIN(modname,suite) \
347  { \
348  const char *fst_test_module = #modname; \
349  if (fst_core && !zstr(fst_test_module)) { \
350  const char *err; \
351  switch_loadable_module_load_module((char *)"./mod", (char *)fst_test_module, SWITCH_TRUE, &err); \
352  } \
353  FCT_FIXTURE_SUITE_BGN(suite);
354 #else
355 #define FST_MODULE_BEGIN(modname,suite) \
356  { \
357  const char *fst_test_module = #modname; \
358  if (fst_core && !zstr(fst_test_module)) { \
359  const char *err; \
360  char path[1024]; \
361  sprintf(path, "%s%s%s", SWITCH_TEST_BASE_DIR_OVERRIDE, SWITCH_PATH_SEPARATOR, "../.libs/"); \
362  switch_loadable_module_load_module((char *)path, (char *)fst_test_module, SWITCH_TRUE, &err); \
363  } \
364  FCT_FIXTURE_SUITE_BGN(suite);
365 #endif
366 
367 /**
368  * Define the end of a FreeSWITCH module test suite.
369  */
370 #ifdef WIN32
371 #define FST_MODULE_END() \
372  FCT_FIXTURE_SUITE_END(); \
373  if (!zstr(fst_test_module) && switch_loadable_module_exists(fst_test_module) == SWITCH_STATUS_SUCCESS) { \
374  const char *err; \
375  switch_loadable_module_unload_module((char *)"./mod", (char *)fst_test_module, SWITCH_FALSE, &err); \
376  } \
377  }
378 #else
379 #define FST_MODULE_END() \
380  FCT_FIXTURE_SUITE_END(); \
381  if (!zstr(fst_test_module) && switch_loadable_module_exists(fst_test_module) == SWITCH_STATUS_SUCCESS) { \
382  const char *err; \
383  char path[1024]; \
384  sprintf(path, "%s%s%s", SWITCH_TEST_BASE_DIR_OVERRIDE, SWITCH_PATH_SEPARATOR, "../.libs/"); \
385  switch_loadable_module_unload_module((char*)path, (char *)fst_test_module, SWITCH_FALSE, &err); \
386  } \
387  }
388 #endif
389 
390 /**
391  * Define the beginning of a test suite not associated with a module.
392  * @param suite the name of this test suite
393  */
394 #define FST_SUITE_BEGIN(suite) \
395  const char *fst_test_module = NULL; \
396  FCT_FIXTURE_SUITE_BGN(suite)
397 
398 /**
399  * Define the end of a test suite.
400  */
401 #define FST_SUITE_END FCT_FIXTURE_SUITE_END
402 
403 
404 /**
405  * Define the test suite setup. This is run before each test or session test.
406  */
407 #define FST_SETUP_BEGIN() \
408  FCT_SETUP_BGN() \
409  if (fst_core) { \
410  switch_core_new_memory_pool(&fst_pool); \
411  if (fst_core > 1) { \
412  fst_timer_started = (switch_core_timer_init(&fst_timer, "soft", 20, 160, fst_pool) == SWITCH_STATUS_SUCCESS); \
413  } \
414  }
415 
416 /**
417  * Define the end of test suite setup.
418  */
419 #define FST_SETUP_END FCT_SETUP_END
420 
421 
422 /**
423  * Define the test suite teardown. This is run after each test or session test.
424  */
425 #define FST_TEARDOWN_BEGIN() \
426  FCT_TEARDOWN_BGN() \
427  if (fst_core) { \
428  if (fst_pool) switch_core_destroy_memory_pool(&fst_pool); \
429  if (fst_core > 1) { \
430  if (fst_timer_started) switch_core_timer_destroy(&fst_timer); \
431  } \
432  }
433 
434 /**
435  * Define the test suite teardown end.
436  */
437 #define FST_TEARDOWN_END FCT_TEARDOWN_END
438 
439 /**
440  * Define a test in a test suite.
441  * Defined vars:
442  * switch_memory_pool_t *fst_pool; A memory pool that is torn down on test completion
443  * switch_core_timer_t *fst_timer; A 8kHz, 20ms soft timer (160 samples per frame)
444  * @param name the name of this test
445  */
446 #define FST_TEST_BEGIN(name) \
447  FCT_TEST_BGN(name) \
448  if (fst_core) { \
449  switch_log_level_t level = SWITCH_LOG_DEBUG; \
450  switch_core_session_ctl(SCSC_LOGLEVEL, &level); \
451  fst_requires(fst_pool != NULL); \
452  if (fst_core > 1) { \
453  fst_requires(fst_timer_started); \
454  } \
455  fst_time_mark(); \
456  } \
457  if (fst_test_module) { \
458  fst_requires_module(fst_test_module); \
459  }
460 
461 #define FST_TEST_END \
462  if (fst_core) { \
463  switch_log_level_t level = SWITCH_LOG_DISABLE; \
464  switch_core_session_ctl(SCSC_LOGLEVEL, &level); \
465  } \
466  FCT_TEST_END
467 
468 
469 /**
470  * Define a session test in a test suite. This can be used to test IVR functions.
471  *
472  * Records session audio to /tmp/name.wav where name is the name of the test.
473  *
474  * Required modules:
475  * mod_loopback - for null endpoint
476  * mod_sndfile - for wav file support
477  *
478  * Defined vars:
479  * switch_memory_pool_t *fst_pool; A memory pool that is torn down on test completion
480  * switch_core_timer_t *fst_timer; A 8kHz, 20ms soft timer (160 samples per frame)
481  * switch_core_session_t *fst_session; The outbound null session. L16, 1 channel, 8kHz.
482  * switch_core_session_t *fst_session_pool; The outbound null session's pool.
483  * switch_channel_t *fst_channel; The outbound null session's channel.
484  *
485  * @param name the name of this test
486  * @param rate the rate of the channel
487  * @param video_codec the rate of the channel
488  */
489 
490 #define FST_SESSION_BEGIN_RATE_VIDEO(name, rate, video_codec) \
491  FCT_TEST_BGN(name) \
492  { \
493  if (fst_core) { \
494  switch_log_level_t level = SWITCH_LOG_DEBUG; \
495  switch_core_session_ctl(SCSC_LOGLEVEL, &level); \
496  fst_requires(fst_pool != NULL); \
497  if (fst_core > 1) { \
498  fst_requires(fst_timer_started); \
499  } \
500  fst_time_mark(); \
501  } \
502  } \
503  { \
504  switch_core_session_t *fst_session = NULL; \
505  switch_event_t *fst_originate_vars = NULL; \
506  switch_call_cause_t fst_cause = SWITCH_CAUSE_NORMAL_CLEARING; \
507  fst_requires(fst_core); \
508  if (fst_test_module) { \
509  fst_requires_module(fst_test_module); \
510  } \
511  fst_requires_module("mod_loopback"); \
512  fst_requires_module("mod_sndfile"); \
513  fst_requires(switch_core_running()); \
514  fst_requires(switch_event_create_plain(&fst_originate_vars, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS); \
515  switch_event_add_header_string(fst_originate_vars, SWITCH_STACK_BOTTOM, "origination_caller_id_number", "+15551112222"); \
516  switch_event_add_header(fst_originate_vars, SWITCH_STACK_BOTTOM, "rate", "%d", rate); \
517  if (switch_ivr_originate(NULL, &fst_session, &fst_cause, "{null_video_codec=" video_codec "}null/+15553334444", 2, NULL, NULL, NULL, NULL, fst_originate_vars, SOF_NONE, NULL, NULL) == SWITCH_STATUS_SUCCESS && fst_session) { \
518  switch_memory_pool_t *fst_session_pool = switch_core_session_get_pool(fst_session); \
519  switch_channel_t *fst_channel = switch_core_session_get_channel(fst_session); \
520  switch_channel_set_state(fst_channel, CS_SOFT_EXECUTE); \
521  switch_channel_wait_for_state(fst_channel, NULL, CS_SOFT_EXECUTE); \
522  switch_channel_set_variable(fst_channel, "send_silence_when_idle", "-1"); \
523  switch_channel_set_variable(fst_channel, "RECORD_STEREO", "true"); \
524  switch_ivr_record_session(fst_session, (char *)"/tmp/"#name".wav", 0, NULL); \
525  switch_channel_set_variable(fst_channel, "RECORD_STEREO", NULL); \
526  for(;;) {
527 
528 /**
529  * Define a session test in a test suite. This can be used to test IVR functions.
530  * See FST_SESSION_BEGIN_RATE_VIDEO
531  */
532 
533 #define FST_SESSION_BEGIN(name) FST_SESSION_BEGIN_RATE(name, 8000)
534 #define FST_SESSION_BEGIN_RATE(name, rate) FST_SESSION_BEGIN_RATE_VIDEO(name, rate, "")
535 
536 /* BODY OF TEST CASE HERE */
537 
538 /**
539  * Define the end of a session test in a test suite.
540  * Hangs up session under test.
541  */
542 #define FST_SESSION_END() \
543  break; \
544  } \
545  if (switch_channel_ready(fst_channel)) { \
546  switch_channel_hangup(fst_channel, SWITCH_CAUSE_NORMAL_CLEARING); \
547  } \
548  if (fst_originate_vars) { \
549  switch_event_destroy(&fst_originate_vars); \
550  } \
551  if (fst_session_pool) { \
552  fst_session_pool = NULL; \
553  } \
554  switch_core_session_rwunlock(fst_session); \
555  if (fst_core) { \
556  switch_log_level_t level = SWITCH_LOG_DISABLE; \
557  switch_core_session_ctl(SCSC_LOGLEVEL, &level); \
558  } \
559  switch_sleep(1000000); \
560  } \
561  } \
562  FCT_TEST_END()
563 
564 
565 /* CORE ASR TEST MACROS */
566 
567 /**
568  * Open core ASR for a recognizer module. Opens for L16, 1 channel, 8KHz.
569  *
570  * Test Requires:
571  * switch_core_asr_open() == SWITCH_STATUS_SUCCESS
572  *
573  * Defined vars:
574  * switch_asr_handle_t ah; Core ASR handle
575  * switch_asr_flag_t flags; Core ASR flags used to open recognizer.
576  * char *fst_asr_result; Result of last recognition. Allocated from test memory pool.
577  *
578  * @param recognizer name of recognizer to open (like gcloud_dialogflow)
579  *
580  */
581 #define fst_test_core_asr_open(recognizer) \
582 {\
583  char *fst_asr_result = NULL; \
584  switch_asr_handle_t ah = { 0 }; \
585  switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE; \
586  fst_requires(fst_core > 1); \
587  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Open recognizer: %s\n", recognizer); \
588  /* open ASR interface and feed recorded audio into it and collect result */ \
589  fst_requires(switch_core_asr_open(&ah, recognizer, "L16", 8000, "", &flags, fst_pool) == SWITCH_STATUS_SUCCESS); \
590 
591 /**
592  * Execute test on opened recognizer. Reads audio from input file and passes it to the recognizer.
593  *
594  * Test Requires:
595  * switch_core_asr_load_grammar(grammar) == SWITCH_STATUS_SUCCESS
596  * switch_core_file_open(input_filename) == SWITCH_STATUS_SUCCESS
597  * switch_core_file_close() == SWITCH_STATUS_SUCCESS
598  *
599  * Test Checks:
600  * Got result from recognizer.
601  *
602  * Test Output:
603  * fst_asr_result has the xmlstr from switch_core_file_get_results()
604  *
605  * @param grammar recognizer grammar
606  * @param input_filename name of file containing audio to send to recognizer.
607  */
608 #define fst_test_core_asr(grammar, input_filename) \
609 { \
610  /* feed file into ASR */ \
611  switch_status_t result; \
612  switch_file_handle_t file_handle = { 0 }; \
613  uint8_t *buf; \
614  size_t len = 160; \
615  int got_result = 0; \
616  fst_asr_result = NULL; \
617  file_handle.channels = 1; \
618  file_handle.native_rate = 8000; \
619  fst_requires(fst_core > 1); \
620  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Test recognizer: input = %s\n", input_filename); \
621  fst_requires(switch_core_asr_load_grammar(&ah, grammar, "") == SWITCH_STATUS_SUCCESS); \
622  fst_requires(switch_core_file_open(&file_handle, input_filename, file_handle.channels, 8000, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) == SWITCH_STATUS_SUCCESS); \
623  buf = (uint8_t *)switch_core_alloc(fst_pool, sizeof(uint8_t) * 160 * sizeof(uint16_t) * file_handle.channels); \
624  switch_core_timer_sync(&fst_timer); \
625  while ((result = switch_core_file_read(&file_handle, buf, &len)) == SWITCH_STATUS_SUCCESS) { \
626  fst_requires(switch_core_asr_feed(&ah, buf, len * sizeof(int16_t), &flags) == SWITCH_STATUS_SUCCESS); \
627  switch_core_timer_next(&fst_timer); \
628  if (switch_core_asr_check_results(&ah, &flags) == SWITCH_STATUS_SUCCESS) { \
629  char *xmlstr = NULL; \
630  switch_event_t *headers = NULL; \
631  flags = SWITCH_ASR_FLAG_NONE; \
632  /* switch_ivr_detect_speech.. checks one in media bug then again in speech_thread */ \
633  fst_requires(switch_core_asr_check_results(&ah, &flags) == SWITCH_STATUS_SUCCESS); \
634  result = switch_core_asr_get_results(&ah, &xmlstr, &flags); \
635  if (result == SWITCH_STATUS_SUCCESS) { \
636  got_result++; \
637  switch_core_asr_get_result_headers(&ah, &headers, &flags); \
638  if (headers) { \
639  switch_event_destroy(&headers); \
640  } \
641  fst_check(xmlstr != NULL); \
642  if (xmlstr != NULL) { \
643  fst_asr_result = switch_core_strdup(fst_pool, xmlstr);\
644  } \
645  switch_safe_free(xmlstr); \
646  break; \
647  } \
648  } \
649  len = 160; \
650  } \
651  fst_check(got_result == 1); \
652  fst_requires(switch_core_file_close(&file_handle) == SWITCH_STATUS_SUCCESS); \
653 }
654 
655 /**
656  * Pause an open recognizer.
657  *
658  * Test Requires:
659  * switch_core_asr_pause(&ah) == SWITCH_STATUS_SUCCESS
660  */
661 #define fst_test_core_asr_pause() \
662  fst_requires(fst_core > 1); \
663  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Pause recognizer\n"); \
664  flags = SWITCH_ASR_FLAG_NONE; \
665  fst_requires(switch_core_asr_pause(&ah) == SWITCH_STATUS_SUCCESS);
666 
667 /**
668  * Resumes an open recognizer
669  *
670  * Test Requires:
671  * switch_core_asr_resume(&ah) == SWITCH_STATUS_SUCCESS
672  */
673 #define fst_test_core_asr_resume() \
674  fst_requires(fst_core > 1); \
675  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Resume recognizer\n"); \
676  flags = SWITCH_ASR_FLAG_NONE; \
677  fst_requires(switch_core_asr_resume(&ah) == SWITCH_STATUS_SUCCESS);
678 
679 /**
680  * Close an open recognizer
681  *
682  * Test Requires:
683  * switch_core_asr_close(&ah, flags) == SWITCH_STATUS_SUCCESS
684  */
685 #define fst_test_core_asr_close() \
686  fst_requires(fst_core > 1); \
687  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Close recognizer\n"); \
688  flags = SWITCH_ASR_FLAG_NONE; \
689  fst_requires(switch_core_asr_close(&ah, &flags) == SWITCH_STATUS_SUCCESS); \
690 }
691 
692 
693 
694 /* PLAY AND DETECT SPEECH TEST MACROS - requires FST_SESSION */
695 
696 /**
697  * Define beginning of play_and_detect_speech recognizer test
698  *
699  * Defined vars:
700  * const char *fst_asr_result; Result of last recognition. Allocated from test memory pool.
701  */
702 #define fst_play_and_detect_speech_test_begin() \
703 { \
704  const char *fst_asr_result = NULL; \
705  fst_requires(fst_core > 1);
706 
707 /**
708  * Use play_and_detect_speech APP to test recognizer
709  *
710  * Test Requires:
711  * switch_ivr_displace_session(input_filename) == SWITCH_STATUS_SUCCESS
712  * switch_core_session_execute_application(play_and_detect_speech) == SWITCH_STATUS_SUCCESS
713  * mod_dptools is loaded
714  *
715  * Test Checks:
716  * fst_asr_result != NULL after recognition completes
717  *
718  * Test Output:
719  * fst_asr_result has the result from detect_speech_result channel variable.
720  *
721  * @param recognizer name of recognizer
722  * @param grammar recognizer grammar
723  * @param prompt_filename name of prompt to play
724  * @param input_filename name of file containing input audio for the recognizer
725  */
726 #define fst_play_and_detect_speech_app_test(recognizer, grammar, prompt_filename, input_filename) \
727 { \
728  char *args = NULL; \
729  fst_requires(fst_core > 1); \
730  fst_requires_module("mod_dptools"); \
731  switch_channel_set_variable(fst_channel, "detect_speech_result", ""); \
732  fst_requires(switch_ivr_displace_session(fst_session, input_filename, 0, "mrf") == SWITCH_STATUS_SUCCESS); \
733  args = switch_core_session_sprintf(fst_session, "%s detect:%s %s", prompt_filename, recognizer, grammar); \
734  fst_requires(switch_core_session_execute_application(fst_session, "play_and_detect_speech", args) == SWITCH_STATUS_SUCCESS); \
735  fst_asr_result = switch_channel_get_variable(fst_channel, "detect_speech_result"); \
736  fst_check(fst_asr_result != NULL); \
737 }
738 
739 /**
740  * Use play_and_detect_speech core function to test recognizer
741  *
742  * Test Requires:
743  * switch_ivr_displace_session(input_filename) == SWITCH_STATUS_SUCCESS
744  *
745  * Test Checks:
746  * fst_asr_result != NULL after recognition completes
747  *
748  * Test Output:
749  * fst_asr_result has the result from detect_speech_result channel variable.
750  *
751  * @param recognizer name of recognizer
752  * @param grammar recognizer grammar
753  * @param prompt_filename name of prompt to play
754  * @param input_filename name of file containing input audio for the recognizer
755  * @param input_args input callback args
756  */
757 #define fst_play_and_detect_speech_test(recognizer, grammar, prompt_filename, input_filename, input_args) \
758 { \
759  char *args = NULL; \
760  fst_asr_result = NULL; \
761  fst_requires(fst_core > 1); \
762  fst_requires(switch_ivr_displace_session(fst_session, input_filename, 0, "mrf") == SWITCH_STATUS_SUCCESS); \
763  switch_status_t status = switch_ivr_play_and_detect_speech(fst_session, prompt_filename, recognizer, grammar, (char **)&fst_asr_result, 0, input_args); \
764  fst_check(fst_asr_result != NULL); \
765 }
766 
767 /**
768  * Define end of play_and_detect_speech recognizer test
769  */
770 #define fst_play_and_detect_speech_test_end() \
771 }
772 
773 
774 /**
775  * Compare extension dialplan apps and args with expected apps and args
776  * @param expected NULL terminated string array of app arg and names.
777  * const char *expected[] = { "playback", "https://example.com/foo.wav", "park", "", NULL };
778  * @param extension the switch_caller_extension_t to check
779  */
780 #define fst_check_extension_apps(expected, extension) \
781  { \
782  fst_xcheck(extension != NULL, "Missing extension\n"); \
783  if (extension) { \
784  int i; \
785  switch_caller_application_t *cur_app = extension->applications; \
786  for (i = 0; ; i += 2, cur_app = cur_app->next) { \
787  int cur_app_num = i / 2 + 1; \
788  if (!expected[i]) { \
789  if (cur_app != NULL) { \
790  fst_fail(switch_core_sprintf(fst_pool, "Unexpected application #%d \"%s\"\n", cur_app_num, cur_app->application_name)); \
791  } \
792  break; \
793  } \
794  fst_xcheck(cur_app != NULL, switch_core_sprintf(fst_pool, "Extension application #%d \"%s\" is missing", cur_app_num, expected[i])); \
795  if (!cur_app) { \
796  break; \
797  } \
798  fst_xcheck(cur_app->application_name && !strcmp(expected[i], cur_app->application_name), switch_core_sprintf(fst_pool, "Expected application #%d name is \"%s\", but is \"%s\"\n", cur_app_num, expected[i], cur_app->application_name)); \
799  fst_xcheck(cur_app->application_data && !strcmp(expected[i + 1], cur_app->application_data), switch_core_sprintf(fst_pool, "Expected application #%d %s data is \"%s\", but is \"%s\"\n", cur_app_num, expected[i], expected[i + 1], cur_app->application_data)); \
800  } \
801  } \
802  }
803 
804 
805 /**
806  * Inject DTMF into the session to be detected.
807  *
808  * Test Requires:
809  * switch_api_execute(sched_api) == SWITCH_STATUS_SUCCESS
810  * mod_commands is loaded
811  *
812  * @param when string describing when to send dtmf
813  * @param digits to send
814  */
815 #define fst_sched_recv_dtmf(when, digits) \
816 { \
817  switch_status_t api_result; \
818  switch_stream_handle_t stream = { 0 }; \
819  SWITCH_STANDARD_STREAM(stream); \
820  fst_requires(fst_core > 1); \
821  fst_requires_module("mod_commands"); \
822  api_result = switch_api_execute("sched_api", switch_core_session_sprintf(fst_session, "%s none uuid_recv_dtmf %s %s", when, switch_core_session_get_uuid(fst_session), digits), NULL, &stream); \
823  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(fst_session), SWITCH_LOG_INFO, "Injecting DTMF %s at %s\n", digits, when); \
824  fst_requires(api_result == SWITCH_STATUS_SUCCESS); \
825  switch_safe_free(stream.data); \
826 }
827 
828 #define fst_xml_start() \
829  switch_stream_handle_t fst_xml_stream = { 0 }; \
830  SWITCH_STANDARD_STREAM(fst_xml_stream);
832  int fst_tag_body = 0;
833 
834 #define fst_xml_open_tag(tag_name) \
835  fst_xml_stream.write_function(&fst_xml_stream, "<%s", #tag_name); \
836  fst_tag_children++;
837 
838 #define fst_xml_attr(attr) \
839  if (!zstr(attr)) fst_xml_stream.write_function(&fst_xml_stream, " %s=\"%s\"", #attr, attr);
840 
841 #define fst_xml_close_tag(tag_name) \
842  --fst_tag_children; \
843  if (fst_tag_children > 0 || fst_tag_body) { \
844  fst_xml_stream.write_function(&fst_xml_stream, "</%s>", #tag_name); \
845  } else { \
846  fst_xml_stream.write_function(&fst_xml_stream, "/>"); \
847  } \
848  fst_tag_body = 0;
849 
850 #define fst_xml_body(body) \
851  if (fst_tag_body) { \
852  fst_xml_stream.write_function(&fst_xml_stream, "%s", body); \
853  } else { \
854  fst_tag_body = 1; \
855  fst_xml_stream.write_function(&fst_xml_stream, ">%s", body); \
856  }
857 
858 #define fst_xml_end() \
859  switch_xml_parse_str_dynamic((char *)fst_xml_stream.data, SWITCH_FALSE);
860 
861 
862 /**
863  * Parse JSON file and save to varname
864  *
865  * Test Requires:
866  * JSON file can be opened and parsed
867  *
868  * Test Output:
869  * varname points at cJSON object
870  *
871  * @param varname name of var to store the resulting cJSON object
872  * @param file name of file to parse
873  */
874 #define fst_parse_json_file(varname, file) \
875 cJSON *varname = NULL; \
876 { \
877  char *buf; \
878  struct stat s; \
879  int size; \
880  int fd = open(file, O_RDONLY); \
881  fst_requires(fd >= 0); \
882  fstat(fd, &s); \
883  switch_zmalloc(buf, s.st_size + 1); \
884  fst_requires(buf); \
885  size = read(fd, buf, s.st_size); \
886  fst_requires(size == s.st_size); \
887  close(fd); \
888  varname = cJSON_Parse(buf); \
889  free(buf); \
890  fst_requires(varname); \
891 }
892 
893 #endif
switch_status_t switch_core_init(_In_ switch_core_flag_t flags, _In_ switch_bool_t console, _Out_ const char **err)
Initilize the core.
void switch_sleep(switch_interval_time_t t)
Definition: switch_time.c:640
switch_bool_t
Definition: switch_types.h:437
void switch_core_set_variable(_In_z_ const char *varname, _In_opt_z_ const char *value)
Add a global variable to the core.
void switch_core_set_globals(void)
Initiate Globals.
Definition: switch_core.c:633
uint32_t switch_core_flag_t
Definition: switch_types.h:395
#define zstr(x)
Definition: switch_utils.h:314
#define SWITCH_TEST_BASE_DIR_OVERRIDE
static switch_status_t fst_init_core_and_modload(const char *confdir, const char *basedir, int minimal, switch_core_flag_t flags)
Definition: switch_test.h:69
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:124
static char * fst_getenv_default(const char *env, char *default_value, switch_bool_t required)
Definition: switch_test.h:41
switch_status_t switch_core_init_and_modload(_In_ switch_core_flag_t flags, _In_ switch_bool_t console, _Out_ const char **err)
Initilize the core and load modules.
int fst_tag_body
Definition: switch_test.h:832
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:82
int fst_tag_children
Definition: switch_test.h:831
switch_status_t
Common return values.
Main Library Header.
unsigned long switch_getpid(void)
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)