44 #define TEST_CATEGORY "/main/message/"
46 #define TEST_CONTEXT "__TEST_MESSAGE_CONTEXT__"
47 #define TEST_EXTENSION "test_message_extension"
50 #define DEFAULT_EXPECTED_EVENTS 4
79 static
int test_msg_send(const struct
ast_msg *msg, const
char *to, const
char *from);
83 .msg_send = test_msg_send,
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);
92 .handle_msg = test_msg_handle_msg_cb,
93 .has_destination = test_msg_has_destination_cb,
96 static int user_event_hook_cb(
int category,
const char *
event,
char *body);
101 .helper = user_event_hook_cb,
125 expected =
AST_VECTOR_GET(&expected_user_event_fields, user_event);
130 for (current = expected; current; current = current->
next) {
133 if (strcmp(current->
name, header)) {
137 error = regcomp(®exbuf, current->
value, REG_EXTENDED | REG_NOSUB);
140 regerror(error, ®exbuf, 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);
146 if (!regexec(®exbuf, value, 0, NULL, 0)) {
151 bad_header = ast_variable_new(header, value, __FILE__);
158 ast_variable_list_append(&bad_headers_head, bad_header);
168 static int message_received;
170 static int test_msg_send(
const struct ast_msg *msg,
const char *to,
const char *from)
172 message_received = 1;
177 static int test_msg_handle_msg_cb(
struct ast_msg *msg)
187 static int test_msg_has_destination_cb(
const struct ast_msg *msg)
196 static int user_event_hook_cb(
int category,
const char *
event,
char *body)
201 if (strcmp(event,
"UserEvent")) {
206 while ((kvp = strsep(&parse,
"\r\n"))) {
210 if (ast_strlen_zero(kvp)) {
213 key = strsep(&kvp,
":");
234 struct timespec wait_time = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000 };
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);
247 return (error != ETIMEDOUT);
255 struct timespec wait_time = { .tv_sec = wait.tv_sec, .tv_nsec = wait.tv_usec * 1000 };
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);
270 ast_test_status_update(test,
"Received %d of %d user events\n",
received_user_events, expected_events);
274 static int verify_bad_headers(
struct ast_test *
test)
289 for (current = headers; current; current = current->
next) {
290 ast_test_status_update(test,
"Expected UserEvent %d: Failed to match %s: %s\n",
292 ast_test_set_result(test, AST_TEST_FAIL);
305 info->name = __func__;
306 info->category = TEST_CATEGORY;
307 info->summary =
"Test register/unregister of a message tech";
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;
318 ast_test_validate(test, reg_result == 0);
321 ast_test_validate(test, reg_result == -1);
324 ast_test_validate(test, reg_result == 0);
327 ast_test_validate(test, reg_result == -1);
329 return AST_TEST_PASS;
338 info->name = __func__;
339 info->category = TEST_CATEGORY;
340 info->summary =
"Test register/unregister of a message handler";
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;
351 ast_test_validate(test, reg_result == 0);
354 ast_test_validate(test, reg_result == -1);
357 ast_test_validate(test, reg_result == 0);
360 ast_test_validate(test, reg_result == -1);
362 return AST_TEST_PASS;
365 static void ast_msg_safe_destroy(
void *obj)
380 const char *out_name;
381 const char *out_value;
385 info->name = __func__;
386 info->category = TEST_CATEGORY;
387 info->summary =
"Test manipulating properties of a message";
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;
399 ast_test_validate(test, msg != NULL);
403 ast_test_validate(test, result == 0);
405 ast_test_validate(test, !strcmp(actual,
"testmsg:foo"));
409 ast_test_validate(test, result == 0);
411 ast_test_validate(test, !strcmp(actual,
"testmsg:bar"));
415 ast_test_validate(test, result == 0);
417 ast_test_validate(test, !strcmp(actual,
"BodyTest: foo"));
421 ast_test_validate(test, result == 0);
423 ast_test_validate(test, !strcmp(actual,
"my_tech"));
427 ast_test_validate(test, result == 0);
429 ast_test_validate(test, !strcmp(actual,
"terminus"));
433 ast_test_validate(test, result == 0);
435 ast_test_validate(test, !strcmp(actual,
"bar"));
439 ast_test_validate(test, result == 0);
441 ast_test_validate(test, !strcmp(actual,
"new_bar"));
445 ast_test_validate(test, it_vars != NULL);
451 ast_test_validate(test, result == 0);
453 ast_test_validate(test, it_vars != NULL);
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"));
460 ast_test_validate(test, result == 0);
462 return AST_TEST_PASS;
473 info->name = __func__;
474 info->category = TEST_CATEGORY;
475 info->summary =
"Test enqueueing messages to the dialplan";
477 "Test that a message enqueued for the dialplan is\n"
478 "passed to that particular extension";
479 return AST_TEST_NOT_RUN;
485 ast_test_validate(test, msg != NULL);
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);
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);
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);
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);
527 return AST_TEST_FAIL;
530 if (verify_bad_headers(test)) {
531 return AST_TEST_FAIL;
534 return AST_TEST_PASS;
544 info->name = __func__;
545 info->category = TEST_CATEGORY;
546 info->summary =
"Test enqueueing messages to a handler";
548 "Test that a message enqueued can be handled by a\n"
549 "non-dialplan handler";
550 return AST_TEST_NOT_RUN;
556 ast_test_validate(test, msg != NULL);
559 ast_test_validate(test, result == 0);
572 ast_test_validate(test, result == 0);
574 return AST_TEST_PASS;
586 info->name = __func__;
587 info->category = TEST_CATEGORY;
588 info->summary =
"Test enqueueing messages to a dialplan and custom handler";
590 "Test that a message enqueued is passed to all\n"
591 "handlers that can process it, dialplan as well as\n"
593 return AST_TEST_NOT_RUN;
599 ast_test_validate(test, msg != NULL);
602 ast_test_validate(test, result == 0);
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);
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);
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);
636 ast_test_set_result(test, AST_TEST_FAIL);
643 ast_test_validate(test, result == 0);
645 if (verify_bad_headers(test)) {
646 return AST_TEST_FAIL;
649 return AST_TEST_PASS;
658 info->name = __func__;
659 info->category = TEST_CATEGORY;
660 info->summary =
"Test checking for a dialplan destination";
662 "Test that a message's destination is verified via the\n"
664 return AST_TEST_NOT_RUN;
670 ast_test_validate(test, msg != NULL);
690 return AST_TEST_PASS;
700 info->name = __func__;
701 info->category = TEST_CATEGORY;
702 info->summary =
"Test checking for a handler destination";
704 "Test that a message's destination is verified via a\n"
706 return AST_TEST_NOT_RUN;
712 ast_test_validate(test, result == 0);
715 ast_test_validate(test, msg != NULL);
729 ast_test_validate(test, result == 0);
731 return AST_TEST_PASS;
740 info->name = __func__;
741 info->category = TEST_CATEGORY;
742 info->summary =
"Test message routing";
744 "Test that a message can be routed if it has\n"
746 return AST_TEST_NOT_RUN;
755 ast_test_validate(test, msg != NULL);
765 ast_test_status_update(test,
"Failed to send message\n");
766 ast_test_set_result(test, AST_TEST_FAIL);
772 return AST_TEST_PASS;
775 static int test_init_cb(
struct ast_test_info *info,
struct ast_test *test)
779 message_received = 0;
787 #define FREE_VARIABLE_VECTOR(vector) do { \
789 for (i = 0; i < AST_VECTOR_SIZE(&(vector)); i++) { \
790 struct ast_variable *headers; \
791 headers = AST_VECTOR_GET(&(vector), i); \
795 ast_variables_destroy(headers); \
797 AST_VECTOR_FREE(&(vector)); \
801 static int test_cleanup_cb(
struct ast_test_info *info,
struct ast_test *test)
803 FREE_VARIABLE_VECTOR(expected_user_event_fields);
809 static int unload_module(
void)
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);
828 static int create_test_dialplan(
void)
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)}",
860 static int load_module(
void)
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);
872 create_test_dialplan();
874 ast_test_register_init(TEST_CATEGORY, test_init_cb);
875 ast_test_register_cleanup(TEST_CATEGORY, test_cleanup_cb);
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.
int ast_msg_handler_unregister(const struct ast_msg_handler *handler)
Unregister a ast_msg_handler.
struct ast_variable * next
Contains all the initialization information required to store a new test definition.
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
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.
const char * ast_msg_get_tech(const struct ast_msg *msg)
Retrieve the technology associated with this message.
static int handler_received_message
Predicate for the test_msg_handler receiving a message.
void ast_manager_unregister_hook(struct manager_custom_hook *hook)
Delete a custom hook to be called when an event is fired.
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
const char * ast_msg_get_endpoint(const struct ast_msg *msg)
Retrieve the endpoint associated with this message.
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the 'body' text of a message (in UTF-8)
void ast_manager_register_hook(struct manager_custom_hook *hook)
Add a custom hook to be called when an event is fired.
An external processor of received messages.
static int verify_user_event_fields(int user_event, const char *header, const char *value)
Verifies a user event header/value pair.
int ast_msg_handler_register(const struct ast_msg_handler *handler)
Register a ast_msg_handler.
static ast_mutex_t handler_lock
Mutex for handler_cond.
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
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.
const char *const name
Name of this message technology.
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Out-of-call text message support.
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
void ast_msg_var_iterator_destroy(struct ast_msg_var_iterator *iter)
Destroy a message variable iterator.
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
const char * ast_msg_get_to(const struct ast_msg *msg)
Retrieve the destination of this message.
int ast_msg_send(struct ast_msg *msg, const char *to, const char *from)
Send a msg directly to an endpoint.
The expected user event fields.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define ast_strdupa(s)
duplicate a string in memory from the stack
void ast_msg_var_unref_current(struct ast_msg_var_iterator *iter)
Unref a message var from inside an iterator loop.
static int expected_user_events
The number of user events we expect for this test.
#define AST_VECTOR(name, type)
Define a vector structure.
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.
Core PBX routines and definitions.
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
const char * ast_msg_get_from(const struct ast_msg *msg)
Retrieve the source of this message.
static int received_user_events
The current number of received user events.
static struct ast_msg_handler test_msg_handler
Our test message handler.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
static ast_cond_t handler_cond
Condition wait variable for test_msg_handler receiving message.
static int handler_wait_for_message(struct ast_test *test)
Wait for the test_msg_handler to receive the message.
Vector container support.
int ast_msg_set_exten(struct ast_msg *msg, const char *fmt,...)
Set the dialplan extension for this message.
#define DEFAULT_EXPECTED_EVENTS
The number of user events we should get in a dialplan test.
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the 'from' URI of a message.
const char * name
Name of the message handler.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
static ast_mutex_t user_event_lock
Mutex for user_event_cond.
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this message.
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.
int ast_msg_has_destination(const struct ast_msg *msg)
Determine if a particular message has a destination via some handler.
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
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.
#define AST_VECTOR_REPLACE(vec, idx, elem)
Replace an element at a specific position in a vector, growing the vector if needed.
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
#define AST_TEST_DEFINE(hdr)
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.
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.
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
static struct manager_custom_hook user_event_hook
AMI event hook that verifies whether or not we've gotten our user events.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct @511 bad_headers
If a user event fails, the bad headers that didn't match.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
struct ast_msg_var_iterator * ast_msg_var_iterator_init(const struct ast_msg *msg)
Create a new message variable iterator.