Asterisk - The Open Source Telephony Project  18.5.0
test_message.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2014, Digium, Inc.
5  *
6  * Matt Jordan <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Test module for out-of-call text message module
22  *
23  * \author \verbatim Matt Jordan <[email protected]> \endverbatim
24  *
25  * \ingroup tests
26  */
27 
28 /*** MODULEINFO
29  <depend>TEST_FRAMEWORK</depend>
30  <support_level>core</support_level>
31  ***/
32 
33 #include "asterisk.h"
34 
35 #include <regex.h>
36 
37 #include "asterisk/module.h"
38 #include "asterisk/test.h"
39 #include "asterisk/message.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/manager.h"
42 #include "asterisk/vector.h"
43 
44 #define TEST_CATEGORY "/main/message/"
45 
46 #define TEST_CONTEXT "__TEST_MESSAGE_CONTEXT__"
47 #define TEST_EXTENSION "test_message_extension"
48 
49 /*! \brief The number of user events we should get in a dialplan test */
50 #define DEFAULT_EXPECTED_EVENTS 4
51 
52 /*! \brief The current number of received user events */
54 
55 /*! \brief The number of user events we expect for this test */
57 
58 /*! \brief Predicate for the \ref test_message_handler receiving a message */
60 
61 /*! \brief Condition wait variable for all dialplan user events being received */
63 
64 /*! \brief Mutex for \c user_event_cond */
66 
67 /*! \brief Condition wait variable for \ref test_msg_handler receiving message */
69 
70 /*! \brief Mutex for \c handler_cond */
72 
73 /*! \brief The expected user event fields */
74 AST_VECTOR(var_vector, struct ast_variable *) expected_user_event_fields;
75 
76 /*! \brief If a user event fails, the bad headers that didn't match */
77 AST_VECTOR(, struct ast_variable *) bad_headers;
78 
79 static int test_msg_send(const struct ast_msg *msg, const char *to, const char *from);
80 
81 static struct ast_msg_tech test_msg_tech = {
82  .name = "testmsg",
83  .msg_send = test_msg_send,
84 };
85 
86 static int test_msg_handle_msg_cb(struct ast_msg *msg);
87 static int test_msg_has_destination_cb(const struct ast_msg *msg);
88 
89 /*! \brief Our test message handler */
91  .name = "testmsg",
92  .handle_msg = test_msg_handle_msg_cb,
93  .has_destination = test_msg_has_destination_cb,
94 };
95 
96 static int user_event_hook_cb(int category, const char *event, char *body);
97 
98 /*! \brief AMI event hook that verifies whether or not we've gotten our user events */
100  .file = AST_MODULE,
101  .helper = user_event_hook_cb,
102 };
103 
104 /*!
105  * \brief Verifies a user event header/value pair
106  *
107  * \param user_event which user event to check
108  * \param header The header to verify
109  * \param value The value read from the event
110  *
111  * \retval -1 on error or evaluation failure
112  * \retval 0 if match not needed or success
113  */
114 static int verify_user_event_fields(int user_event, const char *header, const char *value)
115 {
116  struct ast_variable *current;
117  struct ast_variable *expected;
118  regex_t regexbuf;
119  int error;
120 
121  if (user_event >= AST_VECTOR_SIZE(&expected_user_event_fields)) {
122  return -1;
123  }
124 
125  expected = AST_VECTOR_GET(&expected_user_event_fields, user_event);
126  if (!expected) {
127  return -1;
128  }
129 
130  for (current = expected; current; current = current->next) {
131  struct ast_variable *bad_header;
132 
133  if (strcmp(current->name, header)) {
134  continue;
135  }
136 
137  error = regcomp(&regexbuf, current->value, REG_EXTENDED | REG_NOSUB);
138  if (error) {
139  char error_buf[128];
140  regerror(error, &regexbuf, error_buf, sizeof(error_buf));
141  ast_log(LOG_ERROR, "Failed to compile regex '%s' for header check '%s': %s\n",
142  current->value, current->name, error_buf);
143  return -1;
144  }
145 
146  if (!regexec(&regexbuf, value, 0, NULL, 0)) {
147  regfree(&regexbuf);
148  return 0;
149  }
150 
151  bad_header = ast_variable_new(header, value, __FILE__);
152  if (bad_header) {
153  struct ast_variable *bad_headers_head = NULL;
154 
155  if (user_event < AST_VECTOR_SIZE(&bad_headers)) {
156  bad_headers_head = AST_VECTOR_GET(&bad_headers, user_event);
157  }
158  ast_variable_list_append(&bad_headers_head, bad_header);
159  AST_VECTOR_REPLACE(&bad_headers, user_event, bad_headers_head);
160  }
161  regfree(&regexbuf);
162  return -1;
163  }
164 
165  return 0;
166 }
167 
168 static int message_received;
169 
170 static int test_msg_send(const struct ast_msg *msg, const char *to, const char *from)
171 {
172  message_received = 1;
173 
174  return 0;
175 }
176 
177 static int test_msg_handle_msg_cb(struct ast_msg *msg)
178 {
183 
184  return 0;
185 }
186 
187 static int test_msg_has_destination_cb(const struct ast_msg *msg)
188 {
189  /* We only care about one destination: foo! */
190  if (ast_strlen_zero(ast_msg_get_to(msg))) {
191  return 0;
192  }
193  return (!strcmp(ast_msg_get_to(msg), "foo") ? 1 : 0);
194 }
195 
196 static int user_event_hook_cb(int category, const char *event, char *body)
197 {
198  char *parse;
199  char *kvp;
200 
201  if (strcmp(event, "UserEvent")) {
202  return -1;
203  }
204 
205  parse = ast_strdupa(body);
206  while ((kvp = strsep(&parse, "\r\n"))) {
207  char *key, *value;
208 
209  kvp = ast_trim_blanks(kvp);
210  if (ast_strlen_zero(kvp)) {
211  continue;
212  }
213  key = strsep(&kvp, ":");
214  value = ast_skip_blanks(kvp);
216  }
217 
219 
223  }
225 
226  return 0;
227 }
228 
229 /*! \brief Wait for the \ref test_msg_handler to receive the message */
231 {
232  int error = 0;
233  struct timeval wait = ast_tvadd(ast_tvnow(), ast_tv(5 /* seconds */, 0));
234  struct timespec wait_time = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000 };
235 
237  while (!handler_received_message) {
238  error = ast_cond_timedwait(&handler_cond, &handler_lock, &wait_time);
239  if (error == ETIMEDOUT) {
240  ast_test_status_update(test, "Test timed out while waiting for handler to get message\n");
242  break;
243  }
244  }
246 
247  return (error != ETIMEDOUT);
248 }
249 
250 /*! \brief Wait for the expected number of user events to be received */
251 static int user_event_wait_for_events(struct ast_test *test, int expected_events)
252 {
253  int error;
254  struct timeval wait = ast_tvadd(ast_tvnow(), ast_tv(5 /* seconds */, 0));
255  struct timespec wait_time = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000 };
256 
257  expected_user_events = expected_events;
258 
261  error = ast_cond_timedwait(&user_event_cond, &user_event_lock, &wait_time);
262  if (error == ETIMEDOUT) {
263  ast_test_status_update(test, "Test timed out while waiting for %d expected user events\n", expected_events);
265  break;
266  }
267  }
269 
270  ast_test_status_update(test, "Received %d of %d user events\n", received_user_events, expected_events);
271  return !(received_user_events == expected_events);
272 }
273 
274 static int verify_bad_headers(struct ast_test *test)
275 {
276  int res = 0;
277  int i;
278 
279  for (i = 0; i < AST_VECTOR_SIZE(&bad_headers); i++) {
280  struct ast_variable *headers;
281  struct ast_variable *current;
282 
283  headers = AST_VECTOR_GET(&bad_headers, i);
284  if (!headers) {
285  continue;
286  }
287 
288  res = -1;
289  for (current = headers; current; current = current->next) {
290  ast_test_status_update(test, "Expected UserEvent %d: Failed to match %s: %s\n",
291  i, current->name, current->value);
293  }
294  }
295 
296  return res;
297 }
298 
299 AST_TEST_DEFINE(test_message_msg_tech_registration)
300 {
301  int reg_result;
302 
303  switch (cmd) {
304  case TEST_INIT:
305  info->name = __func__;
306  info->category = TEST_CATEGORY;
307  info->summary = "Test register/unregister of a message tech";
308  info->description =
309  "Test that:\n"
310  "\tA message technology can be registered once only\n"
311  "\tA registered message technology can be unregistered once only";
312  return AST_TEST_NOT_RUN;
313  case TEST_EXECUTE:
314  break;
315  }
316 
317  reg_result = ast_msg_tech_register(&test_msg_tech);
318  ast_test_validate(test, reg_result == 0);
319 
320  reg_result = ast_msg_tech_register(&test_msg_tech);
321  ast_test_validate(test, reg_result == -1);
322 
323  reg_result = ast_msg_tech_unregister(&test_msg_tech);
324  ast_test_validate(test, reg_result == 0);
325 
326  reg_result = ast_msg_tech_unregister(&test_msg_tech);
327  ast_test_validate(test, reg_result == -1);
328 
329  return AST_TEST_PASS;
330 }
331 
332 AST_TEST_DEFINE(test_message_msg_handler_registration)
333 {
334  int reg_result;
335 
336  switch (cmd) {
337  case TEST_INIT:
338  info->name = __func__;
339  info->category = TEST_CATEGORY;
340  info->summary = "Test register/unregister of a message handler";
341  info->description =
342  "Test that:\n"
343  "\tA message handler can be registered once only\n"
344  "\tA registered message handler can be unregistered once only";
345  return AST_TEST_NOT_RUN;
346  case TEST_EXECUTE:
347  break;
348  }
349 
350  reg_result = ast_msg_handler_register(&test_msg_handler);
351  ast_test_validate(test, reg_result == 0);
352 
353  reg_result = ast_msg_handler_register(&test_msg_handler);
354  ast_test_validate(test, reg_result == -1);
355 
356  reg_result = ast_msg_handler_unregister(&test_msg_handler);
357  ast_test_validate(test, reg_result == 0);
358 
359  reg_result = ast_msg_handler_unregister(&test_msg_handler);
360  ast_test_validate(test, reg_result == -1);
361 
362  return AST_TEST_PASS;
363 }
364 
365 static void ast_msg_safe_destroy(void *obj)
366 {
367  struct ast_msg *msg = obj;
368 
369  if (msg) {
370  ast_msg_destroy(msg);
371  }
372 }
373 
374 AST_TEST_DEFINE(test_message_manipulation)
375 {
376  RAII_VAR(struct ast_msg *, msg, NULL, ast_msg_safe_destroy);
378  int result;
379  const char *actual;
380  const char *out_name;
381  const char *out_value;
382 
383  switch (cmd) {
384  case TEST_INIT:
385  info->name = __func__;
386  info->category = TEST_CATEGORY;
387  info->summary = "Test manipulating properties of a message";
388  info->description =
389  "This test covers the following:\n"
390  "\tSetting/getting the body\n"
391  "\tSetting/getting inbound/outbound variables\n"
392  "\tIterating over variables";
393  return AST_TEST_NOT_RUN;
394  case TEST_EXECUTE:
395  break;
396  }
397 
398  msg = ast_msg_alloc();
399  ast_test_validate(test, msg != NULL);
400 
401  /* Test setting/getting to */
402  result = ast_msg_set_to(msg, "testmsg:%s", "foo");
403  ast_test_validate(test, result == 0);
404  actual = ast_msg_get_to(msg);
405  ast_test_validate(test, !strcmp(actual, "testmsg:foo"));
406 
407  /* Test setting/getting from */
408  result = ast_msg_set_from(msg, "testmsg:%s", "bar");
409  ast_test_validate(test, result == 0);
410  actual = ast_msg_get_from(msg);
411  ast_test_validate(test, !strcmp(actual, "testmsg:bar"));
412 
413  /* Test setting/getting body */
414  result = ast_msg_set_body(msg, "BodyTest: %s", "foo");
415  ast_test_validate(test, result == 0);
416  actual = ast_msg_get_body(msg);
417  ast_test_validate(test, !strcmp(actual, "BodyTest: foo"));
418 
419  /* Test setting/getting technology */
420  result = ast_msg_set_tech(msg, "%s", "my_tech");
421  ast_test_validate(test, result == 0);
422  actual = ast_msg_get_tech(msg);
423  ast_test_validate(test, !strcmp(actual, "my_tech"));
424 
425  /* Test setting/getting endpoint */
426  result = ast_msg_set_endpoint(msg, "%s", "terminus");
427  ast_test_validate(test, result == 0);
428  actual = ast_msg_get_endpoint(msg);
429  ast_test_validate(test, !strcmp(actual, "terminus"));
430 
431  /* Test setting/getting non-outbound variable */
432  result = ast_msg_set_var(msg, "foo", "bar");
433  ast_test_validate(test, result == 0);
434  actual = ast_msg_get_var(msg, "foo");
435  ast_test_validate(test, !strcmp(actual, "bar"));
436 
437  /* Test updating existing variable */
438  result = ast_msg_set_var(msg, "foo", "new_bar");
439  ast_test_validate(test, result == 0);
440  actual = ast_msg_get_var(msg, "foo");
441  ast_test_validate(test, !strcmp(actual, "new_bar"));
442 
443  /* Verify a non-outbound variable is not iterable */
444  it_vars = ast_msg_var_iterator_init(msg);
445  ast_test_validate(test, it_vars != NULL);
446  ast_test_validate(test, ast_msg_var_iterator_next(msg, it_vars, &out_name, &out_value) == 0);
448 
449  /* Test updating an existing variable as an outbound variable */
450  result = ast_msg_set_var_outbound(msg, "foo", "outbound_bar");
451  ast_test_validate(test, result == 0);
452  it_vars = ast_msg_var_iterator_init(msg);
453  ast_test_validate(test, it_vars != NULL);
454  result = ast_msg_var_iterator_next(msg, it_vars, &out_name, &out_value);
455  ast_test_validate(test, result == 1);
456  ast_test_validate(test, !strcmp(out_name, "foo"));
457  ast_test_validate(test, !strcmp(out_value, "outbound_bar"));
458  ast_msg_var_unref_current(it_vars);
459  result = ast_msg_var_iterator_next(msg, it_vars, &out_name, &out_value);
460  ast_test_validate(test, result == 0);
461 
462  return AST_TEST_PASS;
463 }
464 
465 AST_TEST_DEFINE(test_message_queue_dialplan_nominal)
466 {
467  RAII_VAR(struct ast_msg *, msg, NULL, ast_msg_safe_destroy);
468  struct ast_variable *expected;
469  struct ast_variable *expected_response = NULL;
470 
471  switch (cmd) {
472  case TEST_INIT:
473  info->name = __func__;
474  info->category = TEST_CATEGORY;
475  info->summary = "Test enqueueing messages to the dialplan";
476  info->description =
477  "Test that a message enqueued for the dialplan is\n"
478  "passed to that particular extension";
479  return AST_TEST_NOT_RUN;
480  case TEST_EXECUTE:
481  break;
482  }
483 
484  msg = ast_msg_alloc();
485  ast_test_validate(test, msg != NULL);
486 
487  expected = ast_variable_new("Verify","^To$", __FILE__);
488  ast_variable_list_append(&expected_response, expected);
489  expected = ast_variable_new("Value","^foo$", __FILE__);
490  ast_variable_list_append(&expected_response, expected);
491  AST_VECTOR_REPLACE(&expected_user_event_fields, 0, expected_response);
492 
493  expected_response = NULL;
494  expected = ast_variable_new("Verify", "^From$", __FILE__);
495  ast_variable_list_append(&expected_response, expected);
496  expected = ast_variable_new("Value","^bar$", __FILE__);
497  ast_variable_list_append(&expected_response, expected);
498  AST_VECTOR_REPLACE(&expected_user_event_fields, 1, expected_response);
499 
500  expected_response = NULL;
501  expected = ast_variable_new("Verify", "^Body$", __FILE__);
502  ast_variable_list_append(&expected_response, expected);
503  expected = ast_variable_new("Value", "^a body$", __FILE__);
504  ast_variable_list_append(&expected_response, expected);
505  AST_VECTOR_REPLACE(&expected_user_event_fields, 2, expected_response);
506 
507  expected_response = NULL;
508  expected = ast_variable_new("Verify", "^Custom$", __FILE__);
509  ast_variable_list_append(&expected_response, expected);
510  expected = ast_variable_new("Value", "^field$", __FILE__);
511  ast_variable_list_append(&expected_response, expected);
512  AST_VECTOR_REPLACE(&expected_user_event_fields, 3, expected_response);
513 
514  ast_msg_set_to(msg, "foo");
515  ast_msg_set_from(msg, "bar");
516  ast_msg_set_body(msg, "a body");
517  ast_msg_set_var_outbound(msg, "custom_data", "field");
518 
521 
522  ast_msg_queue(msg);
523  msg = NULL;
524 
526  ast_test_status_update(test, "Failed to received %d expected user events\n", DEFAULT_EXPECTED_EVENTS);
527  return AST_TEST_FAIL;
528  }
529 
530  if (verify_bad_headers(test)) {
531  return AST_TEST_FAIL;
532  }
533 
534  return AST_TEST_PASS;
535 }
536 
537 AST_TEST_DEFINE(test_message_queue_handler_nominal)
538 {
539  RAII_VAR(struct ast_msg *, msg, NULL, ast_msg_safe_destroy);
540  int result;
541 
542  switch (cmd) {
543  case TEST_INIT:
544  info->name = __func__;
545  info->category = TEST_CATEGORY;
546  info->summary = "Test enqueueing messages to a handler";
547  info->description =
548  "Test that a message enqueued can be handled by a\n"
549  "non-dialplan handler";
550  return AST_TEST_NOT_RUN;
551  case TEST_EXECUTE:
552  break;
553  }
554 
555  msg = ast_msg_alloc();
556  ast_test_validate(test, msg != NULL);
557 
558  result = ast_msg_handler_register(&test_msg_handler);
559  ast_test_validate(test, result == 0);
560 
561  ast_msg_set_to(msg, "foo");
562  ast_msg_set_from(msg, "bar");
563  ast_msg_set_body(msg, "a body");
564 
565  ast_msg_queue(msg);
566  msg = NULL;
567 
568  /* This will automatically fail the test if we don't get the message */
570 
571  result = ast_msg_handler_unregister(&test_msg_handler);
572  ast_test_validate(test, result == 0);
573 
574  return AST_TEST_PASS;
575 }
576 
577 AST_TEST_DEFINE(test_message_queue_both_nominal)
578 {
579  RAII_VAR(struct ast_msg *, msg, NULL, ast_msg_safe_destroy);
580  struct ast_variable *expected;
581  struct ast_variable *expected_response = NULL;
582  int result;
583 
584  switch (cmd) {
585  case TEST_INIT:
586  info->name = __func__;
587  info->category = TEST_CATEGORY;
588  info->summary = "Test enqueueing messages to a dialplan and custom handler";
589  info->description =
590  "Test that a message enqueued is passed to all\n"
591  "handlers that can process it, dialplan as well as\n"
592  "a custom handler";
593  return AST_TEST_NOT_RUN;
594  case TEST_EXECUTE:
595  break;
596  }
597 
598  msg = ast_msg_alloc();
599  ast_test_validate(test, msg != NULL);
600 
601  result = ast_msg_handler_register(&test_msg_handler);
602  ast_test_validate(test, result == 0);
603 
604  expected = ast_variable_new("Verify","^To$", __FILE__);
605  ast_variable_list_append(&expected_response, expected);
606  expected = ast_variable_new("Value","^foo$", __FILE__);
607  ast_variable_list_append(&expected_response, expected);
608  AST_VECTOR_REPLACE(&expected_user_event_fields, 0, expected_response);
609 
610  expected_response = NULL;
611  expected = ast_variable_new("Verify", "^From$", __FILE__);
612  ast_variable_list_append(&expected_response, expected);
613  expected = ast_variable_new("Value","^bar$", __FILE__);
614  ast_variable_list_append(&expected_response, expected);
615  AST_VECTOR_REPLACE(&expected_user_event_fields, 1, expected_response);
616 
617  expected_response = NULL;
618  expected = ast_variable_new("Verify", "^Body$", __FILE__);
619  ast_variable_list_append(&expected_response, expected);
620  expected = ast_variable_new("Value", "^a body$", __FILE__);
621  ast_variable_list_append(&expected_response, expected);
622  AST_VECTOR_REPLACE(&expected_user_event_fields, 2, expected_response);
623 
624  ast_msg_set_to(msg, "foo");
625  ast_msg_set_from(msg, "bar");
626  ast_msg_set_body(msg, "a body");
627 
630 
631  ast_msg_queue(msg);
632  msg = NULL;
633 
635  ast_test_status_update(test, "Failed to received %d expected user events\n", DEFAULT_EXPECTED_EVENTS);
637  }
638 
639  /* This will automatically fail the test if we don't get the message */
641 
642  result = ast_msg_handler_unregister(&test_msg_handler);
643  ast_test_validate(test, result == 0);
644 
645  if (verify_bad_headers(test)) {
646  return AST_TEST_FAIL;
647  }
648 
649  return AST_TEST_PASS;
650 }
651 
652 AST_TEST_DEFINE(test_message_has_destination_dialplan)
653 {
654  RAII_VAR(struct ast_msg *, msg, NULL, ast_msg_safe_destroy);
655 
656  switch (cmd) {
657  case TEST_INIT:
658  info->name = __func__;
659  info->category = TEST_CATEGORY;
660  info->summary = "Test checking for a dialplan destination";
661  info->description =
662  "Test that a message's destination is verified via the\n"
663  "dialplan";
664  return AST_TEST_NOT_RUN;
665  case TEST_EXECUTE:
666  break;
667  }
668 
669  msg = ast_msg_alloc();
670  ast_test_validate(test, msg != NULL);
671 
674  ast_test_validate(test, ast_msg_has_destination(msg) == 1);
675 
676  ast_msg_set_context(msg, "__I_SHOULD_NOT_EXIST_PLZ__");
677  ast_test_validate(test, ast_msg_has_destination(msg) == 0);
678 
680  ast_msg_set_exten(msg, "__I_SHOULD_NOT_EXIST_PLZ__");
681  ast_test_validate(test, ast_msg_has_destination(msg) == 0);
682 
683  ast_msg_set_exten(msg, NULL);
684  ast_test_validate(test, ast_msg_has_destination(msg) == 0);
685 
688  ast_test_validate(test, ast_msg_has_destination(msg) == 0);
689 
690  return AST_TEST_PASS;
691 }
692 
693 AST_TEST_DEFINE(test_message_has_destination_handler)
694 {
695  RAII_VAR(struct ast_msg *, msg, NULL, ast_msg_safe_destroy);
696  int result;
697 
698  switch (cmd) {
699  case TEST_INIT:
700  info->name = __func__;
701  info->category = TEST_CATEGORY;
702  info->summary = "Test checking for a handler destination";
703  info->description =
704  "Test that a message's destination is verified via a\n"
705  "handler";
706  return AST_TEST_NOT_RUN;
707  case TEST_EXECUTE:
708  break;
709  }
710 
711  result = ast_msg_handler_register(&test_msg_handler);
712  ast_test_validate(test, result == 0);
713 
714  msg = ast_msg_alloc();
715  ast_test_validate(test, msg != NULL);
716 
717  ast_msg_set_to(msg, "foo");
719  ast_msg_set_exten(msg, NULL);
720  ast_test_validate(test, ast_msg_has_destination(msg) == 1);
721 
723  ast_test_validate(test, ast_msg_has_destination(msg) == 1);
724 
725  ast_msg_set_to(msg, "__I_SHOULD_NOT_EXIST_PLZ__");
726  ast_test_validate(test, ast_msg_has_destination(msg) == 0);
727 
728  result = ast_msg_handler_unregister(&test_msg_handler);
729  ast_test_validate(test, result == 0);
730 
731  return AST_TEST_PASS;
732 }
733 
734 AST_TEST_DEFINE(test_message_msg_send)
735 {
736  RAII_VAR(struct ast_msg *, msg, NULL, ast_msg_safe_destroy);
737 
738  switch (cmd) {
739  case TEST_INIT:
740  info->name = __func__;
741  info->category = TEST_CATEGORY;
742  info->summary = "Test message routing";
743  info->description =
744  "Test that a message can be routed if it has\n"
745  "a valid handler";
746  return AST_TEST_NOT_RUN;
747  case TEST_EXECUTE:
748  break;
749  }
750 
751  ast_test_validate(test, ast_msg_tech_register(&test_msg_tech) == 0);
752  ast_test_validate(test, ast_msg_handler_register(&test_msg_handler) == 0);
753 
754  msg = ast_msg_alloc();
755  ast_test_validate(test, msg != NULL);
756 
757  ast_msg_set_to(msg, "foo");
759  ast_msg_set_exten(msg, NULL);
760  ast_test_validate(test, ast_msg_has_destination(msg) == 1);
761 
762  if (!ast_msg_send(msg, "testmsg:foo", "blah")) {
763  msg = NULL;
764  } else {
765  ast_test_status_update(test, "Failed to send message\n");
767  }
768 
769  ast_test_validate(test, ast_msg_handler_unregister(&test_msg_handler) == 0);
770  ast_test_validate(test, ast_msg_tech_unregister(&test_msg_tech) == 0);
771 
772  return AST_TEST_PASS;
773 }
774 
775 static int test_init_cb(struct ast_test_info *info, struct ast_test *test)
776 {
779  message_received = 0;
780 
781  AST_VECTOR_INIT(&expected_user_event_fields, DEFAULT_EXPECTED_EVENTS);
783 
784  return 0;
785 }
786 
787 #define FREE_VARIABLE_VECTOR(vector) do { \
788  int i; \
789  for (i = 0; i < AST_VECTOR_SIZE(&(vector)); i++) { \
790  struct ast_variable *headers; \
791  headers = AST_VECTOR_GET(&(vector), i); \
792  if (!headers) { \
793  continue; \
794  } \
795  ast_variables_destroy(headers); \
796  } \
797  AST_VECTOR_FREE(&(vector)); \
798  } while (0)
799 
800 
801 static int test_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
802 {
803  FREE_VARIABLE_VECTOR(expected_user_event_fields);
804  FREE_VARIABLE_VECTOR(bad_headers);
805 
806  return 0;
807 }
808 
809 static int unload_module(void)
810 {
811  AST_TEST_UNREGISTER(test_message_msg_tech_registration);
812  AST_TEST_UNREGISTER(test_message_msg_handler_registration);
813  AST_TEST_UNREGISTER(test_message_manipulation);
814  AST_TEST_UNREGISTER(test_message_queue_dialplan_nominal);
815  AST_TEST_UNREGISTER(test_message_queue_handler_nominal);
816  AST_TEST_UNREGISTER(test_message_queue_both_nominal);
817  AST_TEST_UNREGISTER(test_message_has_destination_dialplan);
818  AST_TEST_UNREGISTER(test_message_has_destination_handler);
819  AST_TEST_UNREGISTER(test_message_msg_send);
820 
822 
823  ast_manager_unregister_hook(&user_event_hook);
824 
825  return 0;
826 }
827 
828 static int create_test_dialplan(void)
829 {
830  int res = 0;
831 
833  return -1;
834  }
835 
837  "UserEvent", "TestMessageUnitTest,Verify:To,Value:${MESSAGE(to)}",
838  NULL, AST_MODULE);
840  "UserEvent", "TestMessageUnitTest,Verify:From,Value:${MESSAGE(from)}",
841  NULL, AST_MODULE);
843  "UserEvent", "TestMessageUnitTest,Verify:Body,Value:${MESSAGE(body)}",
844  NULL, AST_MODULE);
846  "UserEvent", "TestMessageUnitTest,Verify:Custom,Value:${MESSAGE_DATA(custom_data)}",
847  NULL, AST_MODULE);
849  "Set", "MESSAGE_DATA(custom_data)=${MESSAGE_DATA(custom_data)}",
850  NULL, AST_MODULE);
852  "MessageSend", "testmsg:${MESSAGE(from)},testmsg:${MESSAGE(to)}",
853  NULL, AST_MODULE);
854 
855  ast_manager_register_hook(&user_event_hook);
856 
857  return res;
858 }
859 
860 static int load_module(void)
861 {
862  AST_TEST_REGISTER(test_message_msg_tech_registration);
863  AST_TEST_REGISTER(test_message_msg_handler_registration);
864  AST_TEST_REGISTER(test_message_manipulation);
865  AST_TEST_REGISTER(test_message_queue_dialplan_nominal);
866  AST_TEST_REGISTER(test_message_queue_handler_nominal);
867  AST_TEST_REGISTER(test_message_queue_both_nominal);
868  AST_TEST_REGISTER(test_message_has_destination_dialplan);
869  AST_TEST_REGISTER(test_message_has_destination_handler);
870  AST_TEST_REGISTER(test_message_msg_send);
871 
873 
876 
878 }
879 
880 
881 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Out-of-call text message support");
static ast_cond_t user_event_cond
Condition wait variable for all dialplan user events being received.
Definition: test_message.c:62
int ast_msg_handler_unregister(const struct ast_msg_handler *handler)
Unregister a ast_msg_handler.
Definition: message.c:1671
struct ast_variable * next
Contains all the initialization information required to store a new test definition.
Definition: test.h:221
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
Definition: message.c:509
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_msg_get_var(struct ast_msg *msg, const char *name)
Get the specified variable on the message.
Definition: message.c:620
const char * ast_msg_get_tech(const struct ast_msg *msg)
Retrieve the technology associated with this message.
Definition: message.c:546
static int test_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
Definition: test_message.c:801
static int handler_received_message
Predicate for the test_message_handler receiving a message.
Definition: test_message.c:59
void ast_manager_unregister_hook(struct manager_custom_hook *hook)
Delete a custom hook to be called when an event is fired.
Definition: manager.c:1942
#define TEST_EXTENSION
Definition: test_message.c:47
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
Definition: message.c:487
const char * ast_msg_get_endpoint(const struct ast_msg *msg)
Retrieve the endpoint associated with this message.
Definition: message.c:551
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the &#39;body&#39; text of a message (in UTF-8)
Definition: message.c:476
int ast_test_register_init(const char *category, ast_test_init_cb_t *cb)
Definition: test.c:160
void ast_manager_register_hook(struct manager_custom_hook *hook)
Add a custom hook to be called when an event is fired.
Definition: manager.c:1934
An external processor of received messages.
Definition: message.h:98
static int verify_bad_headers(struct ast_test *test)
Definition: test_message.c:274
static int test_msg_handle_msg_cb(struct ast_msg *msg)
Definition: test_message.c:177
static int user_event_hook_cb(int category, const char *event, char *body)
Definition: test_message.c:196
static int verify_user_event_fields(int user_event, const char *header, const char *value)
Verifies a user event header/value pair.
Definition: test_message.c:114
int ast_msg_handler_register(const struct ast_msg_handler *handler)
Register a ast_msg_handler.
Definition: message.c:1629
static ast_mutex_t handler_lock
Mutex for handler_cond.
Definition: test_message.c:71
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
Definition: message.c:418
Structure for variables, used for configurations and for channel variables.
int ast_msg_var_iterator_next(const struct ast_msg *msg, struct ast_msg_var_iterator *iter, const char **name, const char **value)
Get the next variable name and value that is set for sending outbound.
Definition: message.c:689
AST_TEST_DEFINE(test_message_msg_tech_registration)
Definition: test_message.c:299
Test Framework API.
const char *const name
Name of this message technology.
Definition: message.h:61
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
Definition: astman.c:222
static int test_msg_send(const struct ast_msg *msg, const char *to, const char *from)
Definition: test_message.c:170
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
Definition: message.c:1569
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
Out-of-call text message support.
int value
Definition: syslog.c:37
#define TEST_CATEGORY
Definition: test_message.c:44
#define ast_cond_signal(cond)
Definition: lock.h:201
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
Definition: message.c:531
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
Destroy a message variable iterator.
Definition: message.c:706
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the &#39;to&#39; URI of a message.
Definition: message.c:454
pthread_cond_t ast_cond_t
Definition: lock.h:176
#define ast_strlen_zero(foo)
Definition: strings.h:52
const char * ast_msg_get_to(const struct ast_msg *msg)
Retrieve the destination of this message.
Definition: message.c:541
static int message_received
Definition: test_message.c:168
int ast_msg_send(struct ast_msg *msg, const char *to, const char *from)
Send a msg directly to an endpoint.
Definition: message.c:1369
#define ast_log
Definition: astobj2.c:42
#define TEST_CONTEXT
Definition: test_message.c:46
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
Unref a message var from inside an iterator loop.
Definition: message.c:700
static int expected_user_events
The number of user events we expect for this test.
Definition: test_message.c:56
#define FREE_VARIABLE_VECTOR(vector)
Definition: test_message.c:787
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_variable_new(name, value, filename)
int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
Set a variable on the message going to the dialplan.
Definition: message.c:615
Core PBX routines and definitions.
int ast_test_register_cleanup(const char *category, ast_test_cleanup_cb_t *cb)
Definition: test.c:177
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
Definition: message.c:958
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define LOG_ERROR
Definition: logger.h:285
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
Definition: message.c:1610
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
const char * ast_msg_get_from(const struct ast_msg *msg)
Retrieve the source of this message.
Definition: message.c:536
static int received_user_events
The current number of received user events.
Definition: test_message.c:53
static struct ast_msg_handler test_msg_handler
Our test message handler.
Definition: test_message.c:90
def info(msg)
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2283
A message technology.
Definition: message.h:52
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:157
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:182
static ast_cond_t handler_cond
Condition wait variable for test_msg_handler receiving message.
Definition: test_message.c:68
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
void ast_test_set_result(struct ast_test *test, enum ast_test_result_state state)
Definition: test.c:262
static int handler_wait_for_message(struct ast_test *test)
Wait for the test_msg_handler to receive the message.
Definition: test_message.c:230
Vector container support.
int ast_msg_set_exten(struct ast_msg *msg, const char *fmt,...)
Set the dialplan extension for this message.
Definition: message.c:498
#define DEFAULT_EXPECTED_EVENTS
The number of user events we should get in a dialplan test.
Definition: test_message.c:50
static int load_module(void)
Definition: test_message.c:860
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the &#39;from&#39; URI of a message.
Definition: message.c:465
const char * name
Name of the message handler.
Definition: message.h:102
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
static ast_mutex_t user_event_lock
Mutex for user_event_cond.
Definition: test_message.c:65
char * strsep(char **str, const char *delims)
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology&#39;s endpoint associated with this message.
Definition: message.c:520
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:6970
Definition: test.c:65
int ast_msg_has_destination(const struct ast_msg *msg)
Determine if a particular message has a destination via some handler.
Definition: message.c:937
#define AST_MODULE
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:226
int ast_msg_set_var_outbound(struct ast_msg *msg, const char *name, const char *value)
Set a variable on the message being sent to a message tech directly.
Definition: message.c:610
static PGresult * result
Definition: cel_pgsql.c:88
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:284
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: conf2ael.c:625
int error(const char *format,...)
Definition: utils/frame.c:999
A message.
Definition: message.c:233
static int test_init_cb(struct ast_test_info *info, struct ast_test *test)
Definition: test_message.c:775
static int user_event_wait_for_events(struct ast_test *test, int expected_events)
Wait for the expected number of user events to be received.
Definition: test_message.c:251
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6198
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
Definition: message.c:448
static void ast_msg_safe_destroy(void *obj)
Definition: test_message.c:365
static struct manager_custom_hook user_event_hook
AMI event hook that verifies whether or not we&#39;ve gotten our user events.
Definition: test_message.c:99
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
AST_VECTOR(var_vector, struct ast_variable *)
The expected user event fields.
Definition: test_message.c:74
Asterisk module definitions.
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
#define ast_variable_list_append(head, new_var)
static int create_test_dialplan(void)
Definition: test_message.c:828
#define ast_mutex_unlock(a)
Definition: lock.h:188
static int unload_module(void)
Definition: test_message.c:809
static int test_msg_has_destination_cb(const struct ast_msg *msg)
Definition: test_message.c:187
struct ast_msg_var_iterator * ast_msg_var_iterator_init(const struct ast_msg *msg)
Create a new message variable iterator.
Definition: message.c:644