54 #define TEST_CATEGORY "/main/cel/" 56 #define CHANNEL_TECH_NAME "CELTestChannel" 58 #define TEST_BACKEND_NAME "CEL Test Logging" 81 .description =
"Mock channel technology for CEL tests",
93 #define APPEND_EVENT(chan, ev_type, userevent, extra) do { \ 94 if (append_expected_event(chan, ev_type, userevent, extra, NULL)) { \ 95 return AST_TEST_FAIL; \ 99 #define APPEND_EVENT_PEER(chan, ev_type, userevent, extra, peer) do { \ 100 if (append_expected_event(chan, ev_type, userevent, extra, peer)) { \ 101 return AST_TEST_FAIL; \ 105 #define APPEND_EVENT_SNAPSHOT(snapshot, ev_type, userevent, extra, peer) do { \ 106 if (append_expected_event_snapshot(snapshot, ev_type, userevent, extra, peer)) { \ 107 return AST_TEST_FAIL; \ 111 #define APPEND_DUMMY_EVENT() do { \ 112 if (append_dummy_event()) { \ 113 return AST_TEST_FAIL; \ 117 #define BRIDGE_EXIT(channel, bridge) do { \ 118 ast_test_validate(test, !ast_bridge_depart(channel)); \ 119 BRIDGE_EXIT_EVENT(channel, bridge); \ 123 #define BRIDGE_EXIT_EVENT(channel, bridge) do { \ 124 RAII_VAR(struct ast_str *, peer_str, NULL, ast_free); \ 125 peer_str = test_cel_generate_peer_str(channel, bridge); \ 126 ast_test_validate(test, peer_str != NULL); \ 127 BRIDGE_EXIT_EVENT_PEER(channel, bridge, ast_str_buffer(peer_str)); \ 130 #define BRIDGE_EXIT_EVENT_PEER(channel, bridge, peer) do { \ 131 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \ 132 extra = ast_json_pack("{s: s, s: s}", "bridge_id", bridge->uniqueid, "bridge_technology", bridge->technology->name); \ 133 ast_test_validate(test, extra != NULL); \ 134 APPEND_EVENT_PEER(channel, AST_CEL_BRIDGE_EXIT, NULL, extra, peer); \ 137 #define BRIDGE_EXIT_SNAPSHOT(channel, bridge) do { \ 138 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \ 139 RAII_VAR(struct ast_str *, peer_str, NULL, ast_free); \ 140 peer_str = test_cel_generate_peer_str_snapshot(channel, bridge); \ 141 ast_test_validate(test, peer_str != NULL); \ 142 extra = ast_json_pack("{s: s, s: s}", "bridge_id", bridge->uniqueid, "bridge_technology", bridge->technology->name); \ 143 ast_test_validate(test, extra != NULL); \ 144 APPEND_EVENT_SNAPSHOT(channel, AST_CEL_BRIDGE_EXIT, NULL, extra, ast_str_buffer(peer_str)); \ 147 #define BRIDGE_ENTER(channel, bridge) do { \ 148 ast_test_validate(test, !ast_bridge_impart(bridge, channel, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); \ 150 BRIDGE_ENTER_EVENT(channel, bridge); \ 154 #define BRIDGE_ENTER_EVENT(channel, bridge) do { \ 155 RAII_VAR(struct ast_str *, peer_str, NULL, ast_free); \ 156 peer_str = test_cel_generate_peer_str(channel, bridge); \ 157 ast_test_validate(test, peer_str != NULL); \ 158 BRIDGE_ENTER_EVENT_PEER(channel, bridge, ast_str_buffer(peer_str)); \ 161 #define BRIDGE_ENTER_EVENT_PEER(channel, bridge, peer) do { \ 162 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \ 163 extra = ast_json_pack("{s: s, s: s}", "bridge_id", bridge->uniqueid, "bridge_technology", bridge->technology->name); \ 164 ast_test_validate(test, extra != NULL); \ 165 APPEND_EVENT_PEER(channel, AST_CEL_BRIDGE_ENTER, NULL, extra, peer); \ 168 #define BLINDTRANSFER_EVENT(channel, bridge, extension, context) do { \ 169 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \ 170 extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}", \ 171 "extension", extension, \ 172 "context", context, \ 173 "bridge_id", bridge->uniqueid, \ 174 "transferee_channel_name", "N/A", \ 175 "transferee_channel_uniqueid", "N/A"); \ 176 ast_test_validate(test, extra != NULL); \ 177 APPEND_EVENT(channel, AST_CEL_BLINDTRANSFER, NULL, extra); \ 180 #define ATTENDEDTRANSFER_BRIDGE(channel1, bridge1, channel2, bridge2, channel3, channel4) do { \ 181 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \ 182 extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}", \ 183 "bridge1_id", bridge1->uniqueid, \ 184 "channel2_name", ast_channel_name(channel2), \ 185 "channel2_uniqueid", ast_channel_uniqueid(channel2), \ 186 "bridge2_id", bridge2->uniqueid, \ 187 "transferee_channel_name", ast_channel_name(channel4), \ 188 "transferee_channel_uniqueid", ast_channel_uniqueid(channel4), \ 189 "transfer_target_channel_name", ast_channel_name(channel3), \ 190 "transfer_target_channel_uniqueid", ast_channel_uniqueid(channel3)); \ 191 ast_test_validate(test, extra != NULL); \ 192 APPEND_EVENT(channel1, AST_CEL_ATTENDEDTRANSFER, NULL, extra); \ 196 #define ALICE_CALLERID { .id.name.str = "Alice", .id.name.valid = 1, .id.number.str = "100", .id.number.valid = 1, } 199 #define BOB_CALLERID { .id.name.str = "Bob", .id.name.valid = 1, .id.number.str = "200", .id.number.valid = 1, } 202 #define CHARLIE_CALLERID { .id.name.str = "Charlie", .id.name.valid = 1, .id.number.str = "300", .id.number.valid = 1, } 205 #define DAVID_CALLERID { .id.name.str = "David", .id.name.valid = 1, .id.number.str = "400", .id.number.valid = 1, } 208 #define SET_FORMATS(chan) do {\ 209 struct ast_format_cap *caps;\ 210 caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);\ 211 ast_format_cap_append(caps, ast_format_ulaw, 0);\ 212 ast_channel_nativeformats_set((chan), caps);\ 213 ast_channel_set_writeformat((chan), ast_format_ulaw);\ 214 ast_channel_set_rawwriteformat((chan), ast_format_ulaw);\ 215 ast_channel_set_readformat((chan), ast_format_ulaw);\ 216 ast_channel_set_rawreadformat((chan), ast_format_ulaw);\ 221 #define CREATE_ALICE_CHANNEL(channel_var, caller_id) do { \ 222 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "100", "100", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Alice"); \ 223 SET_FORMATS((channel_var));\ 224 APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \ 225 ast_channel_unlock((channel_var)); \ 229 #define CREATE_BOB_CHANNEL(channel_var, caller_id) do { \ 230 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "200", "200", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Bob"); \ 231 SET_FORMATS((channel_var));\ 232 APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \ 233 ast_channel_unlock((channel_var)); \ 237 #define CREATE_CHARLIE_CHANNEL(channel_var, caller_id) do { \ 238 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "300", "300", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Charlie"); \ 239 SET_FORMATS((channel_var));\ 240 APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \ 241 ast_channel_unlock((channel_var)); \ 245 #define CREATE_DAVID_CHANNEL(channel_var, caller_id) do { \ 246 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "400", "400", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/David"); \ 247 SET_FORMATS((channel_var));\ 248 APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \ 249 ast_channel_unlock((channel_var)); \ 253 #define EMULATE_APP_DATA(channel, priority, application, data) do { \ 254 if ((priority) > 0) { \ 255 ast_channel_priority_set((channel), (priority)); \ 257 ast_channel_appl_set((channel), (application)); \ 258 ast_channel_data_set((channel), (data)); \ 259 ast_channel_publish_snapshot((channel)); \ 262 #define ANSWER_CHANNEL(chan) do { \ 263 EMULATE_APP_DATA(chan, 1, "Answer", ""); \ 264 ANSWER_NO_APP(chan); \ 267 #define ANSWER_NO_APP(chan) do { \ 268 ast_setstate(chan, AST_STATE_UP); \ 269 APPEND_EVENT(chan, AST_CEL_ANSWER, NULL, NULL); \ 273 #define HANGUP_CHANNEL(channel, cause, dialstatus) do { \ 274 ast_channel_hangupcause_set((channel), (cause)); \ 275 ao2_ref(channel, +1); \ 276 ast_hangup((channel)); \ 277 HANGUP_EVENT(channel, cause, dialstatus); \ 278 APPEND_EVENT(channel, AST_CEL_CHANNEL_END, NULL, NULL); \ 279 ao2_cleanup(ast_channel_snapshot_get_latest(ast_channel_uniqueid(channel))); \ 280 ao2_cleanup(channel); \ 284 #define HANGUP_EVENT(channel, cause, dialstatus) do { \ 285 RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \ 286 extra = ast_json_pack("{s: i, s: s, s: s}", \ 287 "hangupcause", cause, \ 288 "hangupsource", "", \ 289 "dialstatus", dialstatus); \ 290 ast_test_validate(test, extra != NULL); \ 291 APPEND_EVENT(channel, AST_CEL_HANGUP, NULL, extra); \ 299 const char *userdefevname,
306 const char *userdefevname,
311 static int append_dummy_event(
void);
318 char *current_chan =
NULL;
337 if (!current_snapshot) {
341 ast_str_append(&peer_str, 0,
"%s,", current_snapshot->base->name);
400 info->name = __func__;
402 info->summary =
"Test the CEL records created when a channel is created";
404 "Test the CEL records created when a channel is created";
424 info->name = __func__;
426 info->summary =
"Test inbound unanswered calls";
428 "Test CEL records for a call that is\n" 429 "inbound to Asterisk, executes some dialplan, but\n" 430 "is never answered.";
452 .id.number.valid = 1, };
456 info->name = __func__;
458 info->summary =
"Test outbound unanswered calls";
460 "Test CEL records for a call that is\n" 461 "outbound to Asterisk but is never answered.";
485 info->name = __func__;
487 info->summary =
"Test CEL for a single party";
489 "Test CEL records for a call that is\n" 490 "answered, but only involves a single channel";
514 info->name = __func__;
516 info->summary =
"Test CEL for a single party entering/leaving a bridge";
518 "Test CEL records for a call that is\n" 519 "answered, enters a bridge, and leaves it.";
525 ast_test_validate(
test, bridge !=
NULL);
552 info->name = __func__;
554 info->summary =
"Test CEL for a single party entering/leaving a bridge";
556 "Test CEL records for a call that is\n" 557 "answered, enters a bridge, and leaves it.";
563 ast_test_validate(
test, bridge !=
NULL);
595 info->name = __func__;
597 info->summary =
"Test CEL for a single party entering/leaving a bridge";
599 "Test CEL records for a call that is\n" 600 "answered, enters a bridge, and leaves it. In this scenario, the\n" 601 "Party A should answer the bridge first.";
607 ast_test_validate(
test, bridge !=
NULL);
643 info->name = __func__;
645 info->summary =
"Test CEL for a single party entering/leaving a bridge";
647 "Test CEL records for a call that is\n" 648 "answered, enters a bridge, and leaves it. In this scenario, the\n" 649 "Party B should answer the bridge first.";
655 ast_test_validate(
test, bridge !=
NULL);
697 info->name = __func__;
699 info->summary =
"Test CEL for a single party entering/leaving a multi-party bridge";
701 "Test CEL records for a call that is\n" 702 "answered, enters a bridge, and leaves it. A total of three\n" 703 "parties perform this action.";
709 ast_test_validate(
test, bridge !=
NULL);
745 #define EMULATE_DIAL(channel, dialstring) do { \ 746 EMULATE_APP_DATA(channel, 1, "Dial", dialstring); \ 747 if (append_expected_event(channel, AST_CEL_APP_START, NULL, NULL, NULL)) { \ 748 return AST_TEST_FAIL; \ 752 #define START_DIALED(caller, callee) \ 753 START_DIALED_FULL(caller, callee, "200", "Bob") 755 #define START_DIALED_FULL(caller, callee, number, name) do { \ 756 callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, number, NULL, NULL, NULL, caller, 0, CHANNEL_TECH_NAME "/" name); \ 757 SET_FORMATS(callee);\ 758 ast_channel_unlock(callee); \ 759 if (append_expected_event(callee, AST_CEL_CHANNEL_START, NULL, NULL, NULL)) { \ 760 return AST_TEST_FAIL; \ 762 ast_set_flag(ast_channel_flags(callee), AST_FLAG_OUTGOING); \ 763 EMULATE_APP_DATA(callee, 0, "AppDial", "(Outgoing Line)"); \ 764 ast_channel_publish_dial(caller, callee, name, NULL); \ 775 info->name = __func__;
777 info->summary =
"Test CEL for a dial that isn't answered";
779 "Test CEL records for a channel that\n" 780 "performs a dial operation that isn't answered";
809 info->name = __func__;
811 info->summary =
"Test CEL for a dial that isn't answered";
813 "Test CEL records for a channel that\n" 814 "performs a dial operation that isn't answered";
844 info->name = __func__;
846 info->summary =
"Test CEL for a dial that results in a busy";
848 "Test CEL records for a channel that\n" 849 "performs a dial operation to an endpoint that's busy";
878 info->name = __func__;
880 info->summary =
"Test CEL for a dial that results in congestion";
882 "Test CEL records for a channel that\n" 883 "performs a dial operation to an endpoint that's congested";
912 info->name = __func__;
914 info->summary =
"Test CEL for a dial that results in unavailable";
916 "Test CEL records for a channel that\n" 917 "performs a dial operation to an endpoint that's unavailable";
946 info->name = __func__;
948 info->summary =
"Test CEL for a dial where the caller cancels";
950 "Test CEL records for a channel that\n" 951 "performs a dial operation to an endpoint but then decides\n" 952 "to hang up, cancelling the dial";
983 info->name = __func__;
985 info->summary =
"Test a parallel dial where all channels fail to answer";
987 "This tests dialing three parties: Bob, Charlie, David. Charlie\n" 988 "returns BUSY; David returns CONGESTION; Bob fails to answer and\n" 989 "Alice hangs up. Three records are created for Alice as a result.";
1034 info->name = __func__;
1036 info->summary =
"Test dialing, answering, and not going into a bridge.";
1038 "This is a weird one, but theoretically possible. You can perform\n" 1039 "a dial, then bounce both channels to different priorities and\n" 1040 "never have them enter a bridge together. Ew. This makes sure that\n" 1041 "when we answer, we get a CEL, it gets ended at that point, and\n" 1042 "that it gets finalized appropriately.";
1079 info->name = __func__;
1081 info->summary =
"Test dialing, answering, and going into a 2-party bridge";
1083 "The most 'basic' of scenarios";
1089 ast_test_validate(
test, bridge !=
NULL);
1126 info->name = __func__;
1128 info->summary =
"Test dialing, answering, and going into a 2-party bridge";
1130 "The most 'basic' of scenarios";
1136 ast_test_validate(
test, bridge !=
NULL);
1176 info->name = __func__;
1178 info->summary =
"Test dialing, answering, and going into a multi-party bridge";
1180 "A little tricky to get to do, but possible with some redirects.";
1186 ast_test_validate(
test, bridge !=
NULL);
1251 info->name = __func__;
1253 info->summary =
"Test blind transfers to an extension";
1255 "This test creates two channels, bridges them, and then" 1256 " blind transfers the bridge to an extension.";
1262 ast_test_validate(
test, bridge !=
NULL);
1275 "transfer_extension",
"transfer_context");
1276 if (!transfer_msg) {
1282 if (!transfer_msg->bridge) {
1321 info->name = __func__;
1323 info->summary =
"Test attended transfers between two pairs of bridged parties";
1325 "This test creates four channels, places each pair in" 1326 " a bridge, and then attended transfers the bridges" 1334 ast_test_validate(
test, bridge1 !=
NULL);
1346 ast_test_validate(
test, bridge2 !=
NULL);
1402 info->name = __func__;
1404 info->summary =
"Test attended transfers between two pairs of" 1405 " bridged parties that results in a bridge merge";
1407 "This test creates four channels, places each pair" 1408 " in a bridge, and then attended transfers the bridges" 1409 " together causing a bridge merge.";
1417 "test_cel",
"test_cel_atxfer_bridges_merge_1",
NULL);
1418 ast_test_validate(
test, bridge1 !=
NULL);
1431 "test_cel",
"test_cel_atxfer_bridges_merge_2",
NULL);
1432 ast_test_validate(
test, bridge2 !=
NULL);
1490 info->name = __func__;
1492 info->summary =
"Test attended transfers between two pairs of" 1493 " bridged parties that results in a bridge merge";
1495 "This test creates four channels, places each pair" 1496 " in a bridge, and then attended transfers the bridges" 1497 " together causing a bridge link.";
1507 "test_cel",
"test_cel_atxfer_bridges_link_1",
NULL);
1508 ast_test_validate(
test, bridge1 !=
NULL);
1523 "test_cel",
"test_cel_atxfer_bridges_link_2",
NULL);
1524 ast_test_validate(
test, bridge2 !=
NULL);
1571 info->name = __func__;
1573 info->summary =
"Test call pickup";
1575 "Test CEL records for a call that is\n" 1576 "inbound to Asterisk, executes some dialplan, and\n" 1599 ast_test_validate(
test, extra !=
NULL);
1631 info->name = __func__;
1633 info->summary =
"Test local channel optimization record generation";
1635 "Test CEL records for two local channels being optimized\n" 1636 "out by sending a messages indicating local optimization\n" 1644 ast_test_validate(
test, mc_blob !=
NULL);
1652 ast_test_validate(
test, alice_snapshot !=
NULL);
1657 ast_test_validate(
test, bob_snapshot !=
NULL);
1663 ast_test_validate(
test, local_opt_begin !=
NULL);
1666 ast_test_validate(
test, local_opt_end !=
NULL);
1671 extra =
ast_json_pack(
"{s: s, s: s}",
"local_two", bob_snapshot->base->name,
1672 "local_two_uniqueid", bob_snapshot->base->uniqueid);
1673 ast_test_validate(
test, extra !=
NULL);
1701 memcpy(event_dup, event, event_len);
1719 struct timespec end = {
1720 .tv_sec = start.tv_sec + 15,
1721 .tv_nsec = start.tv_usec * 1000
1737 ao2_link(cel_expected_events, ao2_ev);
1742 static int append_dummy_event(
void)
1759 const char *userdefevname,
1775 const char *userdefevname,
1793 const char *chan_name;
1806 ao2_link(cel_received_events, event_dup);
1811 if (expected <= received) {
1862 if (!intersection) {
1866 while ((chan =
strsep(&str1_dup,
","))) {
1870 while ((chan =
strsep(&str2_dup,
","))) {
1923 if (!str1 && !str2) {
1936 return !strcmp(str1, str2);
1984 const char *ie_type_name;
1990 switch (ie_pltype) {
2020 " did not match number of received events (%d).\n",
2030 while (rx_event && ex_event) {
2043 ?
" (wildcard match)" :
"");
2089 cel_expected_events =
NULL;
2090 cel_received_events =
NULL;
2093 ast_test_validate(test, !
check_events(test, local_expected, local_received));
2098 saved_config =
NULL;
2147 cel_expected_events =
NULL;
2149 cel_received_events =
NULL;
2151 cel_test_config =
NULL;
2160 if (!cel_test_config) {
2163 cel_test_config->
enable = 1;
static int append_expected_event_snapshot(struct ast_channel_snapshot *snapshot, enum ast_cel_event_type type, const char *userdefevname, struct ast_json *extra, const char *peer)
#define APPEND_EVENT_SNAPSHOT(snapshot, ev_type, userevent, extra, peer)
Contains all the initialization information required to store a new test definition.
#define ast_channel_lock(chan)
struct ao2_container * channels
Main Channel structure associated with a channel.
Local proxy channel special access.
static void mid_test_sync(void)
#define AST_MODULE_INFO_STANDARD(keystr, desc)
static int cel_verify_and_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
struct ast_channel_snapshot_base * base
Asterisk main include file. File version handling, generic pbx functions.
struct ast_blind_transfer_message * ast_blind_transfer_message_create(int is_external, struct ast_channel *transferer, const char *exten, const char *context)
Create a blind transfer message to be published.
static void do_sleep(void)
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
static struct ast_str * test_cel_generate_peer_str(struct ast_channel *chan, struct ast_bridge *bridge)
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
#define BRIDGE_ENTER_EVENT_PEER(channel, bridge, peer)
enum ast_event_type ast_event_get_type(const struct ast_event *event)
Get the type for an event.
ast_event_ie_pltype
Payload types for event information elements.
The arg parameter is a search key, but is not an object.
int ast_test_register_init(const char *category, ast_test_init_cb_t *cb)
Message published during a blind transfer.
Time-related functions and macros.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_party_name name
Subscriber name.
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
static int test_cel_peer_strings_match(const char *str1, const char *str2)
Check two peer strings for equality.
#define TEST_BACKEND_NAME
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
#define BRIDGE_EXIT_EVENT(channel, bridge)
#define ast_set_flag(p, flag)
static int load_module(void)
static int unload_module(void)
static int debug
Global debug status.
Structure that contains a snapshot of information about a bridge.
Channel Event channel name Used by: AST_EVENT_CEL Payload type: STR.
int do_mid_test_sync
Flag used to trigger a mid-test synchronization, access controlled by mid_test_sync_lock.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
A local channel optimization occurred.
Structure representing a snapshot of channel state.
Channel Event Time (micro-seconds) Used by: AST_EVENT_CEL Payload type: UINT.
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
Pickup a call target.
#define AST_TEST_REGISTER(cb)
char * str
Subscriber name (Malloced)
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
static struct ast_cel_general_config * cel_test_config
The CEL config used for CEL unit tests.
static struct ast_cel_general_config * saved_config
A placeholder for Asterisk's 'real' CEL configuration.
void ast_str_container_remove(struct ao2_container *str_container, const char *remove)
Removes a string from a string container allocated by ast_str_container_alloc.
const ast_string_field uniqueid
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cond_init(cond, attr)
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define ast_mutex_lock(a)
enum ast_event_ie_pltype ast_event_get_ie_pltype(enum ast_event_ie_type ie_type)
Get the payload type for a given information element type.
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
#define ast_strdup(str)
A wrapper for strdup()
supposed to be an opaque type
static struct ast_str * __test_cel_generate_peer_str(struct ast_channel_snapshot *chan, struct ast_bridge_snapshot *bridge)
static int events_are_equal(struct ast_test *test, struct ast_event *received, struct ast_event *expected)
#define ast_cond_signal(cond)
static struct timespec to_sleep
A 1 second sleep.
#define APPEND_EVENT(chan, ev_type, userevent, extra)
Channel Event Type Used by: AST_EVENT_CEL Payload type: UINT.
struct ast_channel_snapshot * ast_channel_snapshot_create(struct ast_channel *chan)
Generate a snapshot of the channel state. This is an ao2 object, so ao2_cleanup() to deallocate...
static int test_cel_init_cb(struct ast_test_info *info, struct ast_test *test)
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
pthread_cond_t ast_cond_t
Channel Event Time (seconds) Used by: AST_EVENT_CEL Payload type: UINT.
ast_mutex_t sync_lock
Lock used with sync_out for checking the end of test execution.
const char * ast_cel_get_type_name(enum ast_cel_event_type type)
Get the name of a CEL event type.
static struct ast_channel_tech test_cel_chan_tech
A channel technology used for the unit tests.
struct ast_json * ast_json_null(void)
Get the JSON null value.
struct ast_party_id id
Caller party ID.
void ast_cel_set_config(struct ast_cel_general_config *config)
Set the current CEL configuration.
ast_event_ie_type
Event Information Element types.
struct ast_bridge_snapshot * ast_bridge_get_snapshot(struct ast_bridge *bridge)
Returns the current snapshot for the bridge.
#define SCOPED_CHANNELLOCK(varname, chan)
scoped lock specialization for channels.
General Asterisk PBX channel definitions.
static struct ao2_container * cel_received_events
Asterisk JSON abstraction layer.
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_test_status_update(a, b, c...)
static void test_sub(struct ast_event *event)
void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
Add a ast_channel_snapshot to a ast_multi_channel_blob object.
Caller Party information.
ast_mutex_t mid_test_sync_lock
Lock used for synchronizing test execution stages with received events.
static int check_events(struct ast_test *test, struct ao2_container *local_expected, struct ao2_container *local_received)
#define ALICE_CALLERID
Alice's Caller ID.
A set of macros to manage forward-linked lists.
#define CREATE_ALICE_CHANNEL(channel_var, caller_id)
Create a test_cel_chan_tech for Alice.
hangup terminates connection
#define AST_CAUSE_NO_ANSWER
struct ast_bridge * ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Create a new base class bridge.
#define BRIDGE_ENTER(channel, bridge)
Structure to describe a channel "technology", ie a channel driver See for examples: ...
#define APPEND_DUMMY_EVENT()
int ast_test_register_cleanup(const char *category, ast_test_cleanup_cb_t *cb)
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
struct stasis_message_type * ast_local_optimization_end_type(void)
Message type for when a local channel optimization completes.
static int match_ie_val(const struct ast_event *event1, const struct ast_event *event2, enum ast_event_ie_type type)
Check an IE value from two events.
Structure that contains information about a bridge.
#define BRIDGE_EXIT(channel, bridge)
static struct ast_event * ao2_dup_event(const struct ast_event *event)
#define START_DIALED_FULL(caller, callee, number, name)
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
#define ATTENDEDTRANSFER_BRIDGE(channel1, bridge1, channel2, bridge2, channel3, channel4)
#define CHARLIE_CALLERID
Charlie's Caller ID.
#define CHANNEL_TECH_NAME
#define AST_TEST_UNREGISTER(cb)
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
#define ao2_iterator_next(iter)
#define ast_cond_destroy(cond)
struct ast_bridge_snapshot * ast_bridge_snapshot_create(struct ast_bridge *bridge)
Generate a snapshot of the bridge state. This is an ao2 object, so ao2_cleanup() to deallocate...
#define ao2_alloc(data_size, destructor_fn)
#define START_DIALED(caller, callee)
#define ANSWER_NO_APP(chan)
struct ao2_container * apps
#define ast_channel_unlock(chan)
static struct ast_str * test_cel_generate_peer_str_snapshot(struct ast_channel_snapshot *chan, struct ast_bridge *bridge)
#define BRIDGE_EXIT_EVENT_PEER(channel, bridge, peer)
#define ast_bridge_unlock(bridge)
Unlock the bridge.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
struct ast_cel_general_config * ast_cel_get_config(void)
Obtain the current CEL configuration.
void ast_bridge_publish_blind_transfer(struct ast_blind_transfer_message *transfer_message)
Publish a blind transfer event.
Channel Event Peer – for Things involving multiple channels, like BRIDGE Used by: AST_EVENT_CEL Payl...
#define ao2_find(container, arg, flags)
#define HANGUP_CHANNEL(channel, cause, dialstatus)
Hang up a test channel safely.
Basic bridge subclass API.
#define ast_clear_flag(p, flag)
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
#define ast_bridge_lock(bridge)
Lock the bridge.
ast_cond_t sync_out
Condition used for checking the end of test execution.
static int dump_event(struct ast_test *test, struct ast_event *event)
A structure to hold CEL global configuration options.
struct stasis_message_type * ast_local_optimization_begin_type(void)
Message type for when a local channel optimization begins.
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
int ast_event_iterator_init(struct ast_event_iterator *iterator, const struct ast_event *event)
Initialize an event iterator instance.
#define BOB_CALLERID
Bob's Caller ID.
char * strsep(char **str, const char *delims)
#define AST_CAUSE_NO_ROUTE_DESTINATION
int ast_event_iterator_next(struct ast_event_iterator *iterator)
Move iterator instance to next IE.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
void ast_channel_context_set(struct ast_channel *chan, const char *value)
uint32_t ast_event_iterator_get_ie_uint(struct ast_event_iterator *iterator)
Get the value of the current IE in the iterator as an integer payload.
void * ast_cel_general_config_alloc(void)
Allocate a CEL configuration object.
A ringing phone is answered.
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_state_set(struct ast_channel *chan, enum ast_channel_state)
A multi channel blob data structure for multi_channel_blob stasis messages.
const char * ast_event_get_ie_type_name(enum ast_event_ie_type ie_type)
Get the string representation of an information element type.
#define BLINDTRANSFER_EVENT(channel, bridge, extension, context)
Internal Asterisk hangup causes.
Abstract JSON element (object, array, string, int, ...).
#define CREATE_DAVID_CHANNEL(channel_var, caller_id)
Create a test_cel_chan_tech for David.
#define CREATE_BOB_CHANNEL(channel_var, caller_id)
Create a test_cel_chan_tech for Bob.
ast_cel_event_type
CEL event types.
AST_TEST_DEFINE(test_cel_channel_creation)
const char * ast_event_iterator_get_ie_str(struct ast_event_iterator *iterator)
Get the value of the current IE in the iterator as a string payload.
size_t ast_event_get_size(const struct ast_event *event)
Get the size of an event.
static void safe_channel_release(struct ast_channel *chan)
static int append_expected_event(struct ast_channel *chan, enum ast_cel_event_type type, const char *userdefevname, struct ast_json *extra, const char *peer)
#define EMULATE_DIAL(channel, dialstring)
#define ast_mutex_init(pmutex)
static struct ao2_container * cel_expected_events
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
#define ast_mutex_destroy(a)
struct ast_event * ast_cel_create_event(struct ast_channel_snapshot *snapshot, enum ast_cel_event_type event_type, const char *userdefevname, struct ast_json *extra, const char *peer_str)
Allocate and populate a CEL event structure.
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
static void safe_bridge_destroy(struct ast_bridge *bridge)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define EMULATE_APP_DATA(channel, priority, application, data)
Emulate a channel entering into an application.
#define ANSWER_CHANNEL(chan)
enum ast_event_ie_type ast_event_iterator_get_ie_type(struct ast_event_iterator *iterator)
Get the type of the current IE in the iterator instance.
a directed pickup was performed on this channel
#define CREATE_CHARLIE_CHANNEL(channel_var, caller_id)
Create a test_cel_chan_tech for Charlie.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ast_cond_timedwait(cond, mutex, time)
static int append_event(struct ast_event *ev)
#define AST_CAUSE_CONGESTION
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
struct ast_multi_channel_blob * ast_multi_channel_blob_create(struct ast_json *blob)
Create a ast_multi_channel_blob suitable for a stasis_message.
Structure for mutex and tracking information.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
#define ast_mutex_unlock(a)
#define ao2_link(container, obj)