Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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 <mjordan@digium.com>
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 <mjordan@digium.com> \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_msg_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 */
75
76/*! \brief If a user event fails, the bad headers that didn't match */
78
79static int test_msg_send(const struct ast_msg *msg, const char *to, const char *from);
80
81static struct ast_msg_tech test_msg_tech = {
82 .name = "testmsg",
83 .msg_send = test_msg_send,
84};
85
86static int test_msg_handle_msg_cb(struct ast_msg *msg);
87static 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
96static 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 */
114static 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
169
170static int test_msg_send(const struct ast_msg *msg, const char *to, const char *from)
171{
173
174 return 0;
175}
176
177static int test_msg_handle_msg_cb(struct ast_msg *msg)
178{
183
184 return 0;
185}
186
187static int test_msg_has_destination_cb(const struct ast_msg *msg)
188{
189 /* We only care about one destination: foo! */
191 return 0;
192 }
193 return (!strcmp(ast_msg_get_to(msg), "foo") ? 1 : 0);
194}
195
196static 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 */
230static int handler_wait_for_message(struct ast_test *test)
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) {
239 if (error == ETIMEDOUT) {
240 ast_test_status_update(test, "Test timed out while waiting for handler to get message\n");
241 ast_test_set_result(test, AST_TEST_FAIL);
242 break;
243 }
244 }
246
247 return (error != ETIMEDOUT);
248}
249
250/*! \brief Wait for the expected number of user events to be received */
251static 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
262 if (error == ETIMEDOUT) {
263 ast_test_status_update(test, "Test timed out while waiting for %d expected user events\n", expected_events);
264 ast_test_set_result(test, AST_TEST_FAIL);
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
274static 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);
292 ast_test_set_result(test, AST_TEST_FAIL);
293 }
294 }
295
296 return res;
297}
298
299AST_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
318 ast_test_validate(test, reg_result == 0);
319
321 ast_test_validate(test, reg_result == -1);
322
324 ast_test_validate(test, reg_result == 0);
325
327 ast_test_validate(test, reg_result == -1);
328
329 return AST_TEST_PASS;
330}
331
332AST_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
351 ast_test_validate(test, reg_result == 0);
352
354 ast_test_validate(test, reg_result == -1);
355
357 ast_test_validate(test, reg_result == 0);
358
360 ast_test_validate(test, reg_result == -1);
361
362 return AST_TEST_PASS;
363}
364
365static 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
374AST_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"));
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
465AST_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
531 return AST_TEST_FAIL;
532 }
533
534 return AST_TEST_PASS;
535}
536
537AST_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
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
572 ast_test_validate(test, result == 0);
573
574 return AST_TEST_PASS;
575}
576
577AST_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
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);
636 ast_test_set_result(test, AST_TEST_FAIL);
637 }
638
639 /* This will automatically fail the test if we don't get the message */
641
643 ast_test_validate(test, result == 0);
644
646 return AST_TEST_FAIL;
647 }
648
649 return AST_TEST_PASS;
650}
651
652AST_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
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
693AST_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
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");
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
729 ast_test_validate(test, result == 0);
730
731 return AST_TEST_PASS;
732}
733
734AST_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");
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");
766 ast_test_set_result(test, AST_TEST_FAIL);
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
775static int test_init_cb(struct ast_test_info *info, struct ast_test *test)
776{
780
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
801static int test_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
802{
805
806 return 0;
807}
808
809static 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
824
825 return 0;
826}
827
828static int create_test_dialplan(void)
829{
830 int res = 0;
831
833 return -1;
834 }
835
837 "UserEvent", "TestMessageUnitTest,Verify:To,Value:${MESSAGE(to)}",
840 "UserEvent", "TestMessageUnitTest,Verify:From,Value:${MESSAGE(from)}",
843 "UserEvent", "TestMessageUnitTest,Verify:Body,Value:${MESSAGE(body)}",
846 "UserEvent", "TestMessageUnitTest,Verify:Custom,Value:${MESSAGE_DATA(custom_data)}",
849 "Set", "MESSAGE_DATA(custom_data)=${MESSAGE_DATA(custom_data)}",
852 "MessageSend", "testmsg:${MESSAGE(from)},testmsg:${MESSAGE(to)}",
854
856
857 return res;
858}
859
860static 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
874 ast_test_register_init(TEST_CATEGORY, test_init_cb);
875 ast_test_register_cleanup(TEST_CATEGORY, test_cleanup_cb);
876
878}
879
880
881AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Out-of-call text message support");
#define AST_MODULE
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
static PGresult * result
Definition: cel_pgsql.c:84
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:2094
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:2086
char * strsep(char **str, const char *delims)
#define ast_variable_new(name, value, filename)
#define ast_variable_list_append(head, new_var)
#define LOG_ERROR
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
#define ast_mutex_unlock(a)
Definition: lock.h:190
pthread_cond_t ast_cond_t
Definition: lock.h:178
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
#define ast_cond_signal(cond)
Definition: lock.h:203
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
Out-of-call text message support.
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the 'from' URI of a message.
Definition: main/message.c:479
int ast_msg_send(struct ast_msg *msg, const char *to, const char *from)
Send a msg directly to an endpoint.
const char * ast_msg_get_var(struct ast_msg *msg, const char *name)
Get the specified variable on the message.
Definition: main/message.c:634
int ast_msg_handler_unregister(const struct ast_msg_handler *handler)
Unregister a ast_msg_handler.
const char * ast_msg_get_from(const struct ast_msg *msg)
Retrieve the source of this message.
Definition: main/message.c:550
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
Destroy a message variable iterator.
Definition: main/message.c:720
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
Definition: main/message.c:462
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this message.
Definition: main/message.c:534
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: main/message.c:703
const char * ast_msg_get_endpoint(const struct ast_msg *msg)
Retrieve the endpoint associated with this message.
Definition: main/message.c:565
int ast_msg_set_exten(struct ast_msg *msg, const char *fmt,...)
Set the dialplan extension for this message.
Definition: main/message.c:512
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
Definition: main/message.c:523
int ast_msg_has_destination(const struct ast_msg *msg)
Determine if a particular message has a destination via some handler.
Definition: main/message.c:951
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
Definition: main/message.c:432
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
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: main/message.c:629
const char * ast_msg_get_to(const struct ast_msg *msg)
Retrieve the destination of this message.
Definition: main/message.c:555
const char * ast_msg_get_tech(const struct ast_msg *msg)
Retrieve the technology associated with this message.
Definition: main/message.c:560
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
Definition: main/message.c:545
int ast_msg_handler_register(const struct ast_msg_handler *handler)
Register a ast_msg_handler.
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
Definition: main/message.c:501
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the 'body' text of a message (in UTF-8)
Definition: main/message.c:490
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
Definition: main/message.c:468
void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
Unref a message var from inside an iterator loop.
Definition: main/message.c:714
struct ast_msg_var_iterator * ast_msg_var_iterator_init(const struct ast_msg *msg)
Create a new message variable iterator.
Definition: main/message.c:658
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: main/message.c:624
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
Definition: main/message.c:972
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
Core PBX routines and definitions.
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:6928
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:6149
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: pbx.c:8221
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:186
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:161
An external processor of received messages.
Definition: message.h:98
const char * name
Name of the message handler.
Definition: message.h:102
A message technology.
Definition: message.h:52
const char *const name
Name of this message technology.
Definition: message.h:61
A message.
Definition: main/message.c:247
Contains all the initialization information required to store a new test definition.
Definition: test.h:235
Structure for variables, used for configurations and for channel variables.
Definition: astman.c:222
The expected user event fields.
Definition: test_message.c:74
int value
Definition: syslog.c:37
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
struct @503 bad_headers
If a user event fails, the bad headers that didn't match.
static struct ast_msg_handler test_msg_handler
Our test message handler.
Definition: test_message.c:90
AST_TEST_DEFINE(test_message_msg_tech_registration)
Definition: test_message.c:299
#define TEST_EXTENSION
Definition: test_message.c:47
static int verify_bad_headers(struct ast_test *test)
Definition: test_message.c:274
size_t current
Definition: test_message.c:77
static ast_cond_t user_event_cond
Condition wait variable for all dialplan user events being received.
Definition: test_message.c:62
static int create_test_dialplan(void)
Definition: test_message.c:828
static int handler_received_message
Predicate for the test_msg_handler receiving a message.
Definition: test_message.c:59
static ast_mutex_t user_event_lock
Mutex for user_event_cond.
Definition: test_message.c:65
static int user_event_hook_cb(int category, const char *event, char *body)
Definition: test_message.c:196
#define FREE_VARIABLE_VECTOR(vector)
Definition: test_message.c:787
static struct manager_custom_hook user_event_hook
AMI event hook that verifies whether or not we've gotten our user events.
Definition: test_message.c:99
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
static int test_init_cb(struct ast_test_info *info, struct ast_test *test)
Definition: test_message.c:775
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
static ast_cond_t handler_cond
Condition wait variable for test_msg_handler receiving message.
Definition: test_message.c:68
static int expected_user_events
The number of user events we expect for this test.
Definition: test_message.c:56
static int test_msg_has_destination_cb(const struct ast_msg *msg)
Definition: test_message.c:187
static ast_mutex_t handler_lock
Mutex for handler_cond.
Definition: test_message.c:71
static int test_msg_send(const struct ast_msg *msg, const char *to, const char *from)
Definition: test_message.c:170
#define DEFAULT_EXPECTED_EVENTS
The number of user events we should get in a dialplan test.
Definition: test_message.c:50
static int test_msg_handle_msg_cb(struct ast_msg *msg)
Definition: test_message.c:177
static struct ast_msg_tech test_msg_tech
Definition: test_message.c:81
static int received_user_events
The current number of received user events.
Definition: test_message.c:53
#define TEST_CONTEXT
Definition: test_message.c:46
static int load_module(void)
Definition: test_message.c:860
static int unload_module(void)
Definition: test_message.c:809
static int test_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
Definition: test_message.c:801
#define TEST_CATEGORY
Definition: test_message.c:44
static void ast_msg_safe_destroy(void *obj)
Definition: test_message.c:365
static int message_received
Definition: test_message.c:168
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
struct var_vector expected_user_event_fields
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235
int error(const char *format,...)
Definition: utils/frame.c:999
#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:941
Vector container support.
#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
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113
#define AST_VECTOR(name, type)
Define a vector structure.
Definition: vector.h:44
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680