2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2013, Digium, Inc.
6 * Matt Jordan <mjordan@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
21 * \brief CDR unit tests
23 * \author Matt Jordan <mjordan@digium.com>
28 <depend>TEST_FRAMEWORK</depend>
29 <support_level>core</support_level>
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37 #include "asterisk/module.h"
38 #include "asterisk/test.h"
39 #include "asterisk/cdr.h"
40 #include "asterisk/linkedlists.h"
41 #include "asterisk/chanvars.h"
42 #include "asterisk/utils.h"
43 #include "asterisk/causes.h"
44 #include "asterisk/time.h"
45 #include "asterisk/bridging.h"
46 #include "asterisk/bridging_basic.h"
47 #include "asterisk/stasis_channels.h"
48 #include "asterisk/stasis_bridging.h"
52 #define TEST_CATEGORY "/main/cdr/"
54 #define MOCK_CDR_BACKEND "mock_cdr_backend"
56 #define CHANNEL_TECH_NAME "CDRTestChannel"
58 /*! \brief A placeholder for Asterisk's 'real' CDR configuration */
59 static struct ast_cdr_config *saved_config;
61 /*! \brief A configuration suitable for 'normal' CDRs */
62 static struct ast_cdr_config debug_cdr_config = {
63 .settings.flags = CDR_ENABLED | CDR_DEBUG,
66 /*! \brief A configuration suitable for CDRs with unanswered records */
67 static struct ast_cdr_config unanswered_cdr_config = {
68 .settings.flags = CDR_ENABLED | CDR_UNANSWERED | CDR_DEBUG,
71 /*! \brief A configuration suitable for CDRs with congestion enabled */
72 static struct ast_cdr_config congestion_cdr_config = {
73 .settings.flags = CDR_ENABLED | CDR_UNANSWERED | CDR_DEBUG | CDR_CONGESTION,
76 /*! \brief Macro to swap a configuration out from the CDR engine. This should be
77 * used at the beginning of each test to set the needed configuration for that
80 #define SWAP_CONFIG(ao2_config, template) do { \
81 *(ao2_config) = (template); \
82 ast_cdr_set_config((ao2_config)); \
85 /*! \brief A linked list of received CDR entries from the engine */
86 static AST_LIST_HEAD(, test_cdr_entry) actual_cdr_entries = AST_LIST_HEAD_INIT_VALUE;
88 /*! \brief The Mock CDR backend condition wait */
89 static ast_cond_t mock_cdr_cond;
91 /*! \brief A channel technology used for the unit tests */
92 static struct ast_channel_tech test_cdr_chan_tech = {
93 .type = CHANNEL_TECH_NAME,
94 .description = "Mock channel technology for CDR tests",
97 struct test_cdr_entry {
99 AST_LIST_ENTRY(test_cdr_entry) list;
102 /*! \brief The number of CDRs the mock backend has received */
103 static int global_mock_cdr_count;
106 * \brief Callback function for the mock CDR backend
108 * This function 'processes' a dispatched CDR record by adding it to the
109 * \ref actual_cdr_entries list. When a test completes, it can verify the
110 * expected records against this list of actual CDRs created by the engine.
112 * \param cdr The public CDR object created by the engine
114 * \retval -1 on error
115 * \retval 0 on success
117 static int mock_cdr_backend_cb(struct ast_cdr *cdr)
119 struct ast_cdr *cdr_copy, *cdr_prev = NULL;
120 struct ast_cdr *mock_cdr = NULL;
121 struct test_cdr_entry *cdr_wrapper;
123 cdr_wrapper = ast_calloc(1, sizeof(*cdr_wrapper));
128 for (; cdr; cdr = cdr->next) {
129 struct ast_var_t *var_entry, *var_copy;
131 cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
136 cdr_copy->varshead.first = NULL;
137 cdr_copy->varshead.last = NULL;
138 cdr_copy->next = NULL;
140 AST_LIST_TRAVERSE(&cdr->varshead, var_entry, entries) {
141 var_copy = ast_var_assign(var_entry->name, var_entry->value);
145 AST_LIST_INSERT_TAIL(&cdr_copy->varshead, var_copy, entries);
152 cdr_prev->next = cdr_copy;
156 cdr_wrapper->cdr = mock_cdr;
158 AST_LIST_LOCK(&actual_cdr_entries);
159 AST_LIST_INSERT_TAIL(&actual_cdr_entries, cdr_wrapper, list);
160 global_mock_cdr_count++;
161 ast_cond_signal(&mock_cdr_cond);
162 AST_LIST_UNLOCK(&actual_cdr_entries);
168 * \brief Remove all entries from \ref actual_cdr_entries
170 static void clear_mock_cdr_backend(void)
172 struct test_cdr_entry *cdr_wrapper;
174 AST_LIST_LOCK(&actual_cdr_entries);
175 while ((cdr_wrapper = AST_LIST_REMOVE_HEAD(&actual_cdr_entries, list))) {
176 ast_cdr_free(cdr_wrapper->cdr);
177 ast_free(cdr_wrapper);
179 global_mock_cdr_count = 0;
180 AST_LIST_UNLOCK(&actual_cdr_entries);
183 /*! \brief Verify a string field. This will set the test status result to fail;
184 * as such, it assumes that (a) test is the test object variable, and (b) that
185 * a return variable res exists.
187 #define VERIFY_STRING_FIELD(field, actual, expected) do { \
188 if (strcmp((actual)->field, (expected)->field)) { \
189 ast_test_status_update(test, "Field %s failed: actual %s, expected %s\n", #field, (actual)->field, (expected)->field); \
190 ast_test_set_result(test, AST_TEST_FAIL); \
191 res = AST_TEST_FAIL; \
194 /*! \brief Verify a numeric field. This will set the test status result to fail;
195 * as such, it assumes that (a) test is the test object variable, and (b) that
196 * a return variable res exists.
198 #define VERIFY_NUMERIC_FIELD(field, actual, expected) do { \
199 if ((actual)->field != (expected)->field) { \
200 ast_test_status_update(test, "Field %s failed: actual %ld, expected %ld\n", #field, (long)(actual)->field, (long)(expected)->field); \
201 ast_test_set_result(test, AST_TEST_FAIL); \
202 res = AST_TEST_FAIL; \
205 /*! \brief Verify a time field. This will set the test status result to fail;
206 * as such, it assumes that (a) test is the test object variable, and (b) that
207 * a return variable res exists.
209 #define VERIFY_TIME_VALUE(field, actual) do { \
210 if (ast_tvzero((actual)->field)) { \
211 ast_test_status_update(test, "Field %s failed: should not be 0\n", #field); \
212 ast_test_set_result(test, AST_TEST_FAIL); \
213 res = AST_TEST_FAIL; \
216 /*! \brief Alice's Caller ID */
217 #define ALICE_CALLERID { .id.name.str = "Alice", .id.name.valid = 1, .id.number.str = "100", .id.number.valid = 1, }
219 /*! \brief Bob's Caller ID */
220 #define BOB_CALLERID { .id.name.str = "Bob", .id.name.valid = 1, .id.number.str = "200", .id.number.valid = 1, }
222 /*! \brief Charlie's Caller ID */
223 #define CHARLIE_CALLERID { .id.name.str = "Charlie", .id.name.valid = 1, .id.number.str = "300", .id.number.valid = 1, }
225 /*! \brief David's Caller ID */
226 #define DAVID_CALLERID { .id.name.str = "David", .id.name.valid = 1, .id.number.str = "400", .id.number.valid = 1, }
228 /*! \brief Copy the linkedid and uniqueid from a channel to an expected CDR */
229 #define COPY_IDS(channel_var, expected_record) do { \
230 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
231 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
234 /*! \brief Create a \ref test_cdr_chan_tech for Alice, and set the expected
235 * CDR records' linkedid and uniqueid. */
236 #define CREATE_ALICE_CHANNEL(channel_var, caller_id, expected_record) do { \
237 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, 0, CHANNEL_TECH_NAME "/Alice"); \
238 ast_channel_set_caller((channel_var), (caller_id), NULL); \
239 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
240 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
243 /*! \brief Create a \ref test_cdr_chan_tech for Bob, and set the expected
244 * CDR records' linkedid and uniqueid. */
245 #define CREATE_BOB_CHANNEL(channel_var, caller_id, expected_record) do { \
246 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, 0, CHANNEL_TECH_NAME "/Bob"); \
247 ast_channel_set_caller((channel_var), (caller_id), NULL); \
248 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
249 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
252 /*! \brief Create a \ref test_cdr_chan_tech for Charlie, and set the expected
253 * CDR records' linkedid and uniqueid. */
254 #define CREATE_CHARLIE_CHANNEL(channel_var, caller_id, expected_record) do { \
255 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, "300", "Charlie", "300", "300", "default", NULL, 0, CHANNEL_TECH_NAME "/Charlie"); \
256 ast_channel_set_caller((channel_var), (caller_id), NULL); \
257 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
258 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
261 /*! \brief Create a \ref test_cdr_chan_tech for Charlie, and set the expected
262 * CDR records' linkedid and uniqueid. */
263 #define CREATE_DAVID_CHANNEL(channel_var, caller_id, expected_record) do { \
264 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, "400", "David", "400", "400", "default", NULL, 0, CHANNEL_TECH_NAME "/David"); \
265 ast_channel_set_caller((channel_var), (caller_id), NULL); \
266 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
267 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
270 /*! \brief Emulate a channel entering into an application */
271 #define EMULATE_APP_DATA(channel, priority, application, data) do { \
272 if ((priority) > 0) { \
273 ast_channel_priority_set((channel), (priority)); \
275 ast_channel_appl_set((channel), (application)); \
276 ast_channel_data_set((channel), (data)); \
277 ast_channel_publish_snapshot((channel)); \
280 /*! \brief Hang up a test channel safely */
281 #define HANGUP_CHANNEL(channel, cause) do { \
282 ast_channel_hangupcause_set((channel), (cause)); \
283 if (!ast_hangup((channel))) { \
287 static enum ast_test_result_state verify_mock_cdr_record(struct ast_test *test, struct ast_cdr *expected, int record)
289 struct ast_cdr *actual = NULL;
290 struct test_cdr_entry *cdr_wrapper;
292 struct timeval wait_now = ast_tvnow();
293 struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 5, .tv_nsec = wait_now.tv_usec * 1000 };
294 enum ast_test_result_state res = AST_TEST_PASS;
296 while (count < record) {
297 AST_LIST_LOCK(&actual_cdr_entries);
298 if (global_mock_cdr_count < record) {
299 ast_cond_timedwait(&mock_cdr_cond, &actual_cdr_entries.lock, &wait_time);
301 cdr_wrapper = AST_LIST_REMOVE_HEAD(&actual_cdr_entries, list);
302 AST_LIST_UNLOCK(&actual_cdr_entries);
305 ast_test_status_update(test, "Unable to find actual CDR record at %d\n", count);
306 return AST_TEST_FAIL;
308 actual = cdr_wrapper->cdr;
310 if (!expected && actual) {
311 ast_test_status_update(test, "CDRs recorded where no record expected\n");
312 return AST_TEST_FAIL;
315 VERIFY_STRING_FIELD(accountcode, actual, expected);
316 VERIFY_NUMERIC_FIELD(amaflags, actual, expected);
317 VERIFY_STRING_FIELD(channel, actual, expected);
318 VERIFY_STRING_FIELD(clid, actual, expected);
319 VERIFY_STRING_FIELD(dcontext, actual, expected);
320 VERIFY_NUMERIC_FIELD(disposition, actual, expected);
321 VERIFY_STRING_FIELD(dst, actual, expected);
322 VERIFY_STRING_FIELD(dstchannel, actual, expected);
323 VERIFY_STRING_FIELD(lastapp, actual, expected);
324 VERIFY_STRING_FIELD(lastdata, actual, expected);
325 VERIFY_STRING_FIELD(linkedid, actual, expected);
326 VERIFY_STRING_FIELD(peeraccount, actual, expected);
327 VERIFY_STRING_FIELD(src, actual, expected);
328 VERIFY_STRING_FIELD(uniqueid, actual, expected);
329 VERIFY_STRING_FIELD(userfield, actual, expected);
330 VERIFY_TIME_VALUE(start, actual);
331 VERIFY_TIME_VALUE(end, actual);
332 /* Note: there's no way we can really calculate a duration or
333 * billsec - the unit tests are too short. However, if billsec is
334 * non-zero in the expected, then make sure we have an answer time
336 if (expected->billsec) {
337 VERIFY_TIME_VALUE(answer, actual);
339 ast_test_debug(test, "Finished expected record %s, %s\n",
340 expected->channel, S_OR(expected->dstchannel, "<none>"));
341 expected = expected->next;
347 static void safe_channel_release(struct ast_channel *chan)
352 ast_channel_release(chan);
355 AST_TEST_DEFINE(test_cdr_channel_creation)
357 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
358 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
361 struct ast_party_caller caller = ALICE_CALLERID;
362 struct ast_cdr expected = {
363 .clid = "\"Alice\" <100>",
366 .dcontext = "default",
367 .channel = CHANNEL_TECH_NAME "/Alice",
368 .amaflags = AST_AMA_DOCUMENTATION,
369 .disposition = AST_CDR_NOANSWER,
370 .accountcode = "100",
372 enum ast_test_result_state result = AST_TEST_NOT_RUN;
376 info->name = __func__;
377 info->category = TEST_CATEGORY;
378 info->summary = "Test that a CDR is created when a channel is created";
380 "Test that a CDR is created when a channel is created";
381 return AST_TEST_NOT_RUN;
386 SWAP_CONFIG(config, unanswered_cdr_config);
388 CREATE_ALICE_CHANNEL(chan, (&caller), &expected);
390 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
392 result = verify_mock_cdr_record(test, &expected, 1);
397 AST_TEST_DEFINE(test_cdr_unanswered_inbound_call)
399 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
400 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
403 struct ast_party_caller caller = ALICE_CALLERID;
404 struct ast_cdr expected = {
405 .clid = "\"Alice\" <100>",
408 .dcontext = "default",
409 .channel = CHANNEL_TECH_NAME "/Alice",
412 .amaflags = AST_AMA_DOCUMENTATION,
413 .disposition = AST_CDR_NOANSWER,
414 .accountcode = "100",
416 enum ast_test_result_state result = AST_TEST_NOT_RUN;
420 info->name = __func__;
421 info->category = TEST_CATEGORY;
422 info->summary = "Test inbound unanswered calls";
424 "Test the properties of a CDR for a call that is\n"
425 "inbound to Asterisk, executes some dialplan, but\n"
426 "is never answered.\n";
427 return AST_TEST_NOT_RUN;
432 SWAP_CONFIG(config, unanswered_cdr_config);
434 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
436 EMULATE_APP_DATA(chan, 1, "Wait", "1");
438 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
440 result = verify_mock_cdr_record(test, &expected, 1);
445 AST_TEST_DEFINE(test_cdr_unanswered_outbound_call)
447 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
448 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
451 struct ast_party_caller caller = {
455 .id.number.valid = 1, };
456 struct ast_cdr expected = {
459 .dcontext = "default",
460 .channel = CHANNEL_TECH_NAME "/Alice",
461 .lastapp = "AppDial",
462 .lastdata = "(Outgoing Line)",
463 .amaflags = AST_AMA_DOCUMENTATION,
464 .disposition = AST_CDR_NOANSWER,
465 .accountcode = "100",
467 enum ast_test_result_state result = AST_TEST_NOT_RUN;
471 info->name = __func__;
472 info->category = TEST_CATEGORY;
473 info->summary = "Test outbound unanswered calls";
475 "Test the properties of a CDR for a call that is\n"
476 "outbound to Asterisk but is never answered.\n";
477 return AST_TEST_NOT_RUN;
482 SWAP_CONFIG(config, unanswered_cdr_config);
484 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
486 ast_channel_exten_set(chan, "s");
487 ast_channel_context_set(chan, "default");
488 ast_set_flag(ast_channel_flags(chan), AST_FLAG_ORIGINATED);
489 EMULATE_APP_DATA(chan, 0, "AppDial", "(Outgoing Line)");
490 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
492 result = verify_mock_cdr_record(test, &expected, 1);
497 AST_TEST_DEFINE(test_cdr_outbound_bridged_call)
499 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
500 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
501 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
502 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
504 struct timespec to_sleep = {1, 0};
505 enum ast_test_result_state result = AST_TEST_NOT_RUN;
507 struct ast_party_caller caller = ALICE_CALLERID;
508 struct ast_cdr alice_expected = {
509 .clid = "\"Alice\" <100>",
512 .dcontext = "default",
513 .channel = CHANNEL_TECH_NAME "/Alice",
514 .dstchannel = CHANNEL_TECH_NAME "/Bob",
517 .amaflags = AST_AMA_DOCUMENTATION,
519 .disposition = AST_CDR_ANSWERED,
520 .accountcode = "100",
521 .peeraccount = "200",
523 struct ast_cdr bob_expected = {
527 .dcontext = "default",
528 .channel = CHANNEL_TECH_NAME "/Bob",
530 .lastapp = "AppDial",
531 .lastdata = "(Outgoing Line)",
532 .amaflags = AST_AMA_DOCUMENTATION,
534 .disposition = AST_CDR_ANSWERED,
535 .accountcode = "200",
537 .next = &alice_expected,
542 info->name = __func__;
543 info->category = TEST_CATEGORY;
544 info->summary = "Test dialing, answering, and going into a 2-party bridge";
546 "The most 'basic' of scenarios\n";
547 return AST_TEST_NOT_RUN;
552 SWAP_CONFIG(config, debug_cdr_config);
554 CREATE_ALICE_CHANNEL(chan_alice, &caller, &alice_expected);
555 ast_channel_state_set(chan_alice, AST_STATE_UP);
557 bridge = ast_bridge_basic_new();
558 ast_test_validate(test, bridge != NULL);
559 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
561 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
563 chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_alice), 0, CHANNEL_TECH_NAME "/Bob");
564 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_bob), sizeof(bob_expected.linkedid));
565 ast_copy_string(bob_expected.uniqueid, ast_channel_uniqueid(chan_bob), sizeof(bob_expected.uniqueid));
566 ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
567 ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_ORIGINATED);
568 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
570 ast_channel_publish_dial(NULL, chan_bob, "Bob", NULL);
571 ast_channel_state_set(chan_bob, AST_STATE_RINGING);
572 ast_channel_publish_dial(NULL, chan_bob, NULL, "ANSWER");
574 ast_channel_state_set(chan_bob, AST_STATE_UP);
576 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
578 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
580 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
582 ast_bridge_depart(chan_bob);
583 ast_bridge_depart(chan_alice);
585 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
586 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
588 result = verify_mock_cdr_record(test, &bob_expected, 2);
593 AST_TEST_DEFINE(test_cdr_single_party)
595 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
596 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
599 struct ast_party_caller caller = ALICE_CALLERID;
600 struct ast_cdr expected = {
601 .clid = "\"Alice\" <100>",
604 .dcontext = "default",
605 .channel = CHANNEL_TECH_NAME "/Alice",
607 .lastapp = "VoiceMailMain",
610 .amaflags = AST_AMA_DOCUMENTATION,
611 .disposition = AST_CDR_ANSWERED,
612 .accountcode = "100",
614 enum ast_test_result_state result = AST_TEST_NOT_RUN;
618 info->name = __func__;
619 info->category = TEST_CATEGORY;
620 info->summary = "Test cdrs for a single party";
622 "Test the properties of a CDR for a call that is\n"
623 "answered, but only involves a single channel\n";
624 return AST_TEST_NOT_RUN;
628 SWAP_CONFIG(config, debug_cdr_config);
629 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
631 EMULATE_APP_DATA(chan, 1, "Answer", "");
632 ast_setstate(chan, AST_STATE_UP);
633 EMULATE_APP_DATA(chan, 2, "VoiceMailMain", "1");
635 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
637 result = verify_mock_cdr_record(test, &expected, 1);
642 AST_TEST_DEFINE(test_cdr_single_bridge)
644 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
645 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
646 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
648 struct timespec to_sleep = {1, 0};
650 struct ast_party_caller caller = ALICE_CALLERID;
651 struct ast_cdr expected = {
652 .clid = "\"Alice\" <100>",
655 .dcontext = "default",
656 .channel = CHANNEL_TECH_NAME "/Alice",
659 .amaflags = AST_AMA_DOCUMENTATION,
660 .disposition = AST_CDR_ANSWERED,
661 .accountcode = "100",
663 enum ast_test_result_state result = AST_TEST_NOT_RUN;
667 info->name = __func__;
668 info->category = TEST_CATEGORY;
669 info->summary = "Test cdrs for a single party entering/leaving a bridge";
671 "Test the properties of a CDR for a call that is\n"
672 "answered, enters a bridge, and leaves it.\n";
673 return AST_TEST_NOT_RUN;
677 SWAP_CONFIG(config, debug_cdr_config);
678 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
680 EMULATE_APP_DATA(chan, 1, "Answer", "");
681 ast_setstate(chan, AST_STATE_UP);
682 EMULATE_APP_DATA(chan, 2, "Bridge", "");
684 bridge = ast_bridge_basic_new();
685 ast_test_validate(test, bridge != NULL);
687 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
688 ast_bridge_impart(bridge, chan, NULL, NULL, 0);
690 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
692 ast_bridge_depart(chan);
694 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
696 result = verify_mock_cdr_record(test, &expected, 1);
701 AST_TEST_DEFINE(test_cdr_single_bridge_continue)
703 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
704 RAII_VAR(struct ast_bridge *, bridge_one, NULL, ao2_cleanup);
705 RAII_VAR(struct ast_bridge *, bridge_two, NULL, ao2_cleanup);
706 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
708 struct timespec to_sleep = {1, 0};
710 struct ast_party_caller caller = ALICE_CALLERID;
711 struct ast_cdr expected_two = {
712 .clid = "\"Alice\" <100>",
715 .dcontext = "default",
716 .channel = CHANNEL_TECH_NAME "/Alice",
719 .amaflags = AST_AMA_DOCUMENTATION,
720 .disposition = AST_CDR_ANSWERED,
721 .accountcode = "100",
723 struct ast_cdr expected_one = {
724 .clid = "\"Alice\" <100>",
727 .dcontext = "default",
728 .channel = CHANNEL_TECH_NAME "/Alice",
731 .amaflags = AST_AMA_DOCUMENTATION,
732 .disposition = AST_CDR_ANSWERED,
733 .accountcode = "100",
734 .next = &expected_two,
737 enum ast_test_result_state result = AST_TEST_NOT_RUN;
741 info->name = __func__;
742 info->category = TEST_CATEGORY;
743 info->summary = "Test cdrs for a single party entering/leaving a bridge";
745 "Test the properties of a CDR for a call that is\n"
746 "answered, enters a bridge, and leaves it.\n";
747 return AST_TEST_NOT_RUN;
751 SWAP_CONFIG(config, debug_cdr_config);
752 CREATE_ALICE_CHANNEL(chan, &caller, &expected_one);
753 COPY_IDS(chan, &expected_two);
755 EMULATE_APP_DATA(chan, 1, "Answer", "");
756 ast_setstate(chan, AST_STATE_UP);
757 EMULATE_APP_DATA(chan, 2, "Bridge", "");
759 bridge_one = ast_bridge_basic_new();
760 ast_test_validate(test, bridge_one != NULL);
761 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
763 ast_bridge_impart(bridge_one, chan, NULL, NULL, 0);
765 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
767 ast_bridge_depart(chan);
769 EMULATE_APP_DATA(chan, 3, "Wait", "");
771 /* And then it hangs up */
772 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
774 result = verify_mock_cdr_record(test, &expected_one, 2);
779 AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_a)
781 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
782 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
783 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
784 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
786 struct timespec to_sleep = {1, 0};
788 struct ast_party_caller caller_alice = ALICE_CALLERID;
789 struct ast_party_caller caller_bob = BOB_CALLERID;
790 struct ast_cdr bob_expected = {
791 .clid = "\"Bob\" <200>",
794 .dcontext = "default",
795 .channel = CHANNEL_TECH_NAME "/Bob",
798 .amaflags = AST_AMA_DOCUMENTATION,
799 .disposition = AST_CDR_ANSWERED,
800 .accountcode = "200",
802 struct ast_cdr alice_expected = {
803 .clid = "\"Alice\" <100>",
806 .dcontext = "default",
807 .channel = CHANNEL_TECH_NAME "/Alice",
808 .dstchannel = CHANNEL_TECH_NAME "/Bob",
811 .amaflags = AST_AMA_DOCUMENTATION,
812 .disposition = AST_CDR_ANSWERED,
813 .accountcode = "100",
814 .peeraccount = "200",
815 .next = &bob_expected,
818 enum ast_test_result_state result = AST_TEST_NOT_RUN;
822 info->name = __func__;
823 info->category = TEST_CATEGORY;
824 info->summary = "Test cdrs for a single party entering/leaving a bridge";
826 "Test the properties of a CDR for a call that is\n"
827 "answered, enters a bridge, and leaves it. In this scenario, the\n"
828 "Party A should answer the bridge first.\n";
829 return AST_TEST_NOT_RUN;
833 SWAP_CONFIG(config, debug_cdr_config);
834 CREATE_ALICE_CHANNEL(chan_alice, &caller_alice, &alice_expected);
836 CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
837 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
839 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
840 ast_setstate(chan_alice, AST_STATE_UP);
841 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
843 bridge = ast_bridge_basic_new();
844 ast_test_validate(test, bridge != NULL);
846 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
847 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
849 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
850 ast_setstate(chan_bob, AST_STATE_UP);
851 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
853 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
854 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
856 ast_bridge_depart(chan_alice);
857 ast_bridge_depart(chan_bob);
859 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
860 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
862 result = verify_mock_cdr_record(test, &alice_expected, 2);
867 AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_b)
869 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
870 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
871 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
872 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
874 struct timespec to_sleep = {1, 0};
876 struct ast_party_caller caller_alice = ALICE_CALLERID;
877 struct ast_party_caller caller_bob = BOB_CALLERID;
878 struct ast_cdr bob_expected = {
879 .clid = "\"Bob\" <200>",
882 .dcontext = "default",
883 .channel = CHANNEL_TECH_NAME "/Bob",
886 .amaflags = AST_AMA_DOCUMENTATION,
887 .disposition = AST_CDR_ANSWERED,
888 .accountcode = "200",
890 struct ast_cdr alice_expected = {
891 .clid = "\"Alice\" <100>",
894 .dcontext = "default",
895 .channel = CHANNEL_TECH_NAME "/Alice",
896 .dstchannel = CHANNEL_TECH_NAME "/Bob",
899 .amaflags = AST_AMA_DOCUMENTATION,
900 .disposition = AST_CDR_ANSWERED,
901 .accountcode = "100",
902 .peeraccount = "200",
903 .next = &bob_expected,
906 enum ast_test_result_state result = AST_TEST_NOT_RUN;
910 info->name = __func__;
911 info->category = TEST_CATEGORY;
912 info->summary = "Test cdrs for a single party entering/leaving a bridge";
914 "Test the properties of a CDR for a call that is\n"
915 "answered, enters a bridge, and leaves it. In this scenario, the\n"
916 "Party B should answer the bridge first.\n";
917 return AST_TEST_NOT_RUN;
921 SWAP_CONFIG(config, debug_cdr_config);
922 CREATE_ALICE_CHANNEL(chan_alice, &caller_alice, &alice_expected);
924 CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
925 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
927 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
928 ast_setstate(chan_alice, AST_STATE_UP);
929 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
931 bridge = ast_bridge_basic_new();
932 ast_test_validate(test, bridge != NULL);
934 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
935 ast_setstate(chan_bob, AST_STATE_UP);
936 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
937 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
939 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
940 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
942 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
943 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
945 ast_bridge_depart(chan_alice);
946 ast_bridge_depart(chan_bob);
948 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
949 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
951 result = verify_mock_cdr_record(test, &alice_expected, 2);
956 AST_TEST_DEFINE(test_cdr_single_multiparty_bridge)
958 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
959 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
960 RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
961 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
962 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
964 struct timespec to_sleep = {1, 0};
966 struct ast_party_caller caller_alice = ALICE_CALLERID;
967 struct ast_party_caller caller_bob = BOB_CALLERID;
968 struct ast_party_caller caller_charlie = CHARLIE_CALLERID;
969 struct ast_cdr charlie_expected = {
970 .clid = "\"Charlie\" <300>",
973 .dcontext = "default",
974 .channel = CHANNEL_TECH_NAME "/Charlie",
977 .amaflags = AST_AMA_DOCUMENTATION,
978 .disposition = AST_CDR_ANSWERED,
979 .accountcode = "300",
981 struct ast_cdr bob_expected = {
982 .clid = "\"Bob\" <200>",
985 .dcontext = "default",
986 .channel = CHANNEL_TECH_NAME "/Bob",
987 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
990 .amaflags = AST_AMA_DOCUMENTATION,
991 .disposition = AST_CDR_ANSWERED,
992 .accountcode = "200",
993 .peeraccount = "300",
994 .next = &charlie_expected,
996 struct ast_cdr alice_expected_two = {
997 .clid = "\"Alice\" <100>",
1000 .dcontext = "default",
1001 .channel = CHANNEL_TECH_NAME "/Alice",
1002 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1003 .lastapp = "Bridge",
1005 .amaflags = AST_AMA_DOCUMENTATION,
1006 .disposition = AST_CDR_ANSWERED,
1007 .accountcode = "100",
1008 .peeraccount = "300",
1009 .next = &bob_expected,
1011 struct ast_cdr alice_expected_one = {
1012 .clid = "\"Alice\" <100>",
1015 .dcontext = "default",
1016 .channel = CHANNEL_TECH_NAME "/Alice",
1017 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1018 .lastapp = "Bridge",
1020 .amaflags = AST_AMA_DOCUMENTATION,
1021 .disposition = AST_CDR_ANSWERED,
1022 .accountcode = "100",
1023 .peeraccount = "200",
1024 .next = &alice_expected_two,
1027 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1031 info->name = __func__;
1032 info->category = TEST_CATEGORY;
1033 info->summary = "Test cdrs for a single party entering/leaving a multi-party bridge";
1035 "Test the properties of a CDR for a call that is\n"
1036 "answered, enters a bridge, and leaves it. A total of three\n"
1037 "parties perform this action.\n";
1038 return AST_TEST_NOT_RUN;
1042 SWAP_CONFIG(config, debug_cdr_config);
1043 CREATE_ALICE_CHANNEL(chan_alice, &caller_alice, &alice_expected_one);
1044 COPY_IDS(chan_alice, &alice_expected_two);
1045 CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
1046 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
1047 CREATE_CHARLIE_CHANNEL(chan_charlie, &caller_charlie, &charlie_expected);
1048 ast_copy_string(charlie_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected.linkedid));
1050 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
1051 ast_setstate(chan_alice, AST_STATE_UP);
1052 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
1054 bridge = ast_bridge_basic_new();
1055 ast_test_validate(test, bridge != NULL);
1056 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1058 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
1060 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
1061 ast_setstate(chan_bob, AST_STATE_UP);
1062 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
1063 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1065 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
1067 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1069 EMULATE_APP_DATA(chan_charlie, 1, "Answer", "");
1070 ast_setstate(chan_charlie, AST_STATE_UP);
1071 EMULATE_APP_DATA(chan_charlie, 2, "Bridge", "");
1072 ast_bridge_impart(bridge, chan_charlie, NULL, NULL, 0);
1074 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1076 ast_bridge_depart(chan_alice);
1077 ast_bridge_depart(chan_bob);
1078 ast_bridge_depart(chan_charlie);
1080 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
1081 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
1082 HANGUP_CHANNEL(chan_charlie, AST_CAUSE_NORMAL);
1084 result = verify_mock_cdr_record(test, &alice_expected_one, 4);
1089 AST_TEST_DEFINE(test_cdr_dial_unanswered)
1091 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1092 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1093 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1096 struct ast_party_caller caller = ALICE_CALLERID;
1097 struct ast_cdr expected = {
1098 .clid = "\"Alice\" <100>",
1101 .dcontext = "default",
1102 .channel = CHANNEL_TECH_NAME "/Alice",
1103 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1105 .lastdata = CHANNEL_TECH_NAME "/Bob",
1107 .amaflags = AST_AMA_DOCUMENTATION,
1108 .disposition = AST_CDR_NOANSWER,
1109 .accountcode = "100",
1110 .peeraccount = "200",
1112 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1116 info->name = __func__;
1117 info->category = TEST_CATEGORY;
1118 info->summary = "Test CDRs for a dial that isn't answered";
1120 "Test the properties of a CDR for a channel that\n"
1121 "performs a dial operation that isn't answered\n";
1122 return AST_TEST_NOT_RUN;
1127 SWAP_CONFIG(config, unanswered_cdr_config);
1129 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1131 EMULATE_APP_DATA(chan_caller, 1, "Dial", "CDRTestChannel/Bob");
1133 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1134 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1135 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1137 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1138 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1139 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "NOANSWER");
1141 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NO_ANSWER);
1142 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NO_ANSWER);
1144 result = verify_mock_cdr_record(test, &expected, 1);
1150 AST_TEST_DEFINE(test_cdr_dial_busy)
1152 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1153 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1154 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1157 struct ast_party_caller caller = ALICE_CALLERID;
1158 struct ast_cdr expected = {
1159 .clid = "\"Alice\" <100>",
1162 .dcontext = "default",
1163 .channel = CHANNEL_TECH_NAME "/Alice",
1164 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1166 .lastdata = CHANNEL_TECH_NAME "/Bob",
1168 .amaflags = AST_AMA_DOCUMENTATION,
1169 .disposition = AST_CDR_BUSY,
1170 .accountcode = "100",
1171 .peeraccount = "200",
1173 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1177 info->name = __func__;
1178 info->category = TEST_CATEGORY;
1179 info->summary = "Test CDRs for a dial that results in a busy";
1181 "Test the properties of a CDR for a channel that\n"
1182 "performs a dial operation to an endpoint that's busy\n";
1183 return AST_TEST_NOT_RUN;
1188 SWAP_CONFIG(config, unanswered_cdr_config);
1190 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1192 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1194 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1195 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1196 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1198 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1199 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1200 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "BUSY");
1202 HANGUP_CHANNEL(chan_caller, AST_CAUSE_BUSY);
1203 HANGUP_CHANNEL(chan_callee, AST_CAUSE_BUSY);
1205 result = verify_mock_cdr_record(test, &expected, 1);
1210 AST_TEST_DEFINE(test_cdr_dial_congestion)
1212 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1213 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1214 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1217 struct ast_party_caller caller = ALICE_CALLERID;
1218 struct ast_cdr expected = {
1219 .clid = "\"Alice\" <100>",
1222 .dcontext = "default",
1223 .channel = CHANNEL_TECH_NAME "/Alice",
1224 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1226 .lastdata = CHANNEL_TECH_NAME "/Bob",
1228 .amaflags = AST_AMA_DOCUMENTATION,
1229 .disposition = AST_CDR_CONGESTION,
1230 .accountcode = "100",
1231 .peeraccount = "200",
1233 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1237 info->name = __func__;
1238 info->category = TEST_CATEGORY;
1239 info->summary = "Test CDRs for a dial that results in congestion";
1241 "Test the properties of a CDR for a channel that\n"
1242 "performs a dial operation to an endpoint that's congested\n";
1243 return AST_TEST_NOT_RUN;
1248 SWAP_CONFIG(config, congestion_cdr_config);
1250 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1252 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1254 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1255 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1256 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1258 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1259 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1260 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "CONGESTION");
1262 HANGUP_CHANNEL(chan_caller, AST_CAUSE_CONGESTION);
1263 HANGUP_CHANNEL(chan_callee, AST_CAUSE_CONGESTION);
1265 result = verify_mock_cdr_record(test, &expected, 1);
1270 AST_TEST_DEFINE(test_cdr_dial_unavailable)
1272 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1273 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1274 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1277 struct ast_party_caller caller = ALICE_CALLERID;
1278 struct ast_cdr expected = {
1279 .clid = "\"Alice\" <100>",
1282 .dcontext = "default",
1283 .channel = CHANNEL_TECH_NAME "/Alice",
1284 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1286 .lastdata = CHANNEL_TECH_NAME "/Bob",
1288 .amaflags = AST_AMA_DOCUMENTATION,
1289 .disposition = AST_CDR_FAILED,
1290 .accountcode = "100",
1291 .peeraccount = "200",
1293 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1297 info->name = __func__;
1298 info->category = TEST_CATEGORY;
1299 info->summary = "Test CDRs for a dial that results in unavailable";
1301 "Test the properties of a CDR for a channel that\n"
1302 "performs a dial operation to an endpoint that's unavailable\n";
1303 return AST_TEST_NOT_RUN;
1308 SWAP_CONFIG(config, unanswered_cdr_config);
1310 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1312 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1314 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1315 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1316 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1318 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1319 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1320 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "CHANUNAVAIL");
1322 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NO_ROUTE_DESTINATION);
1323 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NO_ROUTE_DESTINATION);
1325 result = verify_mock_cdr_record(test, &expected, 1);
1330 AST_TEST_DEFINE(test_cdr_dial_caller_cancel)
1332 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1333 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1334 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1337 struct ast_party_caller caller = ALICE_CALLERID;
1338 struct ast_cdr expected = {
1339 .clid = "\"Alice\" <100>",
1342 .dcontext = "default",
1343 .channel = CHANNEL_TECH_NAME "/Alice",
1344 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1346 .lastdata = CHANNEL_TECH_NAME "/Bob",
1348 .amaflags = AST_AMA_DOCUMENTATION,
1349 .disposition = AST_CDR_NOANSWER,
1350 .accountcode = "100",
1351 .peeraccount = "200",
1353 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1357 info->name = __func__;
1358 info->category = TEST_CATEGORY;
1359 info->summary = "Test CDRs for a dial where the caller cancels";
1361 "Test the properties of a CDR for a channel that\n"
1362 "performs a dial operation to an endpoint but then decides\n"
1363 "to hang up, cancelling the dial\n";
1364 return AST_TEST_NOT_RUN;
1369 SWAP_CONFIG(config, unanswered_cdr_config);
1371 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1373 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1375 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1376 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1377 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1379 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1380 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1381 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "CANCEL");
1383 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1384 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1386 result = verify_mock_cdr_record(test, &expected, 1);
1391 AST_TEST_DEFINE(test_cdr_dial_parallel_failed)
1393 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1394 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
1395 RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
1396 RAII_VAR(struct ast_channel *, chan_david, NULL, safe_channel_release);
1397 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1400 struct ast_party_caller caller = ALICE_CALLERID;
1401 struct ast_cdr bob_expected = {
1402 .clid = "\"Alice\" <100>",
1405 .dcontext = "default",
1406 .channel = CHANNEL_TECH_NAME "/Alice",
1407 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1409 .lastdata = CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David",
1411 .amaflags = AST_AMA_DOCUMENTATION,
1412 .disposition = AST_CDR_NOANSWER,
1413 .accountcode = "100",
1414 .peeraccount = "200",
1416 struct ast_cdr charlie_expected = {
1417 .clid = "\"Alice\" <100>",
1420 .dcontext = "default",
1421 .channel = CHANNEL_TECH_NAME "/Alice",
1422 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1424 .lastdata = CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David",
1426 .amaflags = AST_AMA_DOCUMENTATION,
1427 .disposition = AST_CDR_BUSY,
1428 .accountcode = "100",
1429 .peeraccount = "300",
1431 struct ast_cdr david_expected = {
1432 .clid = "\"Alice\" <100>",
1435 .dcontext = "default",
1436 .channel = CHANNEL_TECH_NAME "/Alice",
1437 .dstchannel = CHANNEL_TECH_NAME "/David",
1439 .lastdata = CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David",
1441 .amaflags = AST_AMA_DOCUMENTATION,
1442 .disposition = AST_CDR_CONGESTION,
1443 .accountcode = "100",
1444 .peeraccount = "400",
1446 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1448 struct ast_cdr *expected = &bob_expected;
1449 bob_expected.next = &charlie_expected;
1450 charlie_expected.next = &david_expected;
1454 info->name = __func__;
1455 info->category = TEST_CATEGORY;
1456 info->summary = "Test a parallel dial where all channels fail to answer";
1458 "This tests dialing three parties: Bob, Charlie, David. Charlie\n"
1459 "returns BUSY; David returns CONGESTION; Bob fails to answer and\n"
1460 "Alice hangs up. Three records are created for Alice as a result.\n";
1461 return AST_TEST_NOT_RUN;
1466 SWAP_CONFIG(config, congestion_cdr_config);
1468 CREATE_ALICE_CHANNEL(chan_caller, &caller, &bob_expected);
1469 COPY_IDS(chan_caller, &charlie_expected);
1470 COPY_IDS(chan_caller, &david_expected);
1472 /* Channel enters Dial app */
1473 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David");
1475 /* Outbound channels are created */
1476 chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1477 ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
1478 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
1480 chan_charlie = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "300", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Charlie");
1481 ast_set_flag(ast_channel_flags(chan_charlie), AST_FLAG_OUTGOING);
1482 EMULATE_APP_DATA(chan_charlie, 0, "AppDial", "(Outgoing Line)");
1484 chan_david = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "400", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/David");
1485 ast_set_flag(ast_channel_flags(chan_david), AST_FLAG_OUTGOING);
1486 EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");
1489 ast_channel_publish_dial(chan_caller, chan_bob, "Bob", NULL);
1490 ast_channel_publish_dial(chan_caller, chan_charlie, "Charlie", NULL);
1491 ast_channel_publish_dial(chan_caller, chan_david, "David", NULL);
1492 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1494 /* Charlie is busy */
1495 ast_channel_publish_dial(chan_caller, chan_charlie, NULL, "BUSY");
1496 HANGUP_CHANNEL(chan_charlie, AST_CAUSE_BUSY);
1498 /* David is congested */
1499 ast_channel_publish_dial(chan_caller, chan_david, NULL, "CONGESTION");
1500 HANGUP_CHANNEL(chan_david, AST_CAUSE_CONGESTION);
1502 /* Bob is canceled */
1503 ast_channel_publish_dial(chan_caller, chan_bob, NULL, "CANCEL");
1504 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
1506 /* Alice hangs up */
1507 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1509 result = verify_mock_cdr_record(test, expected, 3);
1514 AST_TEST_DEFINE(test_cdr_dial_answer_no_bridge)
1516 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1517 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1518 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1521 struct ast_party_caller caller = ALICE_CALLERID;
1522 struct ast_cdr bob_expected_one = {
1526 .dcontext = "default",
1527 .channel = CHANNEL_TECH_NAME "/Bob",
1530 .amaflags = AST_AMA_DOCUMENTATION,
1531 .disposition = AST_CDR_ANSWERED,
1532 .accountcode = "200",
1534 struct ast_cdr alice_expected_two = {
1535 .clid = "\"Alice\" <100>",
1538 .dcontext = "default",
1539 .channel = CHANNEL_TECH_NAME "/Alice",
1542 .amaflags = AST_AMA_DOCUMENTATION,
1543 .disposition = AST_CDR_ANSWERED,
1544 .accountcode = "100",
1545 .next = &bob_expected_one,
1547 struct ast_cdr alice_expected_one = {
1548 .clid = "\"Alice\" <100>",
1551 .dcontext = "default",
1552 .channel = CHANNEL_TECH_NAME "/Alice",
1553 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1555 .lastdata = CHANNEL_TECH_NAME "/Bob",
1556 .amaflags = AST_AMA_DOCUMENTATION,
1557 .disposition = AST_CDR_ANSWERED,
1558 .accountcode = "100",
1559 .peeraccount = "200",
1560 .next = &alice_expected_two,
1562 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1566 info->name = __func__;
1567 info->category = TEST_CATEGORY;
1568 info->summary = "Test dialing, answering, and not going into a bridge.";
1570 "This is a weird one, but theoretically possible. You can perform\n"
1571 "a dial, then bounce both channels to different priorities and\n"
1572 "never have them enter a bridge together. Ew. This makes sure that\n"
1573 "when we answer, we get a CDR, it gets ended at that point, and\n"
1574 "that it gets finalized appropriately. We should get three CDRs in\n"
1575 "the end - one for the dial, and one for each CDR as they continued\n"
1577 return AST_TEST_NOT_RUN;
1582 SWAP_CONFIG(config, debug_cdr_config);
1584 CREATE_ALICE_CHANNEL(chan_caller, &caller, &alice_expected_one);
1585 COPY_IDS(chan_caller, &alice_expected_two);
1587 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1589 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1590 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1591 COPY_IDS(chan_callee, &bob_expected_one);
1593 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1594 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1595 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "ANSWER");
1597 ast_channel_state_set(chan_caller, AST_STATE_UP);
1598 ast_clear_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1599 ast_channel_state_set(chan_callee, AST_STATE_UP);
1601 EMULATE_APP_DATA(chan_caller, 2, "Wait", "1");
1602 EMULATE_APP_DATA(chan_callee, 1, "Wait", "1");
1604 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1605 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1607 result = verify_mock_cdr_record(test, &alice_expected_one, 3);
1611 AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_a)
1613 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1614 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1615 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1616 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1618 struct timespec to_sleep = {1, 0};
1619 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1621 struct ast_party_caller caller = ALICE_CALLERID;
1622 struct ast_cdr expected = {
1623 .clid = "\"Alice\" <100>",
1626 .dcontext = "default",
1627 .channel = CHANNEL_TECH_NAME "/Alice",
1628 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1630 .lastdata = CHANNEL_TECH_NAME "/Bob",
1631 .amaflags = AST_AMA_DOCUMENTATION,
1633 .disposition = AST_CDR_ANSWERED,
1634 .accountcode = "100",
1635 .peeraccount = "200",
1640 info->name = __func__;
1641 info->category = TEST_CATEGORY;
1642 info->summary = "Test dialing, answering, and going into a 2-party bridge";
1644 "The most 'basic' of scenarios\n";
1645 return AST_TEST_NOT_RUN;
1650 SWAP_CONFIG(config, debug_cdr_config);
1652 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1654 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1656 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1657 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1658 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1660 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1661 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1662 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "ANSWER");
1664 ast_channel_state_set(chan_caller, AST_STATE_UP);
1665 ast_channel_state_set(chan_callee, AST_STATE_UP);
1667 bridge = ast_bridge_basic_new();
1668 ast_test_validate(test, bridge != NULL);
1669 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1671 ast_bridge_impart(bridge, chan_caller, NULL, NULL, 0);
1672 ast_bridge_impart(bridge, chan_callee, NULL, NULL, 0);
1674 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1676 ast_bridge_depart(chan_caller);
1677 ast_bridge_depart(chan_callee);
1679 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1680 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1682 result = verify_mock_cdr_record(test, &expected, 1);
1686 AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_b)
1688 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1689 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1690 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1691 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1693 struct timespec to_sleep = {1, 0};
1694 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1696 struct ast_party_caller caller = ALICE_CALLERID;
1697 struct ast_cdr expected = {
1698 .clid = "\"Alice\" <100>",
1701 .dcontext = "default",
1702 .channel = CHANNEL_TECH_NAME "/Alice",
1703 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1705 .lastdata = CHANNEL_TECH_NAME "/Bob",
1706 .amaflags = AST_AMA_DOCUMENTATION,
1708 .disposition = AST_CDR_ANSWERED,
1709 .accountcode = "100",
1710 .peeraccount = "200",
1715 info->name = __func__;
1716 info->category = TEST_CATEGORY;
1717 info->summary = "Test dialing, answering, and going into a 2-party bridge";
1719 "The most 'basic' of scenarios\n";
1720 return AST_TEST_NOT_RUN;
1725 SWAP_CONFIG(config, debug_cdr_config);
1727 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1729 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1731 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1732 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1733 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1735 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1736 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1737 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "ANSWER");
1739 ast_channel_state_set(chan_caller, AST_STATE_UP);
1740 ast_channel_state_set(chan_callee, AST_STATE_UP);
1742 bridge = ast_bridge_basic_new();
1743 ast_test_validate(test, bridge != NULL);
1744 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1745 ast_bridge_impart(bridge, chan_callee, NULL, NULL, 0);
1746 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1747 ast_bridge_impart(bridge, chan_caller, NULL, NULL, 0);
1748 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1749 ast_bridge_depart(chan_caller);
1750 ast_bridge_depart(chan_callee);
1752 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1753 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1755 result = verify_mock_cdr_record(test, &expected, 1);
1759 AST_TEST_DEFINE(test_cdr_dial_answer_multiparty)
1761 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
1762 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
1763 RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
1764 RAII_VAR(struct ast_channel *, chan_david, NULL, safe_channel_release);
1765 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1766 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1768 struct timespec to_sleep = {1, 0};
1769 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1771 struct ast_party_caller alice_caller = ALICE_CALLERID;
1772 struct ast_party_caller charlie_caller = CHARLIE_CALLERID;
1773 struct ast_cdr charlie_expected_two = {
1774 .clid = "\"Charlie\" <300>",
1777 .dcontext = "default",
1778 .channel = CHANNEL_TECH_NAME "/Charlie",
1779 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1781 .lastdata = CHANNEL_TECH_NAME "/David",
1782 .amaflags = AST_AMA_DOCUMENTATION,
1784 .disposition = AST_CDR_ANSWERED,
1785 .accountcode = "300",
1786 .peeraccount = "200",
1788 struct ast_cdr charlie_expected_one = {
1789 .clid = "\"Charlie\" <300>",
1792 .dcontext = "default",
1793 .channel = CHANNEL_TECH_NAME "/Charlie",
1794 .dstchannel = CHANNEL_TECH_NAME "/David",
1796 .lastdata = CHANNEL_TECH_NAME "/David",
1797 .amaflags = AST_AMA_DOCUMENTATION,
1799 .disposition = AST_CDR_ANSWERED,
1800 .accountcode = "300",
1801 .peeraccount = "400",
1802 .next = &charlie_expected_two,
1804 struct ast_cdr alice_expected_three = {
1805 .clid = "\"Alice\" <100>",
1808 .dcontext = "default",
1809 .channel = CHANNEL_TECH_NAME "/Alice",
1810 .dstchannel = CHANNEL_TECH_NAME "/David",
1812 .lastdata = CHANNEL_TECH_NAME "/Bob",
1813 .amaflags = AST_AMA_DOCUMENTATION,
1815 .disposition = AST_CDR_ANSWERED,
1816 .accountcode = "100",
1817 .peeraccount = "400",
1818 .next = &charlie_expected_one,
1820 struct ast_cdr alice_expected_two = {
1821 .clid = "\"Alice\" <100>",
1824 .dcontext = "default",
1825 .channel = CHANNEL_TECH_NAME "/Alice",
1826 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1828 .lastdata = CHANNEL_TECH_NAME "/Bob",
1829 .amaflags = AST_AMA_DOCUMENTATION,
1831 .disposition = AST_CDR_ANSWERED,
1832 .accountcode = "100",
1833 .peeraccount = "300",
1834 .next = &alice_expected_three,
1836 struct ast_cdr alice_expected_one = {
1837 .clid = "\"Alice\" <100>",
1840 .dcontext = "default",
1841 .channel = CHANNEL_TECH_NAME "/Alice",
1842 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1844 .lastdata = CHANNEL_TECH_NAME "/Bob",
1845 .amaflags = AST_AMA_DOCUMENTATION,
1847 .disposition = AST_CDR_ANSWERED,
1848 .accountcode = "100",
1849 .peeraccount = "200",
1850 .next = &alice_expected_two,
1855 info->name = __func__;
1856 info->category = TEST_CATEGORY;
1857 info->summary = "Test dialing, answering, and going into a multi-party bridge";
1859 "A little tricky to get to do, but possible with some redirects.\n";
1860 return AST_TEST_NOT_RUN;
1865 SWAP_CONFIG(config, debug_cdr_config);
1867 CREATE_ALICE_CHANNEL(chan_alice, &alice_caller, &alice_expected_one);
1868 COPY_IDS(chan_alice, &alice_expected_two);
1869 COPY_IDS(chan_alice, &alice_expected_three);
1871 EMULATE_APP_DATA(chan_alice, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1873 chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, 0, CHANNEL_TECH_NAME "/Bob");
1874 ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
1875 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
1877 CREATE_CHARLIE_CHANNEL(chan_charlie, &charlie_caller, &charlie_expected_one);
1878 EMULATE_APP_DATA(chan_charlie, 1, "Dial", CHANNEL_TECH_NAME "/David");
1879 ast_copy_string(charlie_expected_one.uniqueid, ast_channel_uniqueid(chan_charlie), sizeof(charlie_expected_one.uniqueid));
1880 ast_copy_string(charlie_expected_one.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected_one.linkedid));
1881 ast_copy_string(charlie_expected_two.uniqueid, ast_channel_uniqueid(chan_charlie), sizeof(charlie_expected_two.uniqueid));
1882 ast_copy_string(charlie_expected_two.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected_two.linkedid));
1884 chan_david = ast_channel_alloc(0, AST_STATE_DOWN, "400", "David", "400", "400", "default", NULL, 0, CHANNEL_TECH_NAME "/David");
1885 ast_set_flag(ast_channel_flags(chan_david), AST_FLAG_OUTGOING);
1886 EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");
1888 ast_channel_publish_dial(chan_alice, chan_bob, "Bob", NULL);
1889 ast_channel_state_set(chan_alice, AST_STATE_RINGING);
1890 ast_channel_publish_dial(chan_charlie, chan_david, "David", NULL);
1891 ast_channel_state_set(chan_charlie, AST_STATE_RINGING);
1892 ast_channel_publish_dial(chan_alice, chan_bob, NULL, "ANSWER");
1893 ast_channel_publish_dial(chan_charlie, chan_david, NULL, "ANSWER");
1895 ast_channel_state_set(chan_alice, AST_STATE_UP);
1896 ast_channel_state_set(chan_bob, AST_STATE_UP);
1897 ast_channel_state_set(chan_charlie, AST_STATE_UP);
1898 ast_channel_state_set(chan_david, AST_STATE_UP);
1900 bridge = ast_bridge_basic_new();
1901 ast_test_validate(test, bridge != NULL);
1903 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1904 ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_charlie, NULL, NULL, 0));
1905 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1906 ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_david, NULL, NULL, 0));
1907 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1908 ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0));
1909 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1910 ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0));
1911 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1912 ast_test_validate(test, 0 == ast_bridge_depart(chan_alice));
1913 ast_test_validate(test, 0 == ast_bridge_depart(chan_bob));
1914 ast_test_validate(test, 0 == ast_bridge_depart(chan_charlie));
1915 ast_test_validate(test, 0 == ast_bridge_depart(chan_david));
1917 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
1918 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
1919 HANGUP_CHANNEL(chan_charlie, AST_CAUSE_NORMAL);
1920 HANGUP_CHANNEL(chan_david, AST_CAUSE_NORMAL);
1922 result = verify_mock_cdr_record(test, &alice_expected_one, 5);
1927 AST_TEST_DEFINE(test_cdr_park)
1929 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
1930 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
1931 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1932 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1934 struct timespec to_sleep = {1, 0};
1936 struct ast_party_caller bob_caller = BOB_CALLERID;
1937 struct ast_party_caller alice_caller = ALICE_CALLERID;
1938 struct ast_cdr bob_expected = {
1939 .clid = "\"Bob\" <200>",
1942 .dcontext = "default",
1943 .channel = CHANNEL_TECH_NAME "/Bob",
1947 .amaflags = AST_AMA_DOCUMENTATION,
1948 .disposition = AST_CDR_ANSWERED,
1949 .accountcode = "200",
1951 struct ast_cdr alice_expected = {
1952 .clid = "\"Alice\" <100>",
1955 .dcontext = "default",
1956 .channel = CHANNEL_TECH_NAME "/Alice",
1960 .amaflags = AST_AMA_DOCUMENTATION,
1961 .disposition = AST_CDR_ANSWERED,
1962 .accountcode = "100",
1963 .next = &bob_expected,
1965 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1969 info->name = __func__;
1970 info->category = TEST_CATEGORY;
1971 info->summary = "Test cdrs for a single party entering Park";
1973 "Test the properties of a CDR for calls that are\n"
1974 "answered, enters Park, and leaves it.\n";
1975 return AST_TEST_NOT_RUN;
1979 SWAP_CONFIG(config, debug_cdr_config);
1980 CREATE_ALICE_CHANNEL(chan_alice, &alice_caller, &alice_expected);
1981 CREATE_BOB_CHANNEL(chan_bob, &bob_caller, &bob_expected);
1983 EMULATE_APP_DATA(chan_alice, 1, "Park", "700");
1984 ast_setstate(chan_alice, AST_STATE_UP);
1985 EMULATE_APP_DATA(chan_bob, 1, "Park", "701");
1986 ast_setstate(chan_bob, AST_STATE_UP);
1988 bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING,
1989 AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
1990 | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
1991 ast_test_validate(test, bridge != NULL);
1993 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1994 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
1995 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1996 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
1997 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1998 ast_bridge_depart(chan_alice);
1999 ast_bridge_depart(chan_bob);
2001 /* And then it hangs up */
2002 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
2003 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
2005 result = verify_mock_cdr_record(test, &alice_expected, 2);
2011 AST_TEST_DEFINE(test_cdr_fields)
2013 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
2014 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
2016 char varbuffer[128];
2019 struct timespec to_sleep = {2, 0};
2020 struct ast_flags fork_options = { 0, };
2022 struct ast_party_caller caller = ALICE_CALLERID;
2023 struct ast_cdr original = {
2024 .clid = "\"Alice\" <100>",
2027 .dcontext = "default",
2028 .channel = CHANNEL_TECH_NAME "/Alice",
2032 .amaflags = AST_AMA_OMIT,
2033 .disposition = AST_CDR_FAILED,
2034 .accountcode = "XXX",
2035 .userfield = "yackity",
2037 struct ast_cdr fork_expected_one = {
2038 .clid = "\"Alice\" <100>",
2041 .dcontext = "default",
2042 .channel = CHANNEL_TECH_NAME "/Alice",
2046 .amaflags = AST_AMA_OMIT,
2047 .disposition = AST_CDR_FAILED,
2048 .accountcode = "XXX",
2049 .userfield = "yackity",
2051 struct ast_cdr fork_expected_two = {
2052 .clid = "\"Alice\" <100>",
2055 .dcontext = "default",
2056 .channel = CHANNEL_TECH_NAME "/Alice",
2057 .lastapp = "Answer",
2059 .amaflags = AST_AMA_OMIT,
2060 .disposition = AST_CDR_ANSWERED,
2061 .accountcode = "ZZZ",
2062 .userfield = "schmackity",
2064 enum ast_test_result_state result = AST_TEST_NOT_RUN;
2066 struct ast_cdr *expected = &original;
2067 original.next = &fork_expected_one;
2068 fork_expected_one.next = &fork_expected_two;
2072 info->name = __func__;
2073 info->category = TEST_CATEGORY;
2074 info->summary = "Test field access CDRs";
2076 "This tests setting/retrieving data on CDR records.\n";
2077 return AST_TEST_NOT_RUN;
2082 SWAP_CONFIG(config, unanswered_cdr_config);
2084 CREATE_ALICE_CHANNEL(chan, &caller, &original);
2085 ast_copy_string(fork_expected_one.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_one.uniqueid));
2086 ast_copy_string(fork_expected_one.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_one.linkedid));
2087 ast_copy_string(fork_expected_two.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_two.uniqueid));
2088 ast_copy_string(fork_expected_two.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_two.linkedid));
2090 /* Channel enters Wait app */
2091 ast_channel_appl_set(chan, "Wait");
2092 ast_channel_data_set(chan, "10");
2093 ast_channel_priority_set(chan, 1);
2094 ast_channel_publish_snapshot(chan);
2096 /* Set properties on the channel that propagate to the CDR */
2097 ast_channel_amaflags_set(chan, AST_AMA_OMIT);
2098 ast_channel_accountcode_set(chan, "XXX");
2100 /* Wait one second so we get a duration. */
2101 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
2103 ast_cdr_setuserfield(ast_channel_name(chan), "foobar");
2104 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_1") == 0);
2106 /* Verify that we can't set read-only fields or other fields directly */
2107 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "clid", "junk") != 0);
2108 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "src", "junk") != 0);
2109 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "dst", "junk") != 0);
2110 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "dcontext", "junk") != 0);
2111 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "channel", "junk") != 0);
2112 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "dstchannel", "junk") != 0);
2113 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "lastapp", "junk") != 0);
2114 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "lastdata", "junk") != 0);
2115 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "start", "junk") != 0);
2116 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "answer", "junk") != 0);
2117 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "end", "junk") != 0);
2118 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "duration", "junk") != 0);
2119 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "billsec", "junk") != 0);
2120 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "disposition", "junk") != 0);
2121 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "amaflags", "junk") != 0);
2122 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "accountcode", "junk") != 0);
2123 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "uniqueid", "junk") != 0);
2124 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "linkedid", "junk") != 0);
2125 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "userfield", "junk") != 0);
2126 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "sequence", "junk") != 0);
2128 /* Verify the values */
2129 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "userfield", varbuffer, sizeof(varbuffer)) == 0);
2130 ast_test_validate(test, strcmp(varbuffer, "foobar") == 0);
2131 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
2132 ast_test_validate(test, strcmp(varbuffer, "record_1") == 0);
2133 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "amaflags", varbuffer, sizeof(varbuffer)) == 0);
2134 sscanf(varbuffer, "%d", &int_buffer);
2135 ast_test_validate(test, int_buffer == AST_AMA_OMIT);
2136 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "accountcode", varbuffer, sizeof(varbuffer)) == 0);
2137 ast_test_validate(test, strcmp(varbuffer, "XXX") == 0);
2138 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "clid", varbuffer, sizeof(varbuffer)) == 0);
2139 ast_test_validate(test, strcmp(varbuffer, "\"Alice\" <100>") == 0);
2140 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "src", varbuffer, sizeof(varbuffer)) == 0);
2141 ast_test_validate(test, strcmp(varbuffer, "100") == 0);
2142 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dst", varbuffer, sizeof(varbuffer)) == 0);
2143 ast_test_validate(test, strcmp(varbuffer, "100") == 0);
2144 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dcontext", varbuffer, sizeof(varbuffer)) == 0);
2145 ast_test_validate(test, strcmp(varbuffer, "default") == 0);
2146 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "channel", varbuffer, sizeof(varbuffer)) == 0);
2147 ast_test_validate(test, strcmp(varbuffer, CHANNEL_TECH_NAME "/Alice") == 0);
2148 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dstchannel", varbuffer, sizeof(varbuffer)) == 0);
2149 ast_test_validate(test, strcmp(varbuffer, "") == 0);
2150 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "lastapp", varbuffer, sizeof(varbuffer)) == 0);
2151 ast_test_validate(test, strcmp(varbuffer, "Wait") == 0);
2152 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "lastdata", varbuffer, sizeof(varbuffer)) == 0);
2153 ast_test_validate(test, strcmp(varbuffer, "10") == 0);
2154 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", varbuffer, sizeof(varbuffer)) == 0);
2155 sscanf(varbuffer, "%lf", &db_buffer);
2156 ast_test_validate(test, fabs(db_buffer) > 0);
2157 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", varbuffer, sizeof(varbuffer)) == 0);
2158 sscanf(varbuffer, "%lf", &db_buffer);
2159 ast_test_validate(test, fabs(db_buffer) < EPSILON);
2160 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "end", varbuffer, sizeof(varbuffer)) == 0);
2161 sscanf(varbuffer, "%lf", &db_buffer);
2162 ast_test_validate(test, fabs(db_buffer) < EPSILON);
2163 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "duration", varbuffer, sizeof(varbuffer)) == 0);
2164 sscanf(varbuffer, "%lf", &db_buffer);
2165 ast_test_validate(test, fabs(db_buffer) > 0);
2166 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "billsec", varbuffer, sizeof(varbuffer)) == 0);
2167 sscanf(varbuffer, "%lf", &db_buffer);
2168 ast_test_validate(test, fabs(db_buffer) < EPSILON);
2169 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "disposition", varbuffer, sizeof(varbuffer)) == 0);
2170 sscanf(varbuffer, "%d", &int_buffer);
2171 ast_test_validate(test, int_buffer == AST_CDR_NULL);
2172 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "uniqueid", varbuffer, sizeof(varbuffer)) == 0);
2173 ast_test_validate(test, strcmp(varbuffer, ast_channel_uniqueid(chan)) == 0);
2174 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "linkedid", varbuffer, sizeof(varbuffer)) == 0);
2175 ast_test_validate(test, strcmp(varbuffer, ast_channel_linkedid(chan)) == 0);
2176 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "sequence", varbuffer, sizeof(varbuffer)) == 0);
2178 /* Fork the CDR, and check that we change the properties on both CDRs. */
2179 ast_set_flag(&fork_options, AST_CDR_FLAG_KEEP_VARS);
2180 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2182 /* Change some properties */
2183 ast_cdr_setuserfield(ast_channel_name(chan), "yackity");
2184 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_1b") == 0);
2186 /* Fork the CDR again, finalizing all current CDRs */
2187 ast_set_flag(&fork_options, AST_CDR_FLAG_KEEP_VARS | AST_CDR_FLAG_FINALIZE);
2188 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2190 /* Channel enters Answer app */
2191 ast_channel_appl_set(chan, "Answer");
2192 ast_channel_data_set(chan, "");
2193 ast_channel_priority_set(chan, 1);
2194 ast_channel_publish_snapshot(chan);
2195 ast_setstate(chan, AST_STATE_UP);
2197 /* Set properties on the last record */
2198 ast_channel_accountcode_set(chan, "ZZZ");
2199 ast_cdr_setuserfield(ast_channel_name(chan), "schmackity");
2200 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
2202 /* Hang up and verify */
2203 ast_channel_hangupcause_set(chan, AST_CAUSE_NORMAL);
2204 if (!ast_hangup(chan)) {
2207 result = verify_mock_cdr_record(test, expected, 3);
2212 AST_TEST_DEFINE(test_cdr_no_reset_cdr)
2214 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
2215 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
2217 struct ast_flags fork_options = { 0, };
2218 struct timespec to_sleep = {1, 0};
2220 struct ast_party_caller caller = ALICE_CALLERID;
2221 struct ast_cdr expected = {
2222 .clid = "\"Alice\" <100>",
2225 .dcontext = "default",
2226 .channel = CHANNEL_TECH_NAME "/Alice",
2228 .amaflags = AST_AMA_DOCUMENTATION,
2229 .disposition = AST_CDR_FAILED,
2230 .accountcode = "100",
2232 enum ast_test_result_state result = AST_TEST_NOT_RUN;
2236 info->name = __func__;
2237 info->category = TEST_CATEGORY;
2238 info->summary = "Test field access CDRs";
2240 "This tests setting/retrieving data on CDR records.\n";
2241 return AST_TEST_NOT_RUN;
2246 SWAP_CONFIG(config, unanswered_cdr_config);
2248 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
2250 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
2252 /* Disable the CDR */
2253 ast_test_validate(test, ast_cdr_set_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE) == 0);
2255 /* Fork the CDR. This should be enabled */
2256 ast_set_flag(&fork_options, AST_CDR_FLAG_FINALIZE);
2257 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2259 /* Disable and enable the forked CDR */
2260 ast_test_validate(test, ast_cdr_set_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE) == 0);
2261 ast_test_validate(test, ast_cdr_clear_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE) == 0);
2263 /* Fork and finalize again. This CDR should be propagated */
2264 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2266 /* Disable all future CDRs */
2267 ast_test_validate(test, ast_cdr_set_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE_ALL) == 0);
2269 /* Fork a few more */
2270 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2271 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2272 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2274 ast_channel_hangupcause_set(chan, AST_CAUSE_NORMAL);
2275 if (!ast_hangup(chan)) {
2278 result = verify_mock_cdr_record(test, &expected, 1);
2283 AST_TEST_DEFINE(test_cdr_fork_cdr)
2285 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
2286 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
2288 char varbuffer[128];
2289 char fork_varbuffer[128];
2290 char answer_time[128];
2291 char fork_answer_time[128];
2292 char start_time[128];
2293 char fork_start_time[128];
2294 struct ast_flags fork_options = { 0, };
2295 struct timespec to_sleep = {1, 10000};
2297 struct ast_party_caller caller = ALICE_CALLERID;
2298 struct ast_cdr original = {
2299 .clid = "\"Alice\" <100>",
2302 .dcontext = "default",
2303 .channel = CHANNEL_TECH_NAME "/Alice",
2304 .amaflags = AST_AMA_DOCUMENTATION,
2305 .disposition = AST_CDR_ANSWERED,
2306 .accountcode = "100",
2308 struct ast_cdr fork_expected_one = {
2309 .clid = "\"Alice\" <100>",
2312 .dcontext = "default",
2313 .channel = CHANNEL_TECH_NAME "/Alice",
2314 .amaflags = AST_AMA_DOCUMENTATION,
2315 .disposition = AST_CDR_ANSWERED,
2316 .accountcode = "100",
2318 struct ast_cdr fork_expected_two = {
2319 .clid = "\"Alice\" <100>",
2322 .dcontext = "default",
2323 .channel = CHANNEL_TECH_NAME "/Alice",
2324 .amaflags = AST_AMA_DOCUMENTATION,
2325 .disposition = AST_CDR_ANSWERED,
2326 .accountcode = "100",
2328 enum ast_test_result_state result = AST_TEST_NOT_RUN;
2329 struct ast_cdr *expected = &original;
2330 original.next = &fork_expected_one;
2331 fork_expected_one.next = &fork_expected_two;
2335 info->name = __func__;
2336 info->category = TEST_CATEGORY;
2337 info->summary = "Test field access CDRs";
2339 "This tests setting/retrieving data on CDR records.\n";
2340 return AST_TEST_NOT_RUN;
2345 SWAP_CONFIG(config, debug_cdr_config);
2347 CREATE_ALICE_CHANNEL(chan, &caller, &original);
2348 ast_copy_string(fork_expected_one.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_one.uniqueid));
2349 ast_copy_string(fork_expected_one.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_one.linkedid));
2350 ast_copy_string(fork_expected_two.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_two.uniqueid));
2351 ast_copy_string(fork_expected_two.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_two.linkedid));
2353 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
2355 /* Test blowing away variables */
2356 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_1") == 0);
2357 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
2358 ast_test_validate(test, strcmp(varbuffer, "record_1") == 0);
2359 ast_copy_string(varbuffer, "", sizeof(varbuffer));
2361 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2362 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", fork_varbuffer, sizeof(fork_varbuffer)) == 0);
2363 ast_test_validate(test, strcmp(varbuffer, "record_1") != 0);
2365 /* Test finalizing previous CDRs */
2366 ast_set_flag(&fork_options, AST_CDR_FLAG_FINALIZE);
2367 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2369 /* Test keep variables; setting a new answer time */
2370 ast_setstate(chan, AST_STATE_UP);
2371 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
2372 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
2373 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
2374 ast_test_validate(test, strcmp(varbuffer, "record_2") == 0);
2375 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", answer_time, sizeof(answer_time)) == 0);
2376 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", start_time, sizeof(start_time)) == 0);
2378 ast_set_flag(&fork_options, AST_CDR_FLAG_FINALIZE);
2379 ast_set_flag(&fork_options, AST_CDR_FLAG_KEEP_VARS);
2380 ast_set_flag(&fork_options, AST_CDR_FLAG_SET_ANSWER);
2381 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2382 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", fork_answer_time, sizeof(fork_answer_time)) == 0);
2383 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", fork_start_time, sizeof(fork_start_time)) == 0);
2384 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", fork_varbuffer, sizeof(fork_varbuffer)) == 0);
2385 ast_test_validate(test, strcmp(fork_varbuffer, varbuffer) == 0);
2386 ast_test_validate(test, strcmp(fork_start_time, start_time) == 0);
2387 ast_test_validate(test, strcmp(fork_answer_time, answer_time) != 0);
2389 ast_clear_flag(&fork_options, AST_CDR_FLAG_SET_ANSWER);
2390 ast_set_flag(&fork_options, AST_CDR_FLAG_RESET);
2391 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2392 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", fork_answer_time, sizeof(fork_answer_time)) == 0);
2393 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", fork_start_time, sizeof(fork_start_time)) == 0);
2394 ast_test_validate(test, strcmp(fork_start_time, start_time) != 0);
2395 ast_test_validate(test, strcmp(fork_answer_time, answer_time) != 0);
2397 ast_channel_hangupcause_set(chan, AST_CAUSE_NORMAL);
2398 if (!ast_hangup(chan)) {
2401 result = verify_mock_cdr_record(test, expected, 3);
2407 * \internal \brief Callback function called before each test executes
2409 static int test_cdr_init_cb(struct ast_test_info *info, struct ast_test *test)
2411 /* Back up the real config */
2412 saved_config = ast_cdr_get_config();
2413 clear_mock_cdr_backend();
2418 * \internal \brief Callback function called after each test executes
2420 static int test_cdr_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
2422 /* Restore the real config */
2423 ast_cdr_set_config(saved_config);
2424 ao2_cleanup(saved_config);
2425 saved_config = NULL;
2426 clear_mock_cdr_backend();
2432 static int unload_module(void)
2434 AST_TEST_UNREGISTER(test_cdr_channel_creation);
2435 AST_TEST_UNREGISTER(test_cdr_unanswered_inbound_call);
2436 AST_TEST_UNREGISTER(test_cdr_unanswered_outbound_call);
2438 AST_TEST_UNREGISTER(test_cdr_single_party);
2439 AST_TEST_UNREGISTER(test_cdr_single_bridge);
2440 AST_TEST_UNREGISTER(test_cdr_single_bridge_continue);
2441 AST_TEST_UNREGISTER(test_cdr_single_twoparty_bridge_a);
2442 AST_TEST_UNREGISTER(test_cdr_single_twoparty_bridge_b);
2443 AST_TEST_UNREGISTER(test_cdr_single_multiparty_bridge);
2445 AST_TEST_UNREGISTER(test_cdr_outbound_bridged_call);
2447 AST_TEST_UNREGISTER(test_cdr_dial_unanswered);
2448 AST_TEST_UNREGISTER(test_cdr_dial_congestion);
2449 AST_TEST_UNREGISTER(test_cdr_dial_busy);
2450 AST_TEST_UNREGISTER(test_cdr_dial_unavailable);
2451 AST_TEST_UNREGISTER(test_cdr_dial_caller_cancel);
2452 AST_TEST_UNREGISTER(test_cdr_dial_parallel_failed);
2453 AST_TEST_UNREGISTER(test_cdr_dial_answer_no_bridge);
2454 AST_TEST_UNREGISTER(test_cdr_dial_answer_twoparty_bridge_a);
2455 AST_TEST_UNREGISTER(test_cdr_dial_answer_twoparty_bridge_b);
2456 AST_TEST_UNREGISTER(test_cdr_dial_answer_multiparty);
2458 AST_TEST_UNREGISTER(test_cdr_park);
2460 AST_TEST_UNREGISTER(test_cdr_fields);
2461 AST_TEST_UNREGISTER(test_cdr_no_reset_cdr);
2462 AST_TEST_UNREGISTER(test_cdr_fork_cdr);
2464 ast_cdr_unregister(MOCK_CDR_BACKEND);
2465 ast_channel_unregister(&test_cdr_chan_tech);
2466 clear_mock_cdr_backend();
2471 static int load_module(void)
2473 ast_cond_init(&mock_cdr_cond, NULL);
2475 AST_TEST_REGISTER(test_cdr_channel_creation);
2476 AST_TEST_REGISTER(test_cdr_unanswered_inbound_call);
2477 AST_TEST_REGISTER(test_cdr_unanswered_outbound_call);
2479 AST_TEST_REGISTER(test_cdr_single_party);
2480 AST_TEST_REGISTER(test_cdr_single_bridge);
2481 AST_TEST_REGISTER(test_cdr_single_bridge_continue);
2482 AST_TEST_REGISTER(test_cdr_single_twoparty_bridge_a);
2483 AST_TEST_REGISTER(test_cdr_single_twoparty_bridge_b);
2484 AST_TEST_REGISTER(test_cdr_single_multiparty_bridge);
2486 AST_TEST_REGISTER(test_cdr_outbound_bridged_call);
2488 AST_TEST_REGISTER(test_cdr_dial_unanswered);
2489 AST_TEST_REGISTER(test_cdr_dial_congestion);
2490 AST_TEST_REGISTER(test_cdr_dial_busy);
2491 AST_TEST_REGISTER(test_cdr_dial_unavailable);
2492 AST_TEST_REGISTER(test_cdr_dial_caller_cancel);
2493 AST_TEST_REGISTER(test_cdr_dial_parallel_failed);
2494 AST_TEST_REGISTER(test_cdr_dial_answer_no_bridge);
2495 AST_TEST_REGISTER(test_cdr_dial_answer_twoparty_bridge_a);
2496 AST_TEST_REGISTER(test_cdr_dial_answer_twoparty_bridge_b);
2497 AST_TEST_REGISTER(test_cdr_dial_answer_multiparty);
2499 AST_TEST_REGISTER(test_cdr_park);
2501 AST_TEST_REGISTER(test_cdr_fields);
2502 AST_TEST_REGISTER(test_cdr_no_reset_cdr);
2503 AST_TEST_REGISTER(test_cdr_fork_cdr);
2505 ast_test_register_init(TEST_CATEGORY, test_cdr_init_cb);
2506 ast_test_register_cleanup(TEST_CATEGORY, test_cdr_cleanup_cb);
2508 ast_channel_register(&test_cdr_chan_tech);
2509 ast_cdr_register(MOCK_CDR_BACKEND, "Mock CDR backend", mock_cdr_backend_cb);
2511 return AST_MODULE_LOAD_SUCCESS;
2514 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "CDR unit tests");