68static const char * 
const test_result2str[] = {
 
   91    ast_test_init_cb_t *init_cb;        
 
   97static struct ast_test_execute_results {
 
   98    unsigned int total_tests;  
 
   99    unsigned int total_passed; 
 
  100    unsigned int total_failed; 
 
  101    unsigned int total_time;   
 
  102    unsigned int last_passed;  
 
  103    unsigned int last_failed;  
 
  104    unsigned int last_time;    
 
  110    TEST_NAME_CATEGORY = 2,
 
  114    ({ if (fp != NULL) { \ 
  129#define movefd(oldfd, newfd) \ 
  130    ({ if (oldfd != newfd) { \ 
  131        dup2(oldfd, newfd); \ 
  138#define lowerfd(oldfd) \ 
  139    ({ int newfd = dup(oldfd); \ 
  152static struct ast_test *
test_alloc(ast_test_cb_t *cb);
 
  153static struct ast_test *test_free(
struct ast_test *
test);
 
  154static int test_insert(
struct ast_test *
test);
 
  155static struct ast_test *test_remove(ast_test_cb_t *cb);
 
  156static int test_cat_cmp(
const char *
cat1, 
const char *
cat2);
 
  157static int registration_errors = 0;
 
  180int __ast_test_status_update(
const char *file, 
const char *func, 
int line, 
struct ast_test *
test, 
const char *fmt, ...)
 
  206int ast_test_register_init(
const char *category, ast_test_init_cb_t *cb)
 
  208    struct ast_test *
test;
 
  213        if (!(test_cat_cmp(
test->info.category, category))) {
 
  223int ast_test_register_cleanup(
const char *category, ast_test_cleanup_cb_t *cb)
 
  225    struct ast_test *
test;
 
  230        if (!(test_cat_cmp(
test->info.category, category))) {
 
  231            test->cleanup_cb = cb;
 
  240int ast_test_register(ast_test_cb_t *cb)
 
  242    struct ast_test *
test;
 
  245        ast_log(
LOG_ERROR, 
"Attempted to register test without all required information\n");
 
  246        registration_errors++;
 
  251        registration_errors++;
 
  255    if (test_insert(
test)) {
 
  257        registration_errors++;
 
  264int ast_test_unregister(ast_test_cb_t *cb)
 
  266    struct ast_test *
test;
 
  268    if (!(
test = test_remove(cb))) {
 
  284static void test_execute(
struct ast_test *
test)
 
  286    struct timeval begin;
 
  338int ast_test_capture_command(
struct ast_test_capture *capture, 
const char *file, 
char *
const argv[], 
const char *data, 
unsigned datalen)
 
  340    int fd0[2] = { -1, -1 }, fd1[2] = { -1, -1 }, fd2[2] = { -1, -1 };
 
  345    ast_test_capture_init(capture);
 
  347    if (data != 
NULL && datalen > 0) {
 
  348        if (pipe(fd0) == -1) {
 
  352        fcntl(fd0[1], F_SETFL, fcntl(fd0[1], F_GETFL, 0) | O_NONBLOCK);
 
  354        if ((fd0[0] = open(
"/dev/null", O_RDONLY)) == -1) {
 
  360    if (pipe(fd1) == -1) {
 
  365    if (pipe(fd2) == -1) {
 
  373    if ((pid = fork()) == -1) {
 
  377    } 
else if (pid == 0) {
 
  393        int wstatus, n, nfds;
 
  394        fd_set readfds, writefds;
 
  405        if ((cmd = fmemopen(
buf, 
sizeof(
buf), 
"w")) == 
NULL) {
 
  410        for (i = 0; argv[i] != 
NULL; ++i) {
 
  433            n = waitpid(pid, &wstatus, WNOHANG);
 
  454            nfds = 
MAX(fd0[1], 
MAX(fd1[0], fd2[0])) + 1;
 
  460                if (data != 
NULL && datalen > 0)
 
  461                    FD_SET(fd0[1], &writefds);
 
  473            n = select(nfds, &readfds, &writefds, 
NULL, 
NULL);
 
  476#define SAFE_FD_ISSET(fd, setptr) ((fd) != -1 && FD_ISSET((fd), setptr)) 
  478            if (SAFE_FD_ISSET(fd0[1], &writefds)) {
 
  479                n = write(fd0[1], data, datalen);
 
  482                    datalen -= 
MIN(datalen, n);
 
  491            if (SAFE_FD_ISSET(fd1[0], &readfds)) {
 
  492                n = read(fd1[0], 
buf, 
sizeof(
buf));
 
  494                    fwrite(
buf, 
sizeof(
char), n, 
out);
 
  500            if (SAFE_FD_ISSET(fd2[0], &readfds)) {
 
  501                n = read(fd2[0], 
buf, 
sizeof(
buf));
 
  503                    fwrite(
buf, 
sizeof(
char), n, err);
 
  534static char *reserved_words[] = {
 
  535    "abstract", 
"arguments", 
"as", 
"assert", 
"await",
 
  536    "boolean", 
"break", 
"byte", 
"case", 
"catch", 
"char", 
"class",
 
  537    "const", 
"continue", 
"debugger", 
"def", 
"default", 
"delete", 
"do",
 
  538    "double", 
"else", 
"enum", 
"eval", 
"export", 
"extends", 
"false",
 
  539    "final", 
"finally", 
"float", 
"for", 
"function", 
"goto", 
"if",
 
  540    "implements", 
"import", 
"in", 
"instanceof", 
"int", 
"interface",
 
  541    "let", 
"long", 
"native", 
"new", 
"null", 
"package", 
"private",
 
  542    "protected", 
"public", 
"return", 
"short", 
"static", 
"strictfp",
 
  543    "string", 
"super", 
"switch", 
"synchronized", 
"this", 
"throw", 
"throws",
 
  544    "trait", 
"transient", 
"true", 
"try", 
"typeof", 
"var", 
"void",
 
  545    "volatile", 
"while", 
"with", 
"yield" };
 
  547static int is_reserved_word(
const char *
word)
 
  551    for (i = 0; i < 
ARRAY_LEN(reserved_words); i++) {
 
  552        if (strcmp(
word, reserved_words[i]) == 0) {
 
  560static void test_xml_entry(
struct ast_test *
test, FILE *f)
 
  565    char *test_name = (
char *)
test->info.
name;
 
  577        if (is_reserved_word(next_cat)) {
 
  586    if (is_reserved_word(
test->info.
name)) {
 
  587        size_t name_length = strlen(
test->info.
name) + 2;
 
  590        snprintf(test_name, name_length, 
"_%s", 
test->info.
name);
 
  593    fprintf(f, 
"\t\t<testcase time=\"%u.%u\" classname=\"%s\" name=\"%s\"%s>\n",
 
  594            test->time / 1000, 
test->time % 1000,
 
  601        fprintf(f, 
"\t\t\t<failure><![CDATA[\n%s\n\t\t]]></failure>\n",
 
  603        fprintf(f, 
"\t\t</testcase>\n");
 
  608static void test_txt_entry(
struct ast_test *
test, FILE *f)
 
  614    fprintf(f, 
"\nName:              %s\n", 
test->info.
name);
 
  615    fprintf(f,   
"Category:          %s\n", 
test->info.category);
 
  616    fprintf(f,   
"Summary:           %s\n", 
test->info.summary);
 
  617    fprintf(f,   
"Description:       %s\n", 
test->info.description);
 
  618    fprintf(f,   
"Result:            %s\n", test_result2str[
test->state]);
 
  620        fprintf(f,   
"Time:              %u\n", 
test->time);
 
  642static int test_execute_multiple(
const char *
name, 
const char *category, 
struct ast_cli_args *
cli)
 
  644    char result_buf[32] = { 0 };
 
  646    enum test_mode mode = TEST_ALL; 
 
  652            mode = TEST_NAME_CATEGORY;
 
  660    memset(&last_results, 0, 
sizeof(last_results));
 
  666            if (!test_cat_cmp(
test->info.category, category) && !
test->info.explicit_only) {
 
  670        case TEST_NAME_CATEGORY:
 
  671            if (!(test_cat_cmp(
test->info.category, category)) && !(strcmp(
test->info.
name, 
name))) {
 
  693            last_results.last_time += 
test->time;
 
  695                last_results.last_passed++;
 
  697                last_results.last_failed++;
 
  702                    test_result2str[
test->state],
 
  706                ast_cli(
cli->fd, 
"END    %s - %s Time: %s%ums Result: %s\n",
 
  709                    test->time ? 
"" : 
"<",
 
  717        last_results.total_time += 
test->time;
 
  719            last_results.total_tests++;
 
  721                last_results.total_passed++;
 
  723                last_results.total_failed++;
 
  727    res = last_results.last_passed + last_results.last_failed;
 
  752static int test_generate_results(
const char *
name, 
const char *category, 
const char *xml_path, 
const char *txt_path)
 
  754    enum test_mode mode = TEST_ALL;  
 
  767            mode = TEST_NAME_CATEGORY;
 
  774        if (!(f_xml = fopen(xml_path, 
"w"))) {
 
  781        if (!(f_txt = fopen(txt_path, 
"w"))) {
 
  782            ast_log(
LOG_WARNING, 
"Could not open file %s for text output of test results\n", txt_path);
 
  794        fprintf(f_xml, 
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
 
  795        fprintf(f_xml, 
"<testsuites>\n");
 
  796        fprintf(f_xml, 
"\t<testsuite errors=\"0\" time=\"%u.%u\" tests=\"%u\" failures=\"%u\" " 
  797                "name=\"AsteriskUnitTests\">\n",
 
  798                last_results.total_time / 1000, last_results.total_time % 1000,
 
  799                last_results.total_tests, last_results.total_failed);
 
  800        fprintf(f_xml, 
"\t\t<properties>\n");
 
  801        fprintf(f_xml, 
"\t\t\t<property name=\"version\" value=\"%s\"/>\n", 
ast_get_version());
 
  802        fprintf(f_xml, 
"\t\t</properties>\n");
 
  809        fprintf(f_txt, 
"Number of Tests:          %u\n", last_results.total_tests);
 
  810        fprintf(f_txt, 
"Number of Tests Executed: %u\n", (last_results.total_passed + last_results.total_failed));
 
  811        fprintf(f_txt, 
"Passed Tests:             %u\n", last_results.total_passed);
 
  812        fprintf(f_txt, 
"Failed Tests:             %u\n", last_results.total_failed);
 
  813        fprintf(f_txt, 
"Total Execution Time:     %u\n", last_results.total_time);
 
  820            if (!test_cat_cmp(
test->info.category, category)) {
 
  821                test_xml_entry(
test, f_xml);
 
  822                test_txt_entry(
test, f_txt);
 
  825        case TEST_NAME_CATEGORY:
 
  826            if (!(strcmp(
test->info.category, category)) && !(strcmp(
test->info.
name, 
name))) {
 
  827                test_xml_entry(
test, f_xml);
 
  828                test_txt_entry(
test, f_txt);
 
  832            test_xml_entry(
test, f_xml);
 
  833            test_txt_entry(
test, f_txt);
 
  840        fprintf(f_xml, 
"\t</testsuite>\n");
 
  841        fprintf(f_xml, 
"</testsuites>\n");
 
  858static int test_insert(
struct ast_test *
test)
 
  878static struct ast_test *test_remove(ast_test_cb_t *cb)
 
  880    struct ast_test *cur = 
NULL;
 
  903static int test_cat_cmp(
const char *
cat1, 
const char *
cat2)
 
  919    return strncmp(
cat1, 
cat2, len2) ? 1 : 0;
 
  926static struct ast_test *test_free(
struct ast_test *
test)
 
  942static struct ast_test *
test_alloc(ast_test_cb_t *cb)
 
  944    struct ast_test *
test;
 
  958        return test_free(
test);
 
  964        return test_free(
test);
 
  967    if (
test->info.category[0] != 
'/' || 
test->info.category[strlen(
test->info.category) - 1] != 
'/') {
 
  968        ast_log(
LOG_WARNING, 
"Test category '%s' for test '%s' is missing a leading or trailing slash.\n",
 
  974        ++registration_errors;
 
  978        ast_log(
LOG_ERROR, 
"Test %s%s has no summary, test registration refused.\n",
 
  980        return test_free(
test);
 
  982    if (
test->info.summary[strlen(
test->info.summary) - 1] == 
'\n') {
 
  989        ++registration_errors;
 
  993        ast_log(
LOG_ERROR, 
"Test %s%s has no description, test registration refused.\n",
 
  995        return test_free(
test);
 
  997    if (
test->info.description[strlen(
test->info.description) - 1] == 
'\n') {
 
 1004        ++registration_errors;
 
 1008        ast_log(
LOG_ERROR, 
"Failed to allocate status_str for %s%s, test registration failed.\n",
 
 1010        return test_free(
test);
 
 1021static char *complete_test_category(
const char *
word)
 
 1023    int wordlen = strlen(
word);
 
 1024    struct ast_test *
test;
 
 1028        if (!strncasecmp(
word, 
test->info.category, wordlen)) {
 
 1039static char *complete_test_name(
const char *
word, 
const char *category)
 
 1041    int wordlen = strlen(
word);
 
 1042    struct ast_test *
test;
 
 1046        if (!test_cat_cmp(
test->info.category, category) && !strncasecmp(
word, 
test->info.
name, wordlen)) {
 
 1060#define FORMAT "%-25.25s %-30.30s %-40.40s %-13.13s\n" 
 1061    static const char * 
const option1[] = { 
"all", 
"category", 
NULL };
 
 1062    static const char * 
const option2[] = { 
"name", 
NULL };
 
 1067        e->
command = 
"test show registered";
 
 1070            "Usage: 'test show registered' can be used in three ways.\n" 
 1071            "       1. 'test show registered all' shows all registered tests\n" 
 1072            "       2. 'test show registered category [test category]' shows all tests in the given\n" 
 1074            "       3. 'test show registered category [test category] name [test name]' shows all\n" 
 1075            "           tests in a given category matching a given name\n";
 
 1081        if (
a->pos == 4 && !strcasecmp(
a->argv[3], 
"category")) {
 
 1082            return complete_test_category(
a->word);
 
 1088            return complete_test_name(
a->word, 
a->argv[4]);
 
 1092        if ((
a->argc < 4) || (
a->argc == 6) || (
a->argc > 7) ||
 
 1093            ((
a->argc == 4) && strcasecmp(
a->argv[3], 
"all")) ||
 
 1094            ((
a->argc == 7) && strcasecmp(
a->argv[5], 
"name"))) {
 
 1097        ast_cli(
a->fd, 
FORMAT, 
"Category", 
"Name", 
"Summary", 
"Test Result");
 
 1098        ast_cli(
a->fd, 
FORMAT, 
"--------", 
"----", 
"-------", 
"-----------");
 
 1101            if ((
a->argc == 4) ||
 
 1102                 ((
a->argc == 5) && !test_cat_cmp(
test->info.category, 
a->argv[4])) ||
 
 1103                 ((
a->argc == 7) && !strcmp(
test->info.category, 
a->argv[4]) && !strcmp(
test->info.
name, 
a->argv[6]))) {
 
 1106                        test->info.summary, test_result2str[
test->state]);
 
 1111        ast_cli(
a->fd, 
FORMAT, 
"--------", 
"----", 
"-------", 
"-----------");
 
 1112        ast_cli(
a->fd, 
"\n%d Registered Tests Matched\n", count);
 
 1122    static const char * 
const option1[] = { 
"all", 
"category", 
NULL };
 
 1123    static const char * 
const option2[] = { 
"name", 
"options", 
NULL };
 
 1124    static const char * 
const option3[] = { 
"options", 
NULL };
 
 1130            "Usage: test execute can be used in several ways.\n" 
 1131            "       1. 'test execute all' runs all registered tests\n" 
 1132            "       2. 'test execute category [test category]' runs all tests in the given\n" 
 1134            "       3. 'test execute category [test category] options [test option]...' runs all\n" 
 1135            "           tests in the given category with options supplied to each test\n" 
 1136            "       4. 'test execute category [test category] name [test name]' runs all\n" 
 1137            "           tests in a given category matching a given name\n" 
 1138            "       5. 'test execute category [test category] name [test name] options [test option]...' runs all\n" 
 1139            "           tests in a given category matching a given name with the specified options\n" 
 1146        if (
a->pos == 3 && !strcasecmp(
a->argv[2], 
"category")) {
 
 1147            return complete_test_category(
a->word);
 
 1152        if (
a->pos == 5 && !strcasecmp(
a->argv[4], 
"name")) {
 
 1153            return complete_test_name(
a->word, 
a->argv[3]);
 
 1155        if (
a->pos == 5 && !strcasecmp(
a->argv[4], 
"options")) {
 
 1158        if (
a->pos == 6 && !strcasecmp(
a->argv[4], 
"name")) {
 
 1168        if ((
a->argc == 3) && !strcasecmp(
a->argv[2], 
"all")) { 
 
 1169            ast_cli(
a->fd, 
"Running all available tests...\n\n");
 
 1171        } 
else if (
a->argc == 4) { 
 
 1172            ast_cli(
a->fd, 
"Running all available tests matching category %s\n\n", 
a->argv[3]);
 
 1173            test_execute_multiple(
NULL, 
a->argv[3], 
a);
 
 1174        } 
else if (
a->argc >= 6 && !strcasecmp(
a->argv[4], 
"options")) { 
 
 1175            ast_cli(
a->fd, 
"Running all available tests matching category %s with options\n\n", 
a->argv[3]);
 
 1176            test_execute_multiple(
NULL, 
a->argv[3], 
a);
 
 1177        } 
else if (
a->argc == 6 && !strcasecmp(
a->argv[4], 
"name")) { 
 
 1178            ast_cli(
a->fd, 
"Running all available tests matching category %s and name %s\n\n", 
a->argv[3], 
a->argv[5]);
 
 1179            test_execute_multiple(
a->argv[5], 
a->argv[3], 
a);
 
 1180        } 
else if (
a->argc > 7) { 
 
 1181            ast_cli(
a->fd, 
"Running all available tests matching category %s and name %s with options\n\n", 
a->argv[3], 
a->argv[5]);
 
 1182            test_execute_multiple(
a->argv[5], 
a->argv[3], 
a);
 
 1188        if (!(last_results.last_passed + last_results.last_failed)) {
 
 1189            ast_cli(
a->fd, 
"--- No Tests Found! ---\n");
 
 1191        ast_cli(
a->fd, 
"\n%u Test(s) Executed  %u Passed  %u Failed\n",
 
 1192            (last_results.last_passed + last_results.last_failed),
 
 1193            last_results.last_passed,
 
 1194            last_results.last_failed);
 
 1205#define FORMAT_RES_ALL1 "%s%s %-30.30s %-25.25s %-10.10s\n" 
 1206#define FORMAT_RES_ALL2 "%s%s %-30.30s %-25.25s %s%ums\n" 
 1207    static const char * 
const option1[] = { 
"all", 
"failed", 
"passed", 
NULL };
 
 1208    char result_buf[32] = { 0 };
 
 1216        e->
command = 
"test show results";
 
 1218            "Usage: test show results can be used in three ways\n" 
 1219            "       1. 'test show results all' Displays results for all executed tests.\n" 
 1220            "       2. 'test show results passed' Displays results for all passed tests.\n" 
 1221            "       3. 'test show results failed' Displays results for all failed tests.\n";
 
 1233        } 
else if (!strcasecmp(
a->argv[3], 
"passed")) {
 
 1235        } 
else if (!strcasecmp(
a->argv[3], 
"failed")) {
 
 1237        } 
else if (!strcasecmp(
a->argv[3], 
"all")) {
 
 1243        ast_cli(
a->fd, FORMAT_RES_ALL1, 
"Result", 
"", 
"Name", 
"Category", 
"Time");
 
 1254                    0, sizeof(result_buf));
 
 1260                    test->info.category,
 
 1261                    test->time ? 
" " : 
"<",
 
 1267        ast_cli(
a->fd, 
"%d Test(s) Executed  %d Passed  %d Failed\n", (failed + passed), passed, failed);
 
 1276    static const char * 
const option[] = { 
"xml", 
"txt", 
NULL };
 
 1278    const char *
type = 
"";
 
 1286        e->
command = 
"test generate results";
 
 1288            "Usage: 'test generate results'\n" 
 1289            "       Generates test results in either xml or txt format. An optional \n" 
 1290            "       file path may be provided to specify the location of the xml or\n" 
 1292            "       \nExample usage:\n" 
 1293            "       'test generate results xml' this writes to a default file\n" 
 1294            "       'test generate results xml /path/to/file.xml' writes to specified file\n";
 
 1304        if (
a->argc < 4 || 
a->argc > 5) {
 
 1306        } 
else if (!strcasecmp(
a->argv[3], 
"xml")) {
 
 1309        } 
else if (!strcasecmp(
a->argv[3], 
"txt")) {
 
 1333            ast_cli(
a->fd, 
"Results Generated Successfully: %s\n", 
S_OR(file, 
""));
 
 1335            ast_cli(
a->fd, 
"Results Could Not Be Generated: %s\n", 
S_OR(file, 
""));
 
 1347    AST_CLI_DEFINE(test_cli_show_registered,           
"show registered tests"),
 
 1348    AST_CLI_DEFINE(test_cli_execute_registered,        
"execute registered tests"),
 
 1350    AST_CLI_DEFINE(test_cli_generate_results,          
"generate test results to file"),
 
 1355    return test_suite_topic;
 
 1362struct ast_test_suite_message_payload {
 
 1370static void test_suite_message_payload_dtor(
void *obj)
 
 1372    struct ast_test_suite_message_payload *payload = obj;
 
 1374    if (payload->blob) {
 
 1379struct ast_json *ast_test_suite_get_blob(
struct ast_test_suite_message_payload *payload)
 
 1381    return payload->blob;
 
 1387    struct ast_test_suite_message_payload *payload;
 
 1395    blob = ast_test_suite_get_blob(payload);
 
 1427    .
to_ami = test_suite_event_to_ami);
 
 1429void __ast_test_suite_event_notify(
const char *file, 
const char *func, 
int line, 
const char *
state, 
const char *fmt, ...)
 
 1431    RAII_VAR(
struct ast_test_suite_message_payload *, payload,
 
 1438    if (!ast_test_suite_message_type()) {
 
 1447    payload = 
ao2_alloc(
sizeof(*payload), test_suite_message_payload_dtor);
 
 1455    payload->blob = 
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: i, s: s}",
 
 1456                 "type", 
"testevent",
 
 1459                 "appfunction", func,
 
 1462    if (!payload->blob) {
 
 1476        info->name = 
"registrations";
 
 1477        info->category = 
"/main/test/";
 
 1478        info->summary = 
"Validate Test Registration Data.";
 
 1479        info->description = 
"Validate Test Registration Data.";
 
 1485    if (registration_errors) {
 
 1487            "%d test registration error%s occurred.  See startup logs for details.\n",
 
 1488            registration_errors, registration_errors > 1 ? 
"s" : 
"");
 
 1495static void test_cleanup(
void)
 
 1500    test_suite_topic = 
NULL;
 
 1507#ifdef TEST_FRAMEWORK 
 1512    if (!test_suite_topic) {
 
 
Prototypes for public functions only of internal interest,.
void ast_cli_unregister_multiple(void)
Asterisk version information.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
const char * ast_get_version_num(void)
Retrieve the numeric Asterisk version.
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
void ast_std_free(void *ptr)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_alloc(data_size, destructor_fn)
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
void ast_cli(int fd, const char *fmt,...)
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static struct ast_cli_entry cli[]
static SQLHSTMT execute(struct odbc_obj *obj, void *data, int silent)
Common execution function for SQL queries.
static char prefix[MAX_PREFIX]
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
void ast_replace_sigchld(void)
Replace the SIGCHLD handler.
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
Support for logging to various files, console and syslog Configuration in file logger....
Asterisk JSON abstraction layer.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
A set of macros to manage forward-linked lists.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_INSERT_SORTALPHA(head, elm, field, sortfield)
Inserts a list entry into a alphabetically sorted list.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define WEXITSTATUS(status)
#define WIFEXITED(status)
#define EVENT_FLAG_REPORTING
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_LOG_DIR
static void to_ami(struct ast_sip_subscription *sub, struct ast_str **buf)
static void cleanup(void)
Clean up any old apps that we don't need any more.
static int cleanup_cb(void *obj, void *arg, int flags)
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
#define STASIS_MESSAGE_TYPE_DEFN(name,...)
Boiler-plate messaging macro for defining public message types.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
descriptor for a cli entry.
Abstract JSON element (object, array, string, int, ...).
Struct containing info for an AMI event to send out.
Support for dynamic strings.
A capture of running an external process.
char * outbuf
buffer holding stdout
char * errbuf
buffer holding stderr
size_t errlen
length of buffer holding stderr
pid_t pid
process id of child
size_t outlen
length of buffer holding stdout
int exitcode
exit code of child
Contains all the initialization information required to store a new test definition.
Handy terminal functions for vt* terms.
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
#define ast_test_debug(test, fmt,...)
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
#define AST_TEST_DEFINE(hdr)
static struct test_data * test_alloc(void)
Time-related functions and macros.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.