Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
test.c File Reference

Unit Test Framework. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/test.h"
#include "asterisk/logger.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
#include "asterisk/ast_version.h"
#include "asterisk/paths.h"
#include "asterisk/time.h"
#include "asterisk/stasis.h"
#include "asterisk/json.h"
#include "asterisk/astobj2.h"
Include dependency graph for test.c:

Go to the source code of this file.

Data Structures

struct  ast_test
 
struct  ast_test_execute_results
 
struct  ast_test_suite_message_payload
 A wrapper object that can be ao2 ref counted around an ast_json blob. More...
 
struct  tests
 

Macros

#define FORMAT   "%-25.25s %-30.30s %-40.40s %-13.13s\n"
 
#define FORMAT_RES_ALL1   "%s%s %-30.30s %-25.25s %-10.10s\n"
 
#define FORMAT_RES_ALL2   "%s%s %-30.30s %-25.25s %s%ums\n"
 

Enumerations

enum  test_mode { TEST_ALL = 0, TEST_CATEGORY = 1, TEST_NAME_CATEGORY = 2 }
 

Functions

int __ast_test_status_update (const char *file, const char *func, int line, struct ast_test *test, const char *fmt,...)
 
void __ast_test_suite_event_notify (const char *file, const char *func, int line, const char *state, const char *fmt,...)
 
void ast_test_debug (struct ast_test *test, const char *fmt,...)
 
 AST_TEST_DEFINE (test_registrations)
 
int ast_test_init (void)
 
int ast_test_register (ast_test_cb_t *cb)
 
int ast_test_register_cleanup (const char *category, ast_test_cleanup_cb_t *cb)
 
int ast_test_register_init (const char *category, ast_test_init_cb_t *cb)
 
void ast_test_set_result (struct ast_test *test, enum ast_test_result_state state)
 
struct ast_jsonast_test_suite_get_blob (struct ast_test_suite_message_payload *payload)
 
struct stasis_topicast_test_suite_topic (void)
 
int ast_test_unregister (ast_test_cb_t *cb)
 
static char * complete_test_category (const char *word)
 
static char * complete_test_name (const char *word, const char *category)
 
static int is_reserved_word (const char *word)
 
 STASIS_MESSAGE_TYPE_DEFN (ast_test_suite_message_type,.to_ami=test_suite_event_to_ami)
 The message type for test suite messages. More...
 
static struct ast_testtest_alloc (ast_test_cb_t *cb)
 
static int test_cat_cmp (const char *cat1, const char *cat2)
 compares two test categories to determine if cat1 resides in cat2 More...
 
static void test_cleanup (void)
 
static char * test_cli_execute_registered (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * test_cli_generate_results (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * test_cli_show_registered (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * test_cli_show_results (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void test_execute (struct ast_test *test)
 
static int test_execute_multiple (const char *name, const char *category, struct ast_cli_args *cli)
 
static struct ast_testtest_free (struct ast_test *test)
 
static int test_generate_results (const char *name, const char *category, const char *xml_path, const char *txt_path)
 
static int test_insert (struct ast_test *test)
 
static struct ast_testtest_remove (ast_test_cb_t *cb)
 
static struct ast_manager_event_blobtest_suite_event_to_ami (struct stasis_message *msg)
 
static void test_suite_message_payload_dtor (void *obj)
 
static void test_txt_entry (struct ast_test *test, FILE *f)
 
static void test_xml_entry (struct ast_test *test, FILE *f)
 

Variables

static struct ast_test_execute_results last_results
 
static int registration_errors = 0
 
static char * reserved_words []
 
static struct ast_cli_entry test_cli []
 
static const char *const test_result2str []
 
struct stasis_topictest_suite_topic
 The topic for test suite messages. More...
 
static struct tests tests = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 

Detailed Description

Unit Test Framework.

Author
David Vossel dvoss.nosp@m.el@d.nosp@m.igium.nosp@m..com
Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com

Definition in file test.c.

Macro Definition Documentation

◆ FORMAT

#define FORMAT   "%-25.25s %-30.30s %-40.40s %-13.13s\n"

◆ FORMAT_RES_ALL1

#define FORMAT_RES_ALL1   "%s%s %-30.30s %-25.25s %-10.10s\n"

Referenced by test_cli_show_results().

◆ FORMAT_RES_ALL2

#define FORMAT_RES_ALL2   "%s%s %-30.30s %-25.25s %s%ums\n"

Referenced by test_cli_show_results().

Enumeration Type Documentation

◆ test_mode

enum test_mode
Enumerator
TEST_ALL 
TEST_CATEGORY 
TEST_NAME_CATEGORY 

Definition at line 97 of file test.c.

97  {
98  TEST_ALL = 0,
99  TEST_CATEGORY = 1,
100  TEST_NAME_CATEGORY = 2,
101 };
Definition: test.c:98

Function Documentation

◆ __ast_test_status_update()

int __ast_test_status_update ( const char *  file,
const char *  func,
int  line,
struct ast_test test,
const char *  fmt,
  ... 
)

Definition at line 134 of file test.c.

References ast_cli(), ast_free, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set_va(), buf, ast_test::cli, ast_cli_args::fd, NULL, and ast_test::status_str.

135 {
136  struct ast_str *buf = NULL;
137  va_list ap;
138 
139  if (!(buf = ast_str_create(128))) {
140  return -1;
141  }
142 
143  va_start(ap, fmt);
144  ast_str_set_va(&buf, 0, fmt, ap);
145  va_end(ap);
146 
147  if (test->cli) {
148  ast_cli(test->cli->fd, "[%s:%s:%d]: %s",
149  file, func, line, ast_str_buffer(buf));
150  }
151 
152  ast_str_append(&test->status_str, 0, "[%s:%s:%d]: %s",
153  file, func, line, ast_str_buffer(buf));
154 
155  ast_free(buf);
156 
157  return 0;
158 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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.
Definition: strings.h:982
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
struct ast_str * status_str
Test defined status output from last execution.
Definition: test.c:70
const int fd
Definition: cli.h:159
struct ast_cli_args * cli
CLI arguments, if tests being run from the CLI.
Definition: test.c:77
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ast_free(a)
Definition: astmm.h:182
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:620

◆ __ast_test_suite_event_notify()

void __ast_test_suite_event_notify ( const char *  file,
const char *  func,
int  line,
const char *  state,
const char *  fmt,
  ... 
)

Definition at line 1145 of file test.c.

References ao2_alloc, ao2_cleanup, ast_free, ast_json_pack(), ast_str_buffer(), ast_str_create, ast_str_set_va(), ast_test_suite_topic(), buf, NULL, RAII_VAR, stasis_message_create(), stasis_publish(), and test_suite_message_payload_dtor().

1146 {
1147  RAII_VAR(struct ast_test_suite_message_payload *, payload,
1148  NULL,
1149  ao2_cleanup);
1150  RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
1151  RAII_VAR(struct ast_str *, buf, NULL, ast_free);
1152  va_list ap;
1153 
1154  if (!ast_test_suite_message_type()) {
1155  return;
1156  }
1157 
1158  buf = ast_str_create(128);
1159  if (!buf) {
1160  return;
1161  }
1162 
1163  payload = ao2_alloc(sizeof(*payload), test_suite_message_payload_dtor);
1164  if (!payload) {
1165  return;
1166  }
1167 
1168  va_start(ap, fmt);
1169  ast_str_set_va(&buf, 0, fmt, ap);
1170  va_end(ap);
1171  payload->blob = ast_json_pack("{s: s, s: s, s: s, s: s, s: i, s: s}",
1172  "type", "testevent",
1173  "state", state,
1174  "appfile", file,
1175  "appfunction", func,
1176  "line", line,
1177  "data", ast_str_buffer(buf));
1178  if (!payload->blob) {
1179  return;
1180  }
1181  msg = stasis_message_create(ast_test_suite_message_type(), payload);
1182  if (!msg) {
1183  return;
1184  }
1186 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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.
Definition: strings.h:982
#define NULL
Definition: resample.c:96
#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
static void test_suite_message_payload_dtor(void *obj)
Definition: test.c:1086
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
struct stasis_topic * ast_test_suite_topic(void)
Definition: test.c:1069
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1511
#define ast_free(a)
Definition: astmm.h:182
A wrapper object that can be ao2 ref counted around an ast_json blob.
Definition: test.c:1078
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:620

◆ ast_test_debug()

void ast_test_debug ( struct ast_test test,
const char *  fmt,
  ... 
)

Definition at line 113 of file test.c.

References ast_cli(), ast_free, ast_str_buffer(), ast_str_create, ast_str_set_va(), buf, ast_test::cli, ast_cli_args::fd, and NULL.

Referenced by astobj2_test_1_helper(), test_traversal_sorted(), and verify_mock_cdr_record().

114 {
115  struct ast_str *buf = NULL;
116  va_list ap;
117 
118  buf = ast_str_create(128);
119  if (!buf) {
120  return;
121  }
122 
123  va_start(ap, fmt);
124  ast_str_set_va(&buf, 0, fmt, ap);
125  va_end(ap);
126 
127  if (test->cli) {
128  ast_cli(test->cli->fd, "%s", ast_str_buffer(buf));
129  }
130 
131  ast_free(buf);
132 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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.
Definition: strings.h:982
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const int fd
Definition: cli.h:159
struct ast_cli_args * cli
CLI arguments, if tests being run from the CLI.
Definition: test.c:77
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ast_free(a)
Definition: astmm.h:182
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:620

◆ AST_TEST_DEFINE()

AST_TEST_DEFINE ( test_registrations  )

Definition at line 1188 of file test.c.

References AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, ast_test_info::category, ast_test_info::description, ast_test::info, ast_test_info::name, registration_errors, ast_test_info::summary, TEST_EXECUTE, and TEST_INIT.

1189 {
1190  switch (cmd) {
1191  case TEST_INIT:
1192  info->name = "registrations";
1193  info->category = "/main/test/";
1194  info->summary = "Validate Test Registration Data.";
1195  info->description = "Validate Test Registration Data.";
1196  return AST_TEST_NOT_RUN;
1197  case TEST_EXECUTE:
1198  break;
1199  }
1200 
1201  if (registration_errors) {
1203  "%d test registration error%s occurred. See startup logs for details.\n",
1204  registration_errors, registration_errors > 1 ? "s" : "");
1205  return AST_TEST_FAIL;
1206  }
1207 
1208  return AST_TEST_PASS;
1209 }
static int registration_errors
Definition: test.c:111
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
def info(msg)

◆ ast_test_init()

int ast_test_init ( void  )

Provided by test.c

Definition at line 1221 of file test.c.

References ARRAY_LEN, ast_cli_register_multiple, ast_register_cleanup(), AST_TEST_REGISTER, STASIS_MESSAGE_TYPE_INIT, stasis_topic_create(), and test_cleanup().

Referenced by asterisk_daemon().

1222 {
1223 #ifdef TEST_FRAMEWORK
1225 
1226  /* Create stasis topic */
1227  test_suite_topic = stasis_topic_create("testsuite:all");
1228  if (!test_suite_topic) {
1229  return -1;
1230  }
1231 
1232  if (STASIS_MESSAGE_TYPE_INIT(ast_test_suite_message_type) != 0) {
1233  return -1;
1234  }
1235 
1236  AST_TEST_REGISTER(test_registrations);
1237 
1238  /* Register cli commands */
1240 #endif
1241 
1242  return 0;
1243 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
struct stasis_topic * test_suite_topic
The topic for test suite messages.
Definition: test.c:55
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Definition: stasis.c:618
static void test_cleanup(void)
Definition: test.c:1211
static struct ast_cli_entry test_cli[]
Definition: test.c:1062

◆ ast_test_register()

int ast_test_register ( ast_test_cb_t *  cb)

Definition at line 194 of file test.c.

References ast_log, LOG_ERROR, registration_errors, test, test_alloc(), test_free(), and test_insert().

Referenced by load_module().

195 {
196  struct ast_test *test;
197 
198  if (!cb) {
199  ast_log(LOG_ERROR, "Attempted to register test without all required information\n");
201  return -1;
202  }
203 
204  if (!(test = test_alloc(cb))) {
206  return -1;
207  }
208 
209  if (test_insert(test)) {
210  test_free(test);
212  return -1;
213  }
214 
215  return 0;
216 }
static int registration_errors
Definition: test.c:111
static struct ast_test * test_free(struct ast_test *test)
Definition: test.c:665
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static int test_insert(struct ast_test *test)
Definition: test.c:598
ast_test_cb_t * cb
Definition: test.c:80
Definition: test.c:65
static struct ast_test * test_alloc(ast_test_cb_t *cb)
Definition: test.c:681
static struct ast_test * test
Definition: localtime.c:115

◆ ast_test_register_cleanup()

int ast_test_register_cleanup ( const char *  category,
ast_test_cleanup_cb_t *  cb 
)

Definition at line 177 of file test.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_test_info::category, ast_test::cb, ast_test::cleanup_cb, ast_test::info, test, and test_cat_cmp().

Referenced by load_module().

178 {
179  struct ast_test *test;
180  int registered = 1;
181 
183  AST_LIST_TRAVERSE(&tests, test, entry) {
184  if (!(test_cat_cmp(test->info.category, category))) {
185  test->cleanup_cb = cb;
186  registered = 0;
187  }
188  }
190 
191  return registered;
192 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
ast_test_cleanup_cb_t * cleanup_cb
Definition: test.c:82
static int test_cat_cmp(const char *cat1, const char *cat2)
compares two test categories to determine if cat1 resides in cat2
Definition: test.c:642
const char * category
test category
Definition: test.h:231
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
ast_test_cb_t * cb
Definition: test.c:80
Definition: test.c:65
Definition: test.c:104
struct ast_test_info info
Definition: test.c:66
Definition: search.h:40
static struct ast_test * test
Definition: localtime.c:115

◆ ast_test_register_init()

int ast_test_register_init ( const char *  category,
ast_test_init_cb_t *  cb 
)

Definition at line 160 of file test.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_test_info::category, ast_test::cb, ast_test::info, ast_test::init_cb, test, and test_cat_cmp().

Referenced by load_module().

161 {
162  struct ast_test *test;
163  int registered = 1;
164 
166  AST_LIST_TRAVERSE(&tests, test, entry) {
167  if (!(test_cat_cmp(test->info.category, category))) {
168  test->init_cb = cb;
169  registered = 0;
170  }
171  }
173 
174  return registered;
175 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int test_cat_cmp(const char *cat1, const char *cat2)
compares two test categories to determine if cat1 resides in cat2
Definition: test.c:642
const char * category
test category
Definition: test.h:231
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
ast_test_cb_t * cb
Definition: test.c:80
Definition: test.c:65
Definition: test.c:104
struct ast_test_info info
Definition: test.c:66
Definition: search.h:40
ast_test_init_cb_t * init_cb
Definition: test.c:81
static struct ast_test * test
Definition: localtime.c:115

◆ ast_test_set_result()

void ast_test_set_result ( struct ast_test test,
enum ast_test_result_state  state 
)

Definition at line 262 of file test.c.

References AST_TEST_FAIL, AST_TEST_NOT_RUN, and ast_test::state.

Referenced by AST_TEST_DEFINE(), handler_wait_for_message(), user_event_wait_for_events(), and verify_bad_headers().

263 {
264  if (test->state == AST_TEST_FAIL || state == AST_TEST_NOT_RUN) {
265  return;
266  }
267  test->state = state;
268 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
enum ast_test_result_state state
Definition: test.c:78

◆ ast_test_suite_get_blob()

struct ast_json* ast_test_suite_get_blob ( struct ast_test_suite_message_payload payload)

Definition at line 1095 of file test.c.

References ast_test_suite_message_payload::blob.

Referenced by test_suite_event_to_ami().

1096 {
1097  return payload->blob;
1098 }
struct ast_json * blob
Definition: test.c:1079

◆ ast_test_suite_topic()

struct stasis_topic* ast_test_suite_topic ( void  )

Definition at line 1069 of file test.c.

References test_suite_topic.

Referenced by __ast_test_suite_event_notify(), and __init_manager().

1070 {
1071  return test_suite_topic;
1072 }
struct stasis_topic * test_suite_topic
The topic for test suite messages.
Definition: test.c:55

◆ ast_test_unregister()

int ast_test_unregister ( ast_test_cb_t *  cb)

Definition at line 218 of file test.c.

References test, test_free(), and test_remove().

Referenced by unload_module().

219 {
220  struct ast_test *test;
221 
222  if (!(test = test_remove(cb))) {
223  return -1; /* not found */
224  }
225 
226  test_free(test);
227 
228  return 0;
229 }
static struct ast_test * test_remove(ast_test_cb_t *cb)
Definition: test.c:617
static struct ast_test * test_free(struct ast_test *test)
Definition: test.c:665
ast_test_cb_t * cb
Definition: test.c:80
Definition: test.c:65
static struct ast_test * test
Definition: localtime.c:115

◆ complete_test_category()

static char* complete_test_category ( const char *  word)
static

Definition at line 755 of file test.c.

References ast_cli_completion_add(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_test_info::category, ast_test::info, NULL, and test.

Referenced by test_cli_execute_registered(), and test_cli_show_registered().

756 {
757  int wordlen = strlen(word);
758  struct ast_test *test;
759 
761  AST_LIST_TRAVERSE(&tests, test, entry) {
762  if (!strncasecmp(word, test->info.category, wordlen)) {
764  break;
765  }
766  }
767  }
769 
770  return NULL;
771 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
const char * category
test category
Definition: test.h:231
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
Definition: test.c:65
Definition: test.c:104
struct ast_test_info info
Definition: test.c:66
Definition: search.h:40
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2726
static struct ast_test * test
Definition: localtime.c:115
short word

◆ complete_test_name()

static char* complete_test_name ( const char *  word,
const char *  category 
)
static

Definition at line 773 of file test.c.

References ast_cli_completion_add(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_test_info::category, ast_test::info, ast_test_info::name, NULL, test, and test_cat_cmp().

Referenced by test_cli_execute_registered(), and test_cli_show_registered().

774 {
775  int wordlen = strlen(word);
776  struct ast_test *test;
777 
779  AST_LIST_TRAVERSE(&tests, test, entry) {
780  if (!test_cat_cmp(test->info.category, category) && !strncasecmp(word, test->info.name, wordlen)) {
782  break;
783  }
784  }
785  }
787 
788  return NULL;
789 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
const char * name
name of test, unique to category
Definition: test.h:223
static int test_cat_cmp(const char *cat1, const char *cat2)
compares two test categories to determine if cat1 resides in cat2
Definition: test.c:642
const char * category
test category
Definition: test.h:231
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
Definition: test.c:65
Definition: test.c:104
struct ast_test_info info
Definition: test.c:66
Definition: search.h:40
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2726
static struct ast_test * test
Definition: localtime.c:115
short word

◆ is_reserved_word()

static int is_reserved_word ( const char *  word)
static

Definition at line 287 of file test.c.

References ARRAY_LEN, and reserved_words.

Referenced by test_xml_entry().

288 {
289  int i;
290 
291  for (i = 0; i < ARRAY_LEN(reserved_words); i++) {
292  if (strcmp(word, reserved_words[i]) == 0) {
293  return 1;
294  }
295  }
296 
297  return 0;
298 }
static char * reserved_words[]
Definition: test.c:274
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
short word

◆ STASIS_MESSAGE_TYPE_DEFN()

STASIS_MESSAGE_TYPE_DEFN ( ast_test_suite_message_type  ,
to_ami = test_suite_event_to_ami 
)

The message type for test suite messages.

Since
12

Referenced by test_suite_event_to_ami().

◆ test_alloc()

static struct ast_test * test_alloc ( ast_test_cb_t *  cb)
static

Definition at line 681 of file test.c.

References ast_calloc, ast_log, ast_str_create, ast_strlen_zero, ast_test_info::category, ast_test::cb, ast_test_info::description, ast_test::info, LOG_ERROR, LOG_WARNING, ast_test_info::name, NULL, registration_errors, ast_test::status_str, ast_test_info::summary, test, test_free(), and TEST_INIT.

Referenced by ast_test_register().

682 {
683  struct ast_test *test;
684 
685  test = ast_calloc(1, sizeof(*test));
686  if (!test) {
687  ast_log(LOG_ERROR, "Failed to allocate test, registration failed.\n");
688  return NULL;
689  }
690 
691  test->cb = cb;
692 
693  test->cb(&test->info, TEST_INIT, test);
694 
695  if (ast_strlen_zero(test->info.name)) {
696  ast_log(LOG_ERROR, "Test has no name, test registration refused.\n");
697  return test_free(test);
698  }
699 
700  if (ast_strlen_zero(test->info.category)) {
701  ast_log(LOG_ERROR, "Test %s has no category, test registration refused.\n",
702  test->info.name);
703  return test_free(test);
704  }
705 
706  if (test->info.category[0] != '/' || test->info.category[strlen(test->info.category) - 1] != '/') {
707  ast_log(LOG_WARNING, "Test category '%s' for test '%s' is missing a leading or trailing slash.\n",
708  test->info.category, test->info.name);
709  /*
710  * Flag an error anyways so test_registrations fails but allow the
711  * test to be registered.
712  */
714  }
715 
716  if (ast_strlen_zero(test->info.summary)) {
717  ast_log(LOG_ERROR, "Test %s%s has no summary, test registration refused.\n",
718  test->info.category, test->info.name);
719  return test_free(test);
720  }
721  if (test->info.summary[strlen(test->info.summary) - 1] == '\n') {
722  ast_log(LOG_WARNING, "Test %s%s summary has a trailing newline.\n",
723  test->info.category, test->info.name);
724  /*
725  * Flag an error anyways so test_registrations fails but allow the
726  * test to be registered.
727  */
729  }
730 
731  if (ast_strlen_zero(test->info.description)) {
732  ast_log(LOG_ERROR, "Test %s%s has no description, test registration refused.\n",
733  test->info.category, test->info.name);
734  return test_free(test);
735  }
736  if (test->info.description[strlen(test->info.description) - 1] == '\n') {
737  ast_log(LOG_WARNING, "Test %s%s description has a trailing newline.\n",
738  test->info.category, test->info.name);
739  /*
740  * Flag an error anyways so test_registrations fails but allow the
741  * test to be registered.
742  */
744  }
745 
746  if (!(test->status_str = ast_str_create(128))) {
747  ast_log(LOG_ERROR, "Failed to allocate status_str for %s%s, test registration failed.\n",
748  test->info.category, test->info.name);
749  return test_free(test);
750  }
751 
752  return test;
753 }
const char * summary
Short summary of test.
Definition: test.h:237
static int registration_errors
Definition: test.c:111
#define LOG_WARNING
Definition: logger.h:274
static struct ast_test * test_free(struct ast_test *test)
Definition: test.c:665
#define NULL
Definition: resample.c:96
struct ast_str * status_str
Test defined status output from last execution.
Definition: test.c:70
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
const char * description
More detailed description of test.
Definition: test.h:243
const char * name
name of test, unique to category
Definition: test.h:223
#define LOG_ERROR
Definition: logger.h:285
const char * category
test category
Definition: test.h:231
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
ast_test_cb_t * cb
Definition: test.c:80
Definition: test.c:65
struct ast_test_info info
Definition: test.c:66
static struct ast_test * test
Definition: localtime.c:115
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ test_cat_cmp()

static int test_cat_cmp ( const char *  cat1,
const char *  cat2 
)
static

compares two test categories to determine if cat1 resides in cat2

Definition at line 642 of file test.c.

Referenced by ast_test_register_cleanup(), ast_test_register_init(), complete_test_name(), test_cli_show_registered(), test_execute_multiple(), and test_generate_results().

643 {
644  int len1 = 0;
645  int len2 = 0;
646 
647  if (!cat1 || !cat2) {
648  return -1;
649  }
650 
651  len1 = strlen(cat1);
652  len2 = strlen(cat2);
653 
654  if (len2 > len1) {
655  return -1;
656  }
657 
658  return strncmp(cat1, cat2, len2) ? 1 : 0;
659 }
const char cat1[]
Definition: test_config.c:68
const char cat2[]
Definition: test_config.c:76

◆ test_cleanup()

static void test_cleanup ( void  )
static

Definition at line 1211 of file test.c.

References ao2_cleanup, ARRAY_LEN, ast_cli_unregister_multiple(), AST_TEST_UNREGISTER, NULL, and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by AST_TEST_DEFINE(), ast_test_init(), test_performance(), test_traversal_nonsorted(), and test_traversal_sorted().

1212 {
1213  AST_TEST_UNREGISTER(test_registrations);
1217  STASIS_MESSAGE_TYPE_CLEANUP(ast_test_suite_message_type);
1218 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
#define NULL
Definition: resample.c:96
struct stasis_topic * test_suite_topic
The topic for test suite messages.
Definition: test.c:55
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ast_cli_entry test_cli[]
Definition: test.c:1062

◆ test_cli_execute_registered()

static char* test_cli_execute_registered ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 854 of file test.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), AST_LIST_LOCK, AST_LIST_UNLOCK, CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_test_category(), complete_test_name(), ast_cli_args::fd, ast_test_execute_results::last_failed, ast_test_execute_results::last_passed, last_results, NULL, ast_cli_args::pos, test_execute_multiple(), ast_cli_entry::usage, and ast_cli_args::word.

855 {
856  static const char * const option1[] = { "all", "category", NULL };
857  static const char * const option2[] = { "name", NULL };
858 
859  switch (cmd) {
860  case CLI_INIT:
861  e->command = "test execute";
862  e->usage =
863  "Usage: test execute can be used in three ways.\n"
864  " 1. 'test execute all' runs all registered tests\n"
865  " 2. 'test execute category [test category]' runs all tests in the given\n"
866  " category.\n"
867  " 3. 'test execute category [test category] name [test name]' runs all\n"
868  " tests in a given category matching a given name\n";
869  return NULL;
870  case CLI_GENERATE:
871  if (a->pos == 2) {
872  return ast_cli_complete(a->word, option1, -1);
873  }
874  if (a->pos == 3 && !strcasecmp(a->argv[2], "category")) {
875  return complete_test_category(a->word);
876  }
877  if (a->pos == 4) {
878  return ast_cli_complete(a->word, option2, -1);
879  }
880  if (a->pos == 5) {
881  return complete_test_name(a->word, a->argv[3]);
882  }
883  return NULL;
884  case CLI_HANDLER:
885 
886  if (a->argc < 3|| a->argc > 6) {
887  return CLI_SHOWUSAGE;
888  }
889 
890  if ((a->argc == 3) && !strcasecmp(a->argv[2], "all")) { /* run all registered tests */
891  ast_cli(a->fd, "Running all available tests...\n\n");
893  } else if (a->argc == 4) { /* run only tests within a category */
894  ast_cli(a->fd, "Running all available tests matching category %s\n\n", a->argv[3]);
895  test_execute_multiple(NULL, a->argv[3], a);
896  } else if (a->argc == 6) { /* run only a single test matching the category and name */
897  ast_cli(a->fd, "Running all available tests matching category %s and name %s\n\n", a->argv[3], a->argv[5]);
898  test_execute_multiple(a->argv[5], a->argv[3], a);
899  } else {
900  return CLI_SHOWUSAGE;
901  }
902 
905  ast_cli(a->fd, "--- No Tests Found! ---\n");
906  }
907  ast_cli(a->fd, "\n%u Test(s) Executed %u Passed %u Failed\n",
912  default:
913  return NULL;
914  }
915 
916  return CLI_SUCCESS;
917 }
static char * complete_test_name(const char *word, const char *category)
Definition: test.c:773
unsigned int last_failed
Definition: test.c:93
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
const int argc
Definition: cli.h:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static char * complete_test_category(const char *word)
Definition: test.c:755
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1811
const int fd
Definition: cli.h:159
unsigned int last_passed
Definition: test.c:92
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int test_execute_multiple(const char *name, const char *category, struct ast_cli_args *cli)
Definition: test.c:382
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
static struct ast_test_execute_results last_results
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
Definition: test.c:104
const int pos
Definition: cli.h:164

◆ test_cli_generate_results()

static char* test_cli_generate_results ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 990 of file test.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), ast_config_AST_LOG_DIR, ast_free, ast_str_buffer(), ast_str_create, ast_str_set(), ast_tvnow(), buf, CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, make_ari_stubs::file, NULL, ast_cli_args::pos, S_OR, test_generate_results(), type, ast_cli_entry::usage, and ast_cli_args::word.

991 {
992  static const char * const option[] = { "xml", "txt", NULL };
993  const char *file = NULL;
994  const char *type = "";
995  int isxml = 0;
996  int res = 0;
997  struct ast_str *buf = NULL;
998  struct timeval time = ast_tvnow();
999 
1000  switch (cmd) {
1001  case CLI_INIT:
1002  e->command = "test generate results";
1003  e->usage =
1004  "Usage: 'test generate results'\n"
1005  " Generates test results in either xml or txt format. An optional \n"
1006  " file path may be provided to specify the location of the xml or\n"
1007  " txt file\n"
1008  " \nExample usage:\n"
1009  " 'test generate results xml' this writes to a default file\n"
1010  " 'test generate results xml /path/to/file.xml' writes to specified file\n";
1011  return NULL;
1012  case CLI_GENERATE:
1013  if (a->pos == 3) {
1014  return ast_cli_complete(a->word, option, -1);
1015  }
1016  return NULL;
1017  case CLI_HANDLER:
1018 
1019  /* verify input */
1020  if (a->argc < 4 || a->argc > 5) {
1021  return CLI_SHOWUSAGE;
1022  } else if (!strcasecmp(a->argv[3], "xml")) {
1023  type = "xml";
1024  isxml = 1;
1025  } else if (!strcasecmp(a->argv[3], "txt")) {
1026  type = "txt";
1027  } else {
1028  return CLI_SHOWUSAGE;
1029  }
1030 
1031  if (a->argc == 5) {
1032  file = a->argv[4];
1033  } else {
1034  if (!(buf = ast_str_create(256))) {
1035  return NULL;
1036  }
1037  ast_str_set(&buf, 0, "%s/asterisk_test_results-%ld.%s", ast_config_AST_LOG_DIR, (long) time.tv_sec, type);
1038 
1039  file = ast_str_buffer(buf);
1040  }
1041 
1042  if (isxml) {
1043  res = test_generate_results(NULL, NULL, file, NULL);
1044  } else {
1045  res = test_generate_results(NULL, NULL, NULL, file);
1046  }
1047 
1048  if (!res) {
1049  ast_cli(a->fd, "Results Generated Successfully: %s\n", S_OR(file, ""));
1050  } else {
1051  ast_cli(a->fd, "Results Could Not Be Generated: %s\n", S_OR(file, ""));
1052  }
1053 
1054  ast_free(buf);
1055  default:
1056  return NULL;
1057  }
1058 
1059  return CLI_SUCCESS;
1060 }
static const char type[]
Definition: chan_ooh323.c:109
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
const int argc
Definition: cli.h:160
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Definition: cli.h:152
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
static int test_generate_results(const char *name, const char *category, const char *xml_path, const char *txt_path)
Definition: test.c:492
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1811
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
const int fd
Definition: cli.h:159
const char *const * argv
Definition: cli.h:161
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define CLI_SHOWUSAGE
Definition: cli.h:45
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
#define ast_free(a)
Definition: astmm.h:182
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const int pos
Definition: cli.h:164
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ test_cli_show_registered()

static char* test_cli_show_registered ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 792 of file test.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_test_info::category, CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_test_category(), complete_test_name(), ast_cli_args::fd, FORMAT, ast_test::info, ast_test_info::name, NULL, ast_cli_args::pos, ast_test::state, ast_test_info::summary, test_cat_cmp(), test_result2str, ast_cli_entry::usage, and ast_cli_args::word.

793 {
794 #define FORMAT "%-25.25s %-30.30s %-40.40s %-13.13s\n"
795  static const char * const option1[] = { "all", "category", NULL };
796  static const char * const option2[] = { "name", NULL };
797  struct ast_test *test = NULL;
798  int count = 0;
799  switch (cmd) {
800  case CLI_INIT:
801  e->command = "test show registered";
802 
803  e->usage =
804  "Usage: 'test show registered' can be used in three ways.\n"
805  " 1. 'test show registered all' shows all registered tests\n"
806  " 2. 'test show registered category [test category]' shows all tests in the given\n"
807  " category.\n"
808  " 3. 'test show registered category [test category] name [test name]' shows all\n"
809  " tests in a given category matching a given name\n";
810  return NULL;
811  case CLI_GENERATE:
812  if (a->pos == 3) {
813  return ast_cli_complete(a->word, option1, -1);
814  }
815  if (a->pos == 4 && !strcasecmp(a->argv[3], "category")) {
816  return complete_test_category(a->word);
817  }
818  if (a->pos == 5) {
819  return ast_cli_complete(a->word, option2, -1);
820  }
821  if (a->pos == 6) {
822  return complete_test_name(a->word, a->argv[4]);
823  }
824  return NULL;
825  case CLI_HANDLER:
826  if ((a->argc < 4) || (a->argc == 6) || (a->argc > 7) ||
827  ((a->argc == 4) && strcasecmp(a->argv[3], "all")) ||
828  ((a->argc == 7) && strcasecmp(a->argv[5], "name"))) {
829  return CLI_SHOWUSAGE;
830  }
831  ast_cli(a->fd, FORMAT, "Category", "Name", "Summary", "Test Result");
832  ast_cli(a->fd, FORMAT, "--------", "----", "-------", "-----------");
834  AST_LIST_TRAVERSE(&tests, test, entry) {
835  if ((a->argc == 4) ||
836  ((a->argc == 5) && !test_cat_cmp(test->info.category, a->argv[4])) ||
837  ((a->argc == 7) && !strcmp(test->info.category, a->argv[4]) && !strcmp(test->info.name, a->argv[6]))) {
838 
839  ast_cli(a->fd, FORMAT, test->info.category, test->info.name,
840  test->info.summary, test_result2str[test->state]);
841  count++;
842  }
843  }
845  ast_cli(a->fd, FORMAT, "--------", "----", "-------", "-----------");
846  ast_cli(a->fd, "\n%d Registered Tests Matched\n", count);
847  default:
848  return NULL;
849  }
850 
851  return CLI_SUCCESS;
852 }
static char * complete_test_name(const char *word, const char *category)
Definition: test.c:773
const char * summary
Short summary of test.
Definition: test.h:237
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
const int argc
Definition: cli.h:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static char * complete_test_category(const char *word)
Definition: test.c:755
Definition: cli.h:152
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1811
const int fd
Definition: cli.h:159
const char * name
name of test, unique to category
Definition: test.h:223
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
static int test_cat_cmp(const char *cat1, const char *cat2)
compares two test categories to determine if cat1 resides in cat2
Definition: test.c:642
const char * category
test category
Definition: test.h:231
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
#define FORMAT
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
Definition: test.c:65
Definition: test.c:104
struct ast_test_info info
Definition: test.c:66
const int pos
Definition: cli.h:164
Definition: search.h:40
enum ast_test_result_state state
Definition: test.c:78
static const char *const test_result2str[]
Definition: test.c:58

◆ test_cli_show_results()

static char* test_cli_show_results ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 919 of file test.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_info::category, CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_GREEN, COLOR_RED, ast_cli_entry::command, ast_cli_args::fd, FORMAT_RES_ALL1, FORMAT_RES_ALL2, ast_test::info, ast_test_info::name, NULL, ast_cli_args::pos, result_buf, ast_test::state, term_color(), test_result2str, ast_test::time, ast_cli_entry::usage, and ast_cli_args::word.

920 {
921 #define FORMAT_RES_ALL1 "%s%s %-30.30s %-25.25s %-10.10s\n"
922 #define FORMAT_RES_ALL2 "%s%s %-30.30s %-25.25s %s%ums\n"
923  static const char * const option1[] = { "all", "failed", "passed", NULL };
924  char result_buf[32] = { 0 };
925  struct ast_test *test = NULL;
926  int failed = 0;
927  int passed = 0;
928  int mode; /* 0 for show all, 1 for show fail, 2 for show passed */
929 
930  switch (cmd) {
931  case CLI_INIT:
932  e->command = "test show results";
933  e->usage =
934  "Usage: test show results can be used in three ways\n"
935  " 1. 'test show results all' Displays results for all executed tests.\n"
936  " 2. 'test show results passed' Displays results for all passed tests.\n"
937  " 3. 'test show results failed' Displays results for all failed tests.\n";
938  return NULL;
939  case CLI_GENERATE:
940  if (a->pos == 3) {
941  return ast_cli_complete(a->word, option1, -1);
942  }
943  return NULL;
944  case CLI_HANDLER:
945 
946  /* verify input */
947  if (a->argc != 4) {
948  return CLI_SHOWUSAGE;
949  } else if (!strcasecmp(a->argv[3], "passed")) {
950  mode = 2;
951  } else if (!strcasecmp(a->argv[3], "failed")) {
952  mode = 1;
953  } else if (!strcasecmp(a->argv[3], "all")) {
954  mode = 0;
955  } else {
956  return CLI_SHOWUSAGE;
957  }
958 
959  ast_cli(a->fd, FORMAT_RES_ALL1, "Result", "", "Name", "Category", "Time");
961  AST_LIST_TRAVERSE(&tests, test, entry) {
962  if (test->state == AST_TEST_NOT_RUN) {
963  continue;
964  }
965  test->state == AST_TEST_FAIL ? failed++ : passed++;
966  if (!mode || ((mode == 1) && (test->state == AST_TEST_FAIL)) || ((mode == 2) && (test->state == AST_TEST_PASS))) {
967  /* give our results pretty colors */
968  term_color(result_buf, test_result2str[test->state],
969  (test->state == AST_TEST_FAIL) ? COLOR_RED : COLOR_GREEN,
970  0, sizeof(result_buf));
971 
973  result_buf,
974  " ",
975  test->info.name,
976  test->info.category,
977  test->time ? " " : "<",
978  test->time ? test->time : 1);
979  }
980  }
982 
983  ast_cli(a->fd, "%d Test(s) Executed %d Passed %d Failed\n", (failed + passed), passed, failed);
984  default:
985  return NULL;
986  }
987  return CLI_SUCCESS;
988 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
const int argc
Definition: cli.h:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:152
#define COLOR_GREEN
Definition: term.h:51
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1811
const int fd
Definition: cli.h:159
unsigned int time
Definition: test.c:79
const char * name
name of test, unique to category
Definition: test.h:223
#define COLOR_RED
Definition: term.h:49
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:184
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
const char * category
test category
Definition: test.h:231
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
#define FORMAT_RES_ALL1
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
Definition: test.c:65
Definition: test.c:104
static struct ast_threadstorage result_buf
Definition: func_sprintf.c:42
struct ast_test_info info
Definition: test.c:66
const int pos
Definition: cli.h:164
Definition: search.h:40
#define FORMAT_RES_ALL2
enum ast_test_result_state state
Definition: test.c:78
static const char *const test_result2str[]
Definition: test.c:58

◆ test_execute()

static void test_execute ( struct ast_test test)
static

Definition at line 238 of file test.c.

References ast_str_reset(), AST_TEST_FAIL, AST_TEST_NOT_RUN, ast_tvdiff_ms(), ast_tvnow(), ast_test::cb, ast_test::cleanup_cb, ast_test::info, ast_test::init_cb, result, ast_test::state, ast_test::status_str, TEST_EXECUTE, and ast_test::time.

Referenced by test_execute_multiple().

239 {
240  struct timeval begin;
242 
243  ast_str_reset(test->status_str);
244 
245  begin = ast_tvnow();
246  if (test->init_cb && test->init_cb(&test->info, test)) {
247  test->state = AST_TEST_FAIL;
248  goto exit;
249  }
250  test->state = AST_TEST_NOT_RUN;
251  result = test->cb(&test->info, TEST_EXECUTE, test);
252  if (test->state != AST_TEST_FAIL) {
253  test->state = result;
254  }
255  if (test->cleanup_cb && test->cleanup_cb(&test->info, test)) {
256  test->state = AST_TEST_FAIL;
257  }
258 exit:
259  test->time = ast_tvdiff_ms(ast_tvnow(), begin);
260 }
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
struct ast_str * status_str
Test defined status output from last execution.
Definition: test.c:70
ast_test_cleanup_cb_t * cleanup_cb
Definition: test.c:82
unsigned int time
Definition: test.c:79
ast_test_cb_t * cb
Definition: test.c:80
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:653
struct ast_test_info info
Definition: test.c:66
static PGresult * result
Definition: cel_pgsql.c:88
ast_test_init_cb_t * init_cb
Definition: test.c:81
enum ast_test_result_state state
Definition: test.c:78
ast_test_result_state
Definition: test.h:200

◆ test_execute_multiple()

static int test_execute_multiple ( const char *  name,
const char *  category,
struct ast_cli_args cli 
)
static

Definition at line 382 of file test.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_info::category, ast_test::cli, COLOR_GREEN, COLOR_RED, execute(), ast_test_info::explicit_only, ast_cli_args::fd, ast_test::info, ast_test_execute_results::last_failed, ast_test_execute_results::last_passed, last_results, ast_test_execute_results::last_time, ast_test_info::name, NULL, result_buf, ast_test::state, term_color(), TEST_ALL, test_cat_cmp(), TEST_CATEGORY, test_execute(), TEST_NAME_CATEGORY, test_result2str, ast_test::time, ast_test_execute_results::total_failed, ast_test_execute_results::total_passed, ast_test_execute_results::total_tests, and ast_test_execute_results::total_time.

Referenced by test_cli_execute_registered().

383 {
384  char result_buf[32] = { 0 };
385  struct ast_test *test = NULL;
386  enum test_mode mode = TEST_ALL; /* 3 modes, 0 = run all, 1 = only by category, 2 = only by name and category */
387  int execute = 0;
388  int res = 0;
389 
390  if (!ast_strlen_zero(category)) {
391  if (!ast_strlen_zero(name)) {
392  mode = TEST_NAME_CATEGORY;
393  } else {
394  mode = TEST_CATEGORY;
395  }
396  }
397 
399  /* clear previous execution results */
400  memset(&last_results, 0, sizeof(last_results));
401  AST_LIST_TRAVERSE(&tests, test, entry) {
402 
403  execute = 0;
404  switch (mode) {
405  case TEST_CATEGORY:
406  if (!test_cat_cmp(test->info.category, category) && !test->info.explicit_only) {
407  execute = 1;
408  }
409  break;
410  case TEST_NAME_CATEGORY:
411  if (!(test_cat_cmp(test->info.category, category)) && !(strcmp(test->info.name, name))) {
412  execute = 1;
413  }
414  break;
415  case TEST_ALL:
416  execute = !test->info.explicit_only;
417  }
418 
419  if (execute) {
420  if (cli) {
421  ast_cli(cli->fd, "START %s - %s \n", test->info.category, test->info.name);
422  }
423 
424  /* set the test status update argument. it is ok if cli is NULL */
425  test->cli = cli;
426 
427  /* execute the test and save results */
428  test_execute(test);
429 
430  test->cli = NULL;
431 
432  /* update execution specific counts here */
433  last_results.last_time += test->time;
434  if (test->state == AST_TEST_PASS) {
436  } else if (test->state == AST_TEST_FAIL) {
438  }
439 
440  if (cli) {
441  term_color(result_buf,
442  test_result2str[test->state],
443  (test->state == AST_TEST_FAIL) ? COLOR_RED : COLOR_GREEN,
444  0,
445  sizeof(result_buf));
446  ast_cli(cli->fd, "END %s - %s Time: %s%ums Result: %s\n",
447  test->info.category,
448  test->info.name,
449  test->time ? "" : "<",
450  test->time ? test->time : 1,
451  result_buf);
452  }
453  }
454 
455  /* update total counts as well during this iteration
456  * even if the current test did not execute this time */
457  last_results.total_time += test->time;
459  if (test->state != AST_TEST_NOT_RUN) {
460  if (test->state == AST_TEST_PASS) {
462  } else {
464  }
465  }
466  }
469 
470  return res;
471 }
unsigned int total_time
Definition: test.c:91
unsigned int last_failed
Definition: test.c:93
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void test_execute(struct ast_test *test)
Definition: test.c:238
static SQLHSTMT execute(struct odbc_obj *obj, void *data, int silent)
Common execution function for SQL queries.
Definition: func_odbc.c:454
unsigned int last_time
Definition: test.c:94
test_mode
Definition: test.c:97
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define COLOR_GREEN
Definition: term.h:51
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ast_strlen_zero(foo)
Definition: strings.h:52
const int fd
Definition: cli.h:159
struct ast_cli_args * cli
CLI arguments, if tests being run from the CLI.
Definition: test.c:77
unsigned int last_passed
Definition: test.c:92
unsigned int total_passed
Definition: test.c:89
unsigned int time
Definition: test.c:79
unsigned int total_failed
Definition: test.c:90
const char * name
name of test, unique to category
Definition: test.h:223
#define COLOR_RED
Definition: term.h:49
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:184
static struct ast_cli_entry cli[]
Definition: codec_dahdi.c:265
static int test_cat_cmp(const char *cat1, const char *cat2)
compares two test categories to determine if cat1 resides in cat2
Definition: test.c:642
const char * category
test category
Definition: test.h:231
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
Definition: cdr_mysql.c:74
unsigned int explicit_only
Only run if explicitly named.
Definition: test.h:251
static struct ast_test_execute_results last_results
Definition: test.c:65
Definition: test.c:104
static struct ast_threadstorage result_buf
Definition: func_sprintf.c:42
struct ast_test_info info
Definition: test.c:66
Definition: test.c:98
Definition: search.h:40
unsigned int total_tests
Definition: test.c:88
enum ast_test_result_state state
Definition: test.c:78
static const char *const test_result2str[]
Definition: test.c:58

◆ test_free()

static struct ast_test * test_free ( struct ast_test test)
static

Definition at line 665 of file test.c.

References ast_free, NULL, and ast_test::status_str.

Referenced by ast_test_register(), ast_test_unregister(), and test_alloc().

666 {
667  if (!test) {
668  return NULL;
669  }
670 
671  ast_free(test->status_str);
672  ast_free(test);
673 
674  return NULL;
675 }
#define NULL
Definition: resample.c:96
struct ast_str * status_str
Test defined status output from last execution.
Definition: test.c:70
#define ast_free(a)
Definition: astmm.h:182

◆ test_generate_results()

static int test_generate_results ( const char *  name,
const char *  category,
const char *  xml_path,
const char *  txt_path 
)
static

Definition at line 492 of file test.c.

References ast_get_version(), ast_get_version_num(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_strlen_zero, ast_test_info::category, done, ast_test::info, last_results, LOG_WARNING, ast_test_info::name, NULL, TEST_ALL, test_cat_cmp(), TEST_CATEGORY, TEST_NAME_CATEGORY, test_txt_entry(), test_xml_entry(), ast_test_execute_results::total_failed, ast_test_execute_results::total_passed, ast_test_execute_results::total_tests, and ast_test_execute_results::total_time.

Referenced by test_cli_generate_results().

493 {
494  enum test_mode mode = TEST_ALL; /* 0 generate all, 1 generate by category only, 2 generate by name and category */
495  FILE *f_xml = NULL, *f_txt = NULL;
496  int res = 0;
497  struct ast_test *test = NULL;
498 
499  /* verify at least one output file was given */
500  if (ast_strlen_zero(xml_path) && ast_strlen_zero(txt_path)) {
501  return -1;
502  }
503 
504  /* define what mode is to be used */
505  if (!ast_strlen_zero(category)) {
506  if (!ast_strlen_zero(name)) {
507  mode = TEST_NAME_CATEGORY;
508  } else {
509  mode = TEST_CATEGORY;
510  }
511  }
512  /* open files for writing */
513  if (!ast_strlen_zero(xml_path)) {
514  if (!(f_xml = fopen(xml_path, "w"))) {
515  ast_log(LOG_WARNING, "Could not open file %s for xml test results\n", xml_path);
516  res = -1;
517  goto done;
518  }
519  }
520  if (!ast_strlen_zero(txt_path)) {
521  if (!(f_txt = fopen(txt_path, "w"))) {
522  ast_log(LOG_WARNING, "Could not open file %s for text output of test results\n", txt_path);
523  res = -1;
524  goto done;
525  }
526  }
527 
529  /* xml header information */
530  if (f_xml) {
531  /*
532  * http://confluence.atlassian.com/display/BAMBOO/JUnit+parsing+in+Bamboo
533  */
534  fprintf(f_xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
535  fprintf(f_xml, "<testsuites>\n");
536  fprintf(f_xml, "\t<testsuite errors=\"0\" time=\"%u.%u\" tests=\"%u\" "
537  "name=\"AsteriskUnitTests\">\n",
540  fprintf(f_xml, "\t\t<properties>\n");
541  fprintf(f_xml, "\t\t\t<property name=\"version\" value=\"%s\"/>\n", ast_get_version());
542  fprintf(f_xml, "\t\t</properties>\n");
543  }
544 
545  /* txt header information */
546  if (f_txt) {
547  fprintf(f_txt, "Asterisk Version: %s\n", ast_get_version());
548  fprintf(f_txt, "Asterisk Version Number: %s\n", ast_get_version_num());
549  fprintf(f_txt, "Number of Tests: %u\n", last_results.total_tests);
550  fprintf(f_txt, "Number of Tests Executed: %u\n", (last_results.total_passed + last_results.total_failed));
551  fprintf(f_txt, "Passed Tests: %u\n", last_results.total_passed);
552  fprintf(f_txt, "Failed Tests: %u\n", last_results.total_failed);
553  fprintf(f_txt, "Total Execution Time: %u\n", last_results.total_time);
554  }
555 
556  /* export each individual test */
557  AST_LIST_TRAVERSE(&tests, test, entry) {
558  switch (mode) {
559  case TEST_CATEGORY:
560  if (!test_cat_cmp(test->info.category, category)) {
561  test_xml_entry(test, f_xml);
562  test_txt_entry(test, f_txt);
563  }
564  break;
565  case TEST_NAME_CATEGORY:
566  if (!(strcmp(test->info.category, category)) && !(strcmp(test->info.name, name))) {
567  test_xml_entry(test, f_xml);
568  test_txt_entry(test, f_txt);
569  }
570  break;
571  case TEST_ALL:
572  test_xml_entry(test, f_xml);
573  test_txt_entry(test, f_txt);
574  }
575  }
577 
578 done:
579  if (f_xml) {
580  fprintf(f_xml, "\t</testsuite>\n");
581  fprintf(f_xml, "</testsuites>\n");
582  fclose(f_xml);
583  }
584  if (f_txt) {
585  fclose(f_txt);
586  }
587 
588  return res;
589 }
unsigned int total_time
Definition: test.c:91
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
test_mode
Definition: test.c:97
const char * ast_get_version(void)
Retrieve the Asterisk version string.
Definition: version.c:16
#define LOG_WARNING
Definition: logger.h:274
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define NULL
Definition: resample.c:96
static void test_xml_entry(struct ast_test *test, FILE *f)
Definition: test.c:300
#define ast_strlen_zero(foo)
Definition: strings.h:52
int done
Definition: test_amihooks.c:48
#define ast_log
Definition: astobj2.c:42
unsigned int total_passed
Definition: test.c:89
unsigned int total_failed
Definition: test.c:90
const char * name
name of test, unique to category
Definition: test.h:223
static int test_cat_cmp(const char *cat1, const char *cat2)
compares two test categories to determine if cat1 resides in cat2
Definition: test.c:642
const char * category
test category
Definition: test.h:231
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
Definition: cdr_mysql.c:74
const char * ast_get_version_num(void)
Retrieve the numeric Asterisk version.
Definition: version.c:21
static struct ast_test_execute_results last_results
Definition: test.c:65
Definition: test.c:104
struct ast_test_info info
Definition: test.c:66
static void test_txt_entry(struct ast_test *test, FILE *f)
Definition: test.c:348
Definition: test.c:98
Definition: search.h:40
unsigned int total_tests
Definition: test.c:88

◆ test_insert()

static int test_insert ( struct ast_test test)
static

Definition at line 598 of file test.c.

References AST_LIST_INSERT_SORTALPHA, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_test_info::category, and ast_test::info.

Referenced by ast_test_register().

599 {
600  /* This is a slow operation that may need to be optimized in the future
601  * as the test framework expands. At the moment we are doing string
602  * comparisons on every item within the list to insert in sorted order. */
603 
605  AST_LIST_INSERT_SORTALPHA(&tests, test, entry, info.category);
607 
608  return 0;
609 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_LIST_INSERT_SORTALPHA(head, elm, field, sortfield)
Inserts a list entry into a alphabetically sorted list.
Definition: linkedlists.h:750
def info(msg)
Definition: test.c:104
Definition: search.h:40

◆ test_remove()

static struct ast_test * test_remove ( ast_test_cb_t *  cb)
static

Definition at line 617 of file test.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_test::cb, and NULL.

Referenced by ast_test_unregister().

618 {
619  struct ast_test *cur = NULL;
620 
623  if (cur->cb == cb) {
625  break;
626  }
627  }
630 
631  return cur;
632 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define NULL
Definition: resample.c:96
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
ast_test_cb_t * cb
Definition: test.c:80
Definition: test.c:65
Definition: test.c:104
Definition: search.h:40
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528

◆ test_suite_event_to_ami()

static struct ast_manager_event_blob* test_suite_event_to_ami ( struct stasis_message msg)
static

Definition at line 1100 of file test.c.

References ast_free, ast_json_integer_get(), ast_json_object_get(), ast_json_string_get(), ast_manager_event_blob_create(), ast_str_append(), ast_str_buffer(), ast_str_create, ast_strlen_zero, ast_test_suite_get_blob(), EVENT_FLAG_REPORTING, NULL, RAII_VAR, stasis_message_data(), STASIS_MESSAGE_TYPE_DEFN(), to_ami(), and type.

1101 {
1102  RAII_VAR(struct ast_str *, packet_string, ast_str_create(128), ast_free);
1103  struct ast_test_suite_message_payload *payload;
1104  struct ast_json *blob;
1105  const char *type;
1106 
1107  payload = stasis_message_data(msg);
1108  if (!payload) {
1109  return NULL;
1110  }
1111  blob = ast_test_suite_get_blob(payload);
1112  if (!blob) {
1113  return NULL;
1114  }
1115 
1116  type = ast_json_string_get(ast_json_object_get(blob, "type"));
1117  if (ast_strlen_zero(type) || strcmp("testevent", type)) {
1118  return NULL;
1119  }
1120 
1121  ast_str_append(&packet_string, 0, "Type: StateChange\r\n");
1122  ast_str_append(&packet_string, 0, "State: %s\r\n",
1123  ast_json_string_get(ast_json_object_get(blob, "state")));
1124  ast_str_append(&packet_string, 0, "AppFile: %s\r\n",
1125  ast_json_string_get(ast_json_object_get(blob, "appfile")));
1126  ast_str_append(&packet_string, 0, "AppFunction: %s\r\n",
1127  ast_json_string_get(ast_json_object_get(blob, "appfunction")));
1128  ast_str_append(&packet_string, 0, "AppLine: %jd\r\n",
1129  ast_json_integer_get(ast_json_object_get(blob, "line")));
1130  ast_str_append(&packet_string, 0, "%s\r\n",
1131  ast_json_string_get(ast_json_object_get(blob, "data")));
1132 
1134  "TestEvent",
1135  "%s",
1136  ast_str_buffer(packet_string));
1137 }
static const char type[]
Definition: chan_ooh323.c:109
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define NULL
Definition: resample.c:96
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.
Definition: manager.c:9727
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_json * ast_test_suite_get_blob(struct ast_test_suite_message_payload *payload)
Definition: test.c:1095
#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
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
#define ast_free(a)
Definition: astmm.h:182
A wrapper object that can be ao2 ref counted around an ast_json blob.
Definition: test.c:1078
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
Abstract JSON element (object, array, string, int, ...).
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:322
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ test_suite_message_payload_dtor()

static void test_suite_message_payload_dtor ( void *  obj)
static

Definition at line 1086 of file test.c.

References ast_json_unref(), and ast_test_suite_message_payload::blob.

Referenced by __ast_test_suite_event_notify().

1087 {
1088  struct ast_test_suite_message_payload *payload = obj;
1089 
1090  if (payload->blob) {
1091  ast_json_unref(payload->blob);
1092  }
1093 }
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
A wrapper object that can be ao2 ref counted around an ast_json blob.
Definition: test.c:1078
struct ast_json * blob
Definition: test.c:1079

◆ test_txt_entry()

static void test_txt_entry ( struct ast_test test,
FILE *  f 
)
static

Definition at line 348 of file test.c.

References ast_str_buffer(), AST_TEST_FAIL, AST_TEST_NOT_RUN, ast_test_info::category, ast_test_info::description, ast_test::info, ast_test_info::name, S_OR, ast_test::state, ast_test::status_str, ast_test_info::summary, test_result2str, and ast_test::time.

Referenced by test_generate_results().

349 {
350  if (!f || !test) {
351  return;
352  }
353 
354  fprintf(f, "\nName: %s\n", test->info.name);
355  fprintf(f, "Category: %s\n", test->info.category);
356  fprintf(f, "Summary: %s\n", test->info.summary);
357  fprintf(f, "Description: %s\n", test->info.description);
358  fprintf(f, "Result: %s\n", test_result2str[test->state]);
359  if (test->state != AST_TEST_NOT_RUN) {
360  fprintf(f, "Time: %u\n", test->time);
361  }
362  if (test->state == AST_TEST_FAIL) {
363  fprintf(f, "Error Description: %s\n\n", S_OR(ast_str_buffer(test->status_str), "NA"));
364  }
365 }
const char * summary
Short summary of test.
Definition: test.h:237
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
struct ast_str * status_str
Test defined status output from last execution.
Definition: test.c:70
unsigned int time
Definition: test.c:79
const char * description
More detailed description of test.
Definition: test.h:243
const char * name
name of test, unique to category
Definition: test.h:223
const char * category
test category
Definition: test.h:231
struct ast_test_info info
Definition: test.c:66
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
enum ast_test_result_state state
Definition: test.c:78
static const char *const test_result2str[]
Definition: test.c:58

◆ test_xml_entry()

static void test_xml_entry ( struct ast_test test,
FILE *  f 
)
static

Definition at line 300 of file test.c.

References ast_alloca, ast_free, ast_str_append(), ast_str_buffer(), ast_str_create, ast_strdupa, ast_strsep(), AST_STRSEP_TRIM, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_info::category, ast_test::info, is_reserved_word(), ast_test_info::name, prefix, S_OR, ast_test::state, ast_test::status_str, and ast_test::time.

Referenced by test_generate_results().

301 {
302  /* We need a copy of the category skipping past the initial '/' */
303  char *test_cat = ast_strdupa(test->info.category + 1);
304  char *next_cat;
305  char *test_name = (char *)test->info.name;
306  struct ast_str *category = ast_str_create(strlen(test->info.category) + 32);
307 
308  if (!category || test->state == AST_TEST_NOT_RUN) {
309  ast_free(category);
310 
311  return;
312  }
313 
314  while ((next_cat = ast_strsep(&test_cat, '/', AST_STRSEP_TRIM))) {
315  char *prefix = "";
316 
317  if (is_reserved_word(next_cat)) {
318  prefix = "_";
319  }
320  ast_str_append(&category, 0, ".%s%s", prefix, next_cat);
321  }
322  test_cat = ast_str_buffer(category);
323  /* Skip past the initial '.' */
324  test_cat++;
325 
326  if (is_reserved_word(test->info.name)) {
327  size_t name_length = strlen(test->info.name) + 2;
328 
329  test_name = ast_alloca(name_length);
330  snprintf(test_name, name_length, "_%s", test->info.name);
331  }
332 
333  fprintf(f, "\t\t<testcase time=\"%u.%u\" classname=\"%s\" name=\"%s\"%s>\n",
334  test->time / 1000, test->time % 1000,
335  test_cat, test_name,
336  test->state == AST_TEST_PASS ? "/" : "");
337 
338  ast_free(category);
339 
340  if (test->state == AST_TEST_FAIL) {
341  fprintf(f, "\t\t\t<failure><![CDATA[\n%s\n\t\t]]></failure>\n",
342  S_OR(ast_str_buffer(test->status_str), "NA"));
343  fprintf(f, "\t\t</testcase>\n");
344  }
345 
346 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
struct ast_str * status_str
Test defined status output from last execution.
Definition: test.c:70
unsigned int time
Definition: test.c:79
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition: main/utils.c:1656
const char * name
name of test, unique to category
Definition: test.h:223
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
static int is_reserved_word(const char *word)
Definition: test.c:287
const char * category
test category
Definition: test.h:231
#define ast_free(a)
Definition: astmm.h:182
struct ast_test_info info
Definition: test.c:66
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
enum ast_test_result_state state
Definition: test.c:78
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620
static char prefix[MAX_PREFIX]
Definition: http.c:141

Variable Documentation

◆ last_results

struct ast_test_execute_results last_results
static

◆ registration_errors

int registration_errors = 0
static

Definition at line 111 of file test.c.

Referenced by AST_TEST_DEFINE(), ast_test_register(), and test_alloc().

◆ reserved_words

char* reserved_words[]
static

Definition at line 274 of file test.c.

Referenced by is_reserved_word().

◆ test_cli

struct ast_cli_entry test_cli[]
static

Definition at line 1062 of file test.c.

◆ test_result2str

const char* const test_result2str[]
static
Initial value:
= {
[AST_TEST_NOT_RUN] = "NOT RUN",
[AST_TEST_PASS] = "PASS",
[AST_TEST_FAIL] = "FAIL",
}

This array corresponds to the values defined in the ast_test_state enum

Definition at line 58 of file test.c.

Referenced by test_cli_show_registered(), test_cli_show_results(), test_execute_multiple(), and test_txt_entry().

◆ test_suite_topic

struct stasis_topic* test_suite_topic

The topic for test suite messages.

Since
12

Definition at line 55 of file test.c.

Referenced by ast_test_suite_topic().

◆ tests

struct tests tests = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static