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/bridge.h"
46 #include "asterisk/bridge_features.h"
47 #include "asterisk/stasis_channels.h"
48 #include "asterisk/stasis_bridges.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) \
283 ast_channel_hangupcause_set((channel), (cause)); \
284 ast_hangup(channel); \
288 static enum ast_test_result_state verify_mock_cdr_record(struct ast_test *test, struct ast_cdr *expected, int record)
290 struct ast_cdr *actual = NULL;
291 struct test_cdr_entry *cdr_wrapper;
293 struct timeval wait_now = ast_tvnow();
294 struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 5, .tv_nsec = wait_now.tv_usec * 1000 };
295 enum ast_test_result_state res = AST_TEST_PASS;
297 while (count < record) {
298 AST_LIST_LOCK(&actual_cdr_entries);
299 if (global_mock_cdr_count < record) {
300 ast_cond_timedwait(&mock_cdr_cond, &actual_cdr_entries.lock, &wait_time);
302 cdr_wrapper = AST_LIST_REMOVE_HEAD(&actual_cdr_entries, list);
303 AST_LIST_UNLOCK(&actual_cdr_entries);
306 ast_test_status_update(test, "Unable to find actual CDR record at %d\n", count);
307 return AST_TEST_FAIL;
309 actual = cdr_wrapper->cdr;
311 if (!expected && actual) {
312 ast_test_status_update(test, "CDRs recorded where no record expected\n");
313 return AST_TEST_FAIL;
316 VERIFY_STRING_FIELD(accountcode, actual, expected);
317 VERIFY_NUMERIC_FIELD(amaflags, actual, expected);
318 VERIFY_STRING_FIELD(channel, actual, expected);
319 VERIFY_STRING_FIELD(clid, actual, expected);
320 VERIFY_STRING_FIELD(dcontext, actual, expected);
321 VERIFY_NUMERIC_FIELD(disposition, actual, expected);
322 VERIFY_STRING_FIELD(dst, actual, expected);
323 VERIFY_STRING_FIELD(dstchannel, actual, expected);
324 VERIFY_STRING_FIELD(lastapp, actual, expected);
325 VERIFY_STRING_FIELD(lastdata, actual, expected);
326 VERIFY_STRING_FIELD(linkedid, actual, expected);
327 VERIFY_STRING_FIELD(peeraccount, actual, expected);
328 VERIFY_STRING_FIELD(src, actual, expected);
329 VERIFY_STRING_FIELD(uniqueid, actual, expected);
330 VERIFY_STRING_FIELD(userfield, actual, expected);
331 VERIFY_TIME_VALUE(start, actual);
332 VERIFY_TIME_VALUE(end, actual);
333 /* Note: there's no way we can really calculate a duration or
334 * billsec - the unit tests are too short. However, if billsec is
335 * non-zero in the expected, then make sure we have an answer time
337 if (expected->billsec) {
338 VERIFY_TIME_VALUE(answer, actual);
340 ast_test_debug(test, "Finished expected record %s, %s\n",
341 expected->channel, S_OR(expected->dstchannel, "<none>"));
342 expected = expected->next;
348 static void safe_channel_release(struct ast_channel *chan)
353 ast_channel_release(chan);
356 AST_TEST_DEFINE(test_cdr_channel_creation)
358 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
359 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
362 struct ast_party_caller caller = ALICE_CALLERID;
363 struct ast_cdr expected = {
364 .clid = "\"Alice\" <100>",
367 .dcontext = "default",
368 .channel = CHANNEL_TECH_NAME "/Alice",
369 .amaflags = AST_AMA_DOCUMENTATION,
370 .disposition = AST_CDR_NOANSWER,
371 .accountcode = "100",
373 enum ast_test_result_state result = AST_TEST_NOT_RUN;
377 info->name = __func__;
378 info->category = TEST_CATEGORY;
379 info->summary = "Test that a CDR is created when a channel is created";
381 "Test that a CDR is created when a channel is created";
382 return AST_TEST_NOT_RUN;
387 SWAP_CONFIG(config, unanswered_cdr_config);
389 CREATE_ALICE_CHANNEL(chan, (&caller), &expected);
391 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
393 result = verify_mock_cdr_record(test, &expected, 1);
398 AST_TEST_DEFINE(test_cdr_unanswered_inbound_call)
400 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
401 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
404 struct ast_party_caller caller = ALICE_CALLERID;
405 struct ast_cdr expected = {
406 .clid = "\"Alice\" <100>",
409 .dcontext = "default",
410 .channel = CHANNEL_TECH_NAME "/Alice",
413 .amaflags = AST_AMA_DOCUMENTATION,
414 .disposition = AST_CDR_NOANSWER,
415 .accountcode = "100",
417 enum ast_test_result_state result = AST_TEST_NOT_RUN;
421 info->name = __func__;
422 info->category = TEST_CATEGORY;
423 info->summary = "Test inbound unanswered calls";
425 "Test the properties of a CDR for a call that is\n"
426 "inbound to Asterisk, executes some dialplan, but\n"
427 "is never answered.\n";
428 return AST_TEST_NOT_RUN;
433 SWAP_CONFIG(config, unanswered_cdr_config);
435 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
437 EMULATE_APP_DATA(chan, 1, "Wait", "1");
439 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
441 result = verify_mock_cdr_record(test, &expected, 1);
446 AST_TEST_DEFINE(test_cdr_unanswered_outbound_call)
448 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
449 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
452 struct ast_party_caller caller = {
456 .id.number.valid = 1, };
457 struct ast_cdr expected = {
460 .dcontext = "default",
461 .channel = CHANNEL_TECH_NAME "/Alice",
462 .lastapp = "AppDial",
463 .lastdata = "(Outgoing Line)",
464 .amaflags = AST_AMA_DOCUMENTATION,
465 .disposition = AST_CDR_NOANSWER,
466 .accountcode = "100",
468 enum ast_test_result_state result = AST_TEST_NOT_RUN;
472 info->name = __func__;
473 info->category = TEST_CATEGORY;
474 info->summary = "Test outbound unanswered calls";
476 "Test the properties of a CDR for a call that is\n"
477 "outbound to Asterisk but is never answered.\n";
478 return AST_TEST_NOT_RUN;
483 SWAP_CONFIG(config, unanswered_cdr_config);
485 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
487 ast_channel_exten_set(chan, "s");
488 ast_channel_context_set(chan, "default");
489 ast_set_flag(ast_channel_flags(chan), AST_FLAG_ORIGINATED);
490 EMULATE_APP_DATA(chan, 0, "AppDial", "(Outgoing Line)");
491 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
493 result = verify_mock_cdr_record(test, &expected, 1);
498 AST_TEST_DEFINE(test_cdr_outbound_bridged_call)
500 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
501 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
502 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
503 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
505 struct timespec to_sleep = {1, 0};
506 enum ast_test_result_state result = AST_TEST_NOT_RUN;
508 struct ast_party_caller caller = ALICE_CALLERID;
509 struct ast_cdr alice_expected = {
510 .clid = "\"Alice\" <100>",
513 .dcontext = "default",
514 .channel = CHANNEL_TECH_NAME "/Alice",
515 .dstchannel = CHANNEL_TECH_NAME "/Bob",
518 .amaflags = AST_AMA_DOCUMENTATION,
520 .disposition = AST_CDR_ANSWERED,
521 .accountcode = "100",
522 .peeraccount = "200",
524 struct ast_cdr bob_expected = {
528 .dcontext = "default",
529 .channel = CHANNEL_TECH_NAME "/Bob",
531 .lastapp = "AppDial",
532 .lastdata = "(Outgoing Line)",
533 .amaflags = AST_AMA_DOCUMENTATION,
535 .disposition = AST_CDR_ANSWERED,
536 .accountcode = "200",
538 .next = &alice_expected,
543 info->name = __func__;
544 info->category = TEST_CATEGORY;
545 info->summary = "Test dialing, answering, and going into a 2-party bridge";
547 "The most 'basic' of scenarios\n";
548 return AST_TEST_NOT_RUN;
553 SWAP_CONFIG(config, debug_cdr_config);
555 CREATE_ALICE_CHANNEL(chan_alice, &caller, &alice_expected);
556 ast_channel_state_set(chan_alice, AST_STATE_UP);
558 bridge = ast_bridge_basic_new();
559 ast_test_validate(test, bridge != NULL);
560 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
562 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
564 chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_alice), 0, CHANNEL_TECH_NAME "/Bob");
565 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_bob), sizeof(bob_expected.linkedid));
566 ast_copy_string(bob_expected.uniqueid, ast_channel_uniqueid(chan_bob), sizeof(bob_expected.uniqueid));
567 ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
568 ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_ORIGINATED);
569 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
571 ast_channel_publish_dial(NULL, chan_bob, "Bob", NULL);
572 ast_channel_state_set(chan_bob, AST_STATE_RINGING);
573 ast_channel_publish_dial(NULL, chan_bob, NULL, "ANSWER");
575 ast_channel_state_set(chan_bob, AST_STATE_UP);
577 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
579 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
581 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
583 ast_bridge_depart(chan_bob);
584 ast_bridge_depart(chan_alice);
586 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
587 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
589 result = verify_mock_cdr_record(test, &bob_expected, 2);
594 AST_TEST_DEFINE(test_cdr_single_party)
596 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
597 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
600 struct ast_party_caller caller = ALICE_CALLERID;
601 struct ast_cdr expected = {
602 .clid = "\"Alice\" <100>",
605 .dcontext = "default",
606 .channel = CHANNEL_TECH_NAME "/Alice",
608 .lastapp = "VoiceMailMain",
611 .amaflags = AST_AMA_DOCUMENTATION,
612 .disposition = AST_CDR_ANSWERED,
613 .accountcode = "100",
615 enum ast_test_result_state result = AST_TEST_NOT_RUN;
619 info->name = __func__;
620 info->category = TEST_CATEGORY;
621 info->summary = "Test cdrs for a single party";
623 "Test the properties of a CDR for a call that is\n"
624 "answered, but only involves a single channel\n";
625 return AST_TEST_NOT_RUN;
629 SWAP_CONFIG(config, debug_cdr_config);
630 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
632 EMULATE_APP_DATA(chan, 1, "Answer", "");
633 ast_setstate(chan, AST_STATE_UP);
634 EMULATE_APP_DATA(chan, 2, "VoiceMailMain", "1");
636 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
638 result = verify_mock_cdr_record(test, &expected, 1);
643 AST_TEST_DEFINE(test_cdr_single_bridge)
645 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
646 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
647 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
649 struct timespec to_sleep = {1, 0};
651 struct ast_party_caller caller = ALICE_CALLERID;
652 struct ast_cdr expected = {
653 .clid = "\"Alice\" <100>",
656 .dcontext = "default",
657 .channel = CHANNEL_TECH_NAME "/Alice",
660 .amaflags = AST_AMA_DOCUMENTATION,
661 .disposition = AST_CDR_ANSWERED,
662 .accountcode = "100",
664 enum ast_test_result_state result = AST_TEST_NOT_RUN;
668 info->name = __func__;
669 info->category = TEST_CATEGORY;
670 info->summary = "Test cdrs for a single party entering/leaving a bridge";
672 "Test the properties of a CDR for a call that is\n"
673 "answered, enters a bridge, and leaves it.\n";
674 return AST_TEST_NOT_RUN;
678 SWAP_CONFIG(config, debug_cdr_config);
679 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
681 EMULATE_APP_DATA(chan, 1, "Answer", "");
682 ast_setstate(chan, AST_STATE_UP);
683 EMULATE_APP_DATA(chan, 2, "Bridge", "");
685 bridge = ast_bridge_basic_new();
686 ast_test_validate(test, bridge != NULL);
688 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
689 ast_bridge_impart(bridge, chan, NULL, NULL, 0);
691 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
693 ast_bridge_depart(chan);
695 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
697 result = verify_mock_cdr_record(test, &expected, 1);
702 AST_TEST_DEFINE(test_cdr_single_bridge_continue)
704 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
705 RAII_VAR(struct ast_bridge *, bridge_one, NULL, ao2_cleanup);
706 RAII_VAR(struct ast_bridge *, bridge_two, NULL, ao2_cleanup);
707 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
709 struct timespec to_sleep = {1, 0};
711 struct ast_party_caller caller = ALICE_CALLERID;
712 struct ast_cdr expected_two = {
713 .clid = "\"Alice\" <100>",
716 .dcontext = "default",
717 .channel = CHANNEL_TECH_NAME "/Alice",
720 .amaflags = AST_AMA_DOCUMENTATION,
721 .disposition = AST_CDR_ANSWERED,
722 .accountcode = "100",
724 struct ast_cdr expected_one = {
725 .clid = "\"Alice\" <100>",
728 .dcontext = "default",
729 .channel = CHANNEL_TECH_NAME "/Alice",
732 .amaflags = AST_AMA_DOCUMENTATION,
733 .disposition = AST_CDR_ANSWERED,
734 .accountcode = "100",
735 .next = &expected_two,
738 enum ast_test_result_state result = AST_TEST_NOT_RUN;
742 info->name = __func__;
743 info->category = TEST_CATEGORY;
744 info->summary = "Test cdrs for a single party entering/leaving a bridge";
746 "Test the properties of a CDR for a call that is\n"
747 "answered, enters a bridge, and leaves it.\n";
748 return AST_TEST_NOT_RUN;
752 SWAP_CONFIG(config, debug_cdr_config);
753 CREATE_ALICE_CHANNEL(chan, &caller, &expected_one);
754 COPY_IDS(chan, &expected_two);
756 EMULATE_APP_DATA(chan, 1, "Answer", "");
757 ast_setstate(chan, AST_STATE_UP);
758 EMULATE_APP_DATA(chan, 2, "Bridge", "");
760 bridge_one = ast_bridge_basic_new();
761 ast_test_validate(test, bridge_one != NULL);
762 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
764 ast_bridge_impart(bridge_one, chan, NULL, NULL, 0);
766 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
768 ast_bridge_depart(chan);
770 EMULATE_APP_DATA(chan, 3, "Wait", "");
772 /* And then it hangs up */
773 HANGUP_CHANNEL(chan, AST_CAUSE_NORMAL);
775 result = verify_mock_cdr_record(test, &expected_one, 2);
780 AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_a)
782 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
783 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
784 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
785 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
787 struct timespec to_sleep = {1, 0};
789 struct ast_party_caller caller_alice = ALICE_CALLERID;
790 struct ast_party_caller caller_bob = BOB_CALLERID;
791 struct ast_cdr bob_expected = {
792 .clid = "\"Bob\" <200>",
795 .dcontext = "default",
796 .channel = CHANNEL_TECH_NAME "/Bob",
799 .amaflags = AST_AMA_DOCUMENTATION,
800 .disposition = AST_CDR_ANSWERED,
801 .accountcode = "200",
803 struct ast_cdr alice_expected = {
804 .clid = "\"Alice\" <100>",
807 .dcontext = "default",
808 .channel = CHANNEL_TECH_NAME "/Alice",
809 .dstchannel = CHANNEL_TECH_NAME "/Bob",
812 .amaflags = AST_AMA_DOCUMENTATION,
813 .disposition = AST_CDR_ANSWERED,
814 .accountcode = "100",
815 .peeraccount = "200",
816 .next = &bob_expected,
819 enum ast_test_result_state result = AST_TEST_NOT_RUN;
823 info->name = __func__;
824 info->category = TEST_CATEGORY;
825 info->summary = "Test cdrs for a single party entering/leaving a bridge";
827 "Test the properties of a CDR for a call that is\n"
828 "answered, enters a bridge, and leaves it. In this scenario, the\n"
829 "Party A should answer the bridge first.\n";
830 return AST_TEST_NOT_RUN;
834 SWAP_CONFIG(config, debug_cdr_config);
835 CREATE_ALICE_CHANNEL(chan_alice, &caller_alice, &alice_expected);
837 CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
838 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
840 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
841 ast_setstate(chan_alice, AST_STATE_UP);
842 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
844 bridge = ast_bridge_basic_new();
845 ast_test_validate(test, bridge != NULL);
847 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
848 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
850 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
851 ast_setstate(chan_bob, AST_STATE_UP);
852 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
854 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
855 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
857 ast_bridge_depart(chan_alice);
858 ast_bridge_depart(chan_bob);
860 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
861 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
863 result = verify_mock_cdr_record(test, &alice_expected, 2);
868 AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_b)
870 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
871 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
872 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
873 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
875 struct timespec to_sleep = {1, 0};
877 struct ast_party_caller caller_alice = ALICE_CALLERID;
878 struct ast_party_caller caller_bob = BOB_CALLERID;
879 struct ast_cdr bob_expected = {
880 .clid = "\"Bob\" <200>",
883 .dcontext = "default",
884 .channel = CHANNEL_TECH_NAME "/Bob",
887 .amaflags = AST_AMA_DOCUMENTATION,
888 .disposition = AST_CDR_ANSWERED,
889 .accountcode = "200",
891 struct ast_cdr alice_expected = {
892 .clid = "\"Alice\" <100>",
895 .dcontext = "default",
896 .channel = CHANNEL_TECH_NAME "/Alice",
897 .dstchannel = CHANNEL_TECH_NAME "/Bob",
900 .amaflags = AST_AMA_DOCUMENTATION,
901 .disposition = AST_CDR_ANSWERED,
902 .accountcode = "100",
903 .peeraccount = "200",
904 .next = &bob_expected,
907 enum ast_test_result_state result = AST_TEST_NOT_RUN;
911 info->name = __func__;
912 info->category = TEST_CATEGORY;
913 info->summary = "Test cdrs for a single party entering/leaving a bridge";
915 "Test the properties of a CDR for a call that is\n"
916 "answered, enters a bridge, and leaves it. In this scenario, the\n"
917 "Party B should answer the bridge first.\n";
918 return AST_TEST_NOT_RUN;
922 SWAP_CONFIG(config, debug_cdr_config);
923 CREATE_ALICE_CHANNEL(chan_alice, &caller_alice, &alice_expected);
925 CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
926 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
928 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
929 ast_setstate(chan_alice, AST_STATE_UP);
930 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
932 bridge = ast_bridge_basic_new();
933 ast_test_validate(test, bridge != NULL);
935 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
936 ast_setstate(chan_bob, AST_STATE_UP);
937 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
938 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
940 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
941 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
943 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
944 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
946 ast_bridge_depart(chan_alice);
947 ast_bridge_depart(chan_bob);
949 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
950 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
952 result = verify_mock_cdr_record(test, &alice_expected, 2);
957 AST_TEST_DEFINE(test_cdr_single_multiparty_bridge)
959 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
960 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
961 RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
962 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
963 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
965 struct timespec to_sleep = {1, 0};
967 struct ast_party_caller caller_alice = ALICE_CALLERID;
968 struct ast_party_caller caller_bob = BOB_CALLERID;
969 struct ast_party_caller caller_charlie = CHARLIE_CALLERID;
970 struct ast_cdr charlie_expected = {
971 .clid = "\"Charlie\" <300>",
974 .dcontext = "default",
975 .channel = CHANNEL_TECH_NAME "/Charlie",
978 .amaflags = AST_AMA_DOCUMENTATION,
979 .disposition = AST_CDR_ANSWERED,
980 .accountcode = "300",
982 struct ast_cdr bob_expected = {
983 .clid = "\"Bob\" <200>",
986 .dcontext = "default",
987 .channel = CHANNEL_TECH_NAME "/Bob",
988 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
991 .amaflags = AST_AMA_DOCUMENTATION,
992 .disposition = AST_CDR_ANSWERED,
993 .accountcode = "200",
994 .peeraccount = "300",
995 .next = &charlie_expected,
997 struct ast_cdr alice_expected_two = {
998 .clid = "\"Alice\" <100>",
1001 .dcontext = "default",
1002 .channel = CHANNEL_TECH_NAME "/Alice",
1003 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1004 .lastapp = "Bridge",
1006 .amaflags = AST_AMA_DOCUMENTATION,
1007 .disposition = AST_CDR_ANSWERED,
1008 .accountcode = "100",
1009 .peeraccount = "300",
1010 .next = &bob_expected,
1012 struct ast_cdr alice_expected_one = {
1013 .clid = "\"Alice\" <100>",
1016 .dcontext = "default",
1017 .channel = CHANNEL_TECH_NAME "/Alice",
1018 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1019 .lastapp = "Bridge",
1021 .amaflags = AST_AMA_DOCUMENTATION,
1022 .disposition = AST_CDR_ANSWERED,
1023 .accountcode = "100",
1024 .peeraccount = "200",
1025 .next = &alice_expected_two,
1028 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1032 info->name = __func__;
1033 info->category = TEST_CATEGORY;
1034 info->summary = "Test cdrs for a single party entering/leaving a multi-party bridge";
1036 "Test the properties of a CDR for a call that is\n"
1037 "answered, enters a bridge, and leaves it. A total of three\n"
1038 "parties perform this action.\n";
1039 return AST_TEST_NOT_RUN;
1043 SWAP_CONFIG(config, debug_cdr_config);
1044 CREATE_ALICE_CHANNEL(chan_alice, &caller_alice, &alice_expected_one);
1045 COPY_IDS(chan_alice, &alice_expected_two);
1046 CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
1047 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
1048 CREATE_CHARLIE_CHANNEL(chan_charlie, &caller_charlie, &charlie_expected);
1049 ast_copy_string(charlie_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected.linkedid));
1051 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
1052 ast_setstate(chan_alice, AST_STATE_UP);
1053 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
1055 bridge = ast_bridge_basic_new();
1056 ast_test_validate(test, bridge != NULL);
1057 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1059 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
1061 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
1062 ast_setstate(chan_bob, AST_STATE_UP);
1063 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
1064 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1066 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
1068 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1070 EMULATE_APP_DATA(chan_charlie, 1, "Answer", "");
1071 ast_setstate(chan_charlie, AST_STATE_UP);
1072 EMULATE_APP_DATA(chan_charlie, 2, "Bridge", "");
1073 ast_bridge_impart(bridge, chan_charlie, NULL, NULL, 0);
1075 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1077 ast_bridge_depart(chan_alice);
1078 ast_bridge_depart(chan_bob);
1079 ast_bridge_depart(chan_charlie);
1081 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
1082 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
1083 HANGUP_CHANNEL(chan_charlie, AST_CAUSE_NORMAL);
1085 result = verify_mock_cdr_record(test, &alice_expected_one, 4);
1090 AST_TEST_DEFINE(test_cdr_dial_unanswered)
1092 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1093 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1094 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1097 struct ast_party_caller caller = ALICE_CALLERID;
1098 struct ast_cdr expected = {
1099 .clid = "\"Alice\" <100>",
1102 .dcontext = "default",
1103 .channel = CHANNEL_TECH_NAME "/Alice",
1104 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1106 .lastdata = CHANNEL_TECH_NAME "/Bob",
1108 .amaflags = AST_AMA_DOCUMENTATION,
1109 .disposition = AST_CDR_NOANSWER,
1110 .accountcode = "100",
1111 .peeraccount = "200",
1113 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1117 info->name = __func__;
1118 info->category = TEST_CATEGORY;
1119 info->summary = "Test CDRs for a dial that isn't answered";
1121 "Test the properties of a CDR for a channel that\n"
1122 "performs a dial operation that isn't answered\n";
1123 return AST_TEST_NOT_RUN;
1128 SWAP_CONFIG(config, unanswered_cdr_config);
1130 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1132 EMULATE_APP_DATA(chan_caller, 1, "Dial", "CDRTestChannel/Bob");
1134 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1135 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1136 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1138 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1139 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1140 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "NOANSWER");
1142 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NO_ANSWER);
1143 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NO_ANSWER);
1145 result = verify_mock_cdr_record(test, &expected, 1);
1151 AST_TEST_DEFINE(test_cdr_dial_busy)
1153 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1154 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1155 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1158 struct ast_party_caller caller = ALICE_CALLERID;
1159 struct ast_cdr expected = {
1160 .clid = "\"Alice\" <100>",
1163 .dcontext = "default",
1164 .channel = CHANNEL_TECH_NAME "/Alice",
1165 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1167 .lastdata = CHANNEL_TECH_NAME "/Bob",
1169 .amaflags = AST_AMA_DOCUMENTATION,
1170 .disposition = AST_CDR_BUSY,
1171 .accountcode = "100",
1172 .peeraccount = "200",
1174 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1178 info->name = __func__;
1179 info->category = TEST_CATEGORY;
1180 info->summary = "Test CDRs for a dial that results in a busy";
1182 "Test the properties of a CDR for a channel that\n"
1183 "performs a dial operation to an endpoint that's busy\n";
1184 return AST_TEST_NOT_RUN;
1189 SWAP_CONFIG(config, unanswered_cdr_config);
1191 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1193 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1195 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1196 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1197 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1199 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1200 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1201 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "BUSY");
1203 HANGUP_CHANNEL(chan_caller, AST_CAUSE_BUSY);
1204 HANGUP_CHANNEL(chan_callee, AST_CAUSE_BUSY);
1206 result = verify_mock_cdr_record(test, &expected, 1);
1211 AST_TEST_DEFINE(test_cdr_dial_congestion)
1213 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1214 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1215 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1218 struct ast_party_caller caller = ALICE_CALLERID;
1219 struct ast_cdr expected = {
1220 .clid = "\"Alice\" <100>",
1223 .dcontext = "default",
1224 .channel = CHANNEL_TECH_NAME "/Alice",
1225 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1227 .lastdata = CHANNEL_TECH_NAME "/Bob",
1229 .amaflags = AST_AMA_DOCUMENTATION,
1230 .disposition = AST_CDR_CONGESTION,
1231 .accountcode = "100",
1232 .peeraccount = "200",
1234 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1238 info->name = __func__;
1239 info->category = TEST_CATEGORY;
1240 info->summary = "Test CDRs for a dial that results in congestion";
1242 "Test the properties of a CDR for a channel that\n"
1243 "performs a dial operation to an endpoint that's congested\n";
1244 return AST_TEST_NOT_RUN;
1249 SWAP_CONFIG(config, congestion_cdr_config);
1251 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1253 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1255 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1256 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1257 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1259 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1260 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1261 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "CONGESTION");
1263 HANGUP_CHANNEL(chan_caller, AST_CAUSE_CONGESTION);
1264 HANGUP_CHANNEL(chan_callee, AST_CAUSE_CONGESTION);
1266 result = verify_mock_cdr_record(test, &expected, 1);
1271 AST_TEST_DEFINE(test_cdr_dial_unavailable)
1273 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1274 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1275 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1278 struct ast_party_caller caller = ALICE_CALLERID;
1279 struct ast_cdr expected = {
1280 .clid = "\"Alice\" <100>",
1283 .dcontext = "default",
1284 .channel = CHANNEL_TECH_NAME "/Alice",
1285 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1287 .lastdata = CHANNEL_TECH_NAME "/Bob",
1289 .amaflags = AST_AMA_DOCUMENTATION,
1290 .disposition = AST_CDR_FAILED,
1291 .accountcode = "100",
1292 .peeraccount = "200",
1294 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1298 info->name = __func__;
1299 info->category = TEST_CATEGORY;
1300 info->summary = "Test CDRs for a dial that results in unavailable";
1302 "Test the properties of a CDR for a channel that\n"
1303 "performs a dial operation to an endpoint that's unavailable\n";
1304 return AST_TEST_NOT_RUN;
1309 SWAP_CONFIG(config, unanswered_cdr_config);
1311 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1313 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1315 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1316 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1317 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1319 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1320 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1321 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "CHANUNAVAIL");
1323 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NO_ROUTE_DESTINATION);
1324 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NO_ROUTE_DESTINATION);
1326 result = verify_mock_cdr_record(test, &expected, 1);
1331 AST_TEST_DEFINE(test_cdr_dial_caller_cancel)
1333 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1334 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1335 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1338 struct ast_party_caller caller = ALICE_CALLERID;
1339 struct ast_cdr expected = {
1340 .clid = "\"Alice\" <100>",
1343 .dcontext = "default",
1344 .channel = CHANNEL_TECH_NAME "/Alice",
1345 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1347 .lastdata = CHANNEL_TECH_NAME "/Bob",
1349 .amaflags = AST_AMA_DOCUMENTATION,
1350 .disposition = AST_CDR_NOANSWER,
1351 .accountcode = "100",
1352 .peeraccount = "200",
1354 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1358 info->name = __func__;
1359 info->category = TEST_CATEGORY;
1360 info->summary = "Test CDRs for a dial where the caller cancels";
1362 "Test the properties of a CDR for a channel that\n"
1363 "performs a dial operation to an endpoint but then decides\n"
1364 "to hang up, cancelling the dial\n";
1365 return AST_TEST_NOT_RUN;
1370 SWAP_CONFIG(config, unanswered_cdr_config);
1372 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1374 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1376 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1377 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1378 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1380 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1381 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1382 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "CANCEL");
1384 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1385 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1387 result = verify_mock_cdr_record(test, &expected, 1);
1392 AST_TEST_DEFINE(test_cdr_dial_parallel_failed)
1394 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1395 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
1396 RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
1397 RAII_VAR(struct ast_channel *, chan_david, NULL, safe_channel_release);
1398 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1401 struct ast_party_caller caller = ALICE_CALLERID;
1402 struct ast_cdr bob_expected = {
1403 .clid = "\"Alice\" <100>",
1406 .dcontext = "default",
1407 .channel = CHANNEL_TECH_NAME "/Alice",
1408 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1410 .lastdata = CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David",
1412 .amaflags = AST_AMA_DOCUMENTATION,
1413 .disposition = AST_CDR_NOANSWER,
1414 .accountcode = "100",
1415 .peeraccount = "200",
1417 struct ast_cdr charlie_expected = {
1418 .clid = "\"Alice\" <100>",
1421 .dcontext = "default",
1422 .channel = CHANNEL_TECH_NAME "/Alice",
1423 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1425 .lastdata = CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David",
1427 .amaflags = AST_AMA_DOCUMENTATION,
1428 .disposition = AST_CDR_BUSY,
1429 .accountcode = "100",
1430 .peeraccount = "300",
1432 struct ast_cdr david_expected = {
1433 .clid = "\"Alice\" <100>",
1436 .dcontext = "default",
1437 .channel = CHANNEL_TECH_NAME "/Alice",
1438 .dstchannel = CHANNEL_TECH_NAME "/David",
1440 .lastdata = CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David",
1442 .amaflags = AST_AMA_DOCUMENTATION,
1443 .disposition = AST_CDR_CONGESTION,
1444 .accountcode = "100",
1445 .peeraccount = "400",
1447 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1449 struct ast_cdr *expected = &bob_expected;
1450 bob_expected.next = &charlie_expected;
1451 charlie_expected.next = &david_expected;
1455 info->name = __func__;
1456 info->category = TEST_CATEGORY;
1457 info->summary = "Test a parallel dial where all channels fail to answer";
1459 "This tests dialing three parties: Bob, Charlie, David. Charlie\n"
1460 "returns BUSY; David returns CONGESTION; Bob fails to answer and\n"
1461 "Alice hangs up. Three records are created for Alice as a result.\n";
1462 return AST_TEST_NOT_RUN;
1467 SWAP_CONFIG(config, congestion_cdr_config);
1469 CREATE_ALICE_CHANNEL(chan_caller, &caller, &bob_expected);
1470 COPY_IDS(chan_caller, &charlie_expected);
1471 COPY_IDS(chan_caller, &david_expected);
1473 /* Channel enters Dial app */
1474 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David");
1476 /* Outbound channels are created */
1477 chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1478 ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
1479 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
1481 chan_charlie = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "300", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Charlie");
1482 ast_set_flag(ast_channel_flags(chan_charlie), AST_FLAG_OUTGOING);
1483 EMULATE_APP_DATA(chan_charlie, 0, "AppDial", "(Outgoing Line)");
1485 chan_david = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "400", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/David");
1486 ast_set_flag(ast_channel_flags(chan_david), AST_FLAG_OUTGOING);
1487 EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");
1490 ast_channel_publish_dial(chan_caller, chan_bob, "Bob", NULL);
1491 ast_channel_publish_dial(chan_caller, chan_charlie, "Charlie", NULL);
1492 ast_channel_publish_dial(chan_caller, chan_david, "David", NULL);
1493 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1495 /* Charlie is busy */
1496 ast_channel_publish_dial(chan_caller, chan_charlie, NULL, "BUSY");
1497 HANGUP_CHANNEL(chan_charlie, AST_CAUSE_BUSY);
1499 /* David is congested */
1500 ast_channel_publish_dial(chan_caller, chan_david, NULL, "CONGESTION");
1501 HANGUP_CHANNEL(chan_david, AST_CAUSE_CONGESTION);
1503 /* Bob is canceled */
1504 ast_channel_publish_dial(chan_caller, chan_bob, NULL, "CANCEL");
1505 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
1507 /* Alice hangs up */
1508 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1510 result = verify_mock_cdr_record(test, expected, 3);
1515 AST_TEST_DEFINE(test_cdr_dial_answer_no_bridge)
1517 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1518 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1519 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1522 struct ast_party_caller caller = ALICE_CALLERID;
1523 struct ast_cdr bob_expected_one = {
1527 .dcontext = "default",
1528 .channel = CHANNEL_TECH_NAME "/Bob",
1531 .amaflags = AST_AMA_DOCUMENTATION,
1532 .disposition = AST_CDR_ANSWERED,
1533 .accountcode = "200",
1535 struct ast_cdr alice_expected_two = {
1536 .clid = "\"Alice\" <100>",
1539 .dcontext = "default",
1540 .channel = CHANNEL_TECH_NAME "/Alice",
1543 .amaflags = AST_AMA_DOCUMENTATION,
1544 .disposition = AST_CDR_ANSWERED,
1545 .accountcode = "100",
1546 .next = &bob_expected_one,
1548 struct ast_cdr alice_expected_one = {
1549 .clid = "\"Alice\" <100>",
1552 .dcontext = "default",
1553 .channel = CHANNEL_TECH_NAME "/Alice",
1554 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1556 .lastdata = CHANNEL_TECH_NAME "/Bob",
1557 .amaflags = AST_AMA_DOCUMENTATION,
1558 .disposition = AST_CDR_ANSWERED,
1559 .accountcode = "100",
1560 .peeraccount = "200",
1561 .next = &alice_expected_two,
1563 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1567 info->name = __func__;
1568 info->category = TEST_CATEGORY;
1569 info->summary = "Test dialing, answering, and not going into a bridge.";
1571 "This is a weird one, but theoretically possible. You can perform\n"
1572 "a dial, then bounce both channels to different priorities and\n"
1573 "never have them enter a bridge together. Ew. This makes sure that\n"
1574 "when we answer, we get a CDR, it gets ended at that point, and\n"
1575 "that it gets finalized appropriately. We should get three CDRs in\n"
1576 "the end - one for the dial, and one for each CDR as they continued\n"
1578 return AST_TEST_NOT_RUN;
1583 SWAP_CONFIG(config, debug_cdr_config);
1585 CREATE_ALICE_CHANNEL(chan_caller, &caller, &alice_expected_one);
1586 COPY_IDS(chan_caller, &alice_expected_two);
1588 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1590 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1591 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1592 COPY_IDS(chan_callee, &bob_expected_one);
1594 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1595 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1596 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "ANSWER");
1598 ast_channel_state_set(chan_caller, AST_STATE_UP);
1599 ast_clear_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1600 ast_channel_state_set(chan_callee, AST_STATE_UP);
1602 EMULATE_APP_DATA(chan_caller, 2, "Wait", "1");
1603 EMULATE_APP_DATA(chan_callee, 1, "Wait", "1");
1605 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1606 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1608 result = verify_mock_cdr_record(test, &alice_expected_one, 3);
1612 AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_a)
1614 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1615 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1616 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1617 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1619 struct timespec to_sleep = {1, 0};
1620 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1622 struct ast_party_caller caller = ALICE_CALLERID;
1623 struct ast_cdr expected = {
1624 .clid = "\"Alice\" <100>",
1627 .dcontext = "default",
1628 .channel = CHANNEL_TECH_NAME "/Alice",
1629 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1631 .lastdata = CHANNEL_TECH_NAME "/Bob",
1632 .amaflags = AST_AMA_DOCUMENTATION,
1634 .disposition = AST_CDR_ANSWERED,
1635 .accountcode = "100",
1636 .peeraccount = "200",
1641 info->name = __func__;
1642 info->category = TEST_CATEGORY;
1643 info->summary = "Test dialing, answering, and going into a 2-party bridge";
1645 "The most 'basic' of scenarios\n";
1646 return AST_TEST_NOT_RUN;
1651 SWAP_CONFIG(config, debug_cdr_config);
1653 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1655 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1657 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1658 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1659 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1661 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1662 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1663 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "ANSWER");
1665 ast_channel_state_set(chan_caller, AST_STATE_UP);
1666 ast_channel_state_set(chan_callee, AST_STATE_UP);
1668 bridge = ast_bridge_basic_new();
1669 ast_test_validate(test, bridge != NULL);
1670 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1672 ast_bridge_impart(bridge, chan_caller, NULL, NULL, 0);
1673 ast_bridge_impart(bridge, chan_callee, NULL, NULL, 0);
1675 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1677 ast_bridge_depart(chan_caller);
1678 ast_bridge_depart(chan_callee);
1680 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1681 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1683 result = verify_mock_cdr_record(test, &expected, 1);
1687 AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_b)
1689 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1690 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1691 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1692 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1694 struct timespec to_sleep = {1, 0};
1695 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1697 struct ast_party_caller caller = ALICE_CALLERID;
1698 struct ast_cdr expected = {
1699 .clid = "\"Alice\" <100>",
1702 .dcontext = "default",
1703 .channel = CHANNEL_TECH_NAME "/Alice",
1704 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1706 .lastdata = CHANNEL_TECH_NAME "/Bob",
1707 .amaflags = AST_AMA_DOCUMENTATION,
1709 .disposition = AST_CDR_ANSWERED,
1710 .accountcode = "100",
1711 .peeraccount = "200",
1716 info->name = __func__;
1717 info->category = TEST_CATEGORY;
1718 info->summary = "Test dialing, answering, and going into a 2-party bridge";
1720 "The most 'basic' of scenarios\n";
1721 return AST_TEST_NOT_RUN;
1726 SWAP_CONFIG(config, debug_cdr_config);
1728 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1730 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1732 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_caller), 0, CHANNEL_TECH_NAME "/Bob");
1733 ast_set_flag(ast_channel_flags(chan_callee), AST_FLAG_OUTGOING);
1734 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1736 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1737 ast_channel_state_set(chan_caller, AST_STATE_RINGING);
1738 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "ANSWER");
1740 ast_channel_state_set(chan_caller, AST_STATE_UP);
1741 ast_channel_state_set(chan_callee, AST_STATE_UP);
1743 bridge = ast_bridge_basic_new();
1744 ast_test_validate(test, bridge != NULL);
1745 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1746 ast_bridge_impart(bridge, chan_callee, NULL, NULL, 0);
1747 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1748 ast_bridge_impart(bridge, chan_caller, NULL, NULL, 0);
1749 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1750 ast_bridge_depart(chan_caller);
1751 ast_bridge_depart(chan_callee);
1753 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1754 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1756 result = verify_mock_cdr_record(test, &expected, 1);
1760 AST_TEST_DEFINE(test_cdr_dial_answer_multiparty)
1762 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
1763 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
1764 RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
1765 RAII_VAR(struct ast_channel *, chan_david, NULL, safe_channel_release);
1766 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1767 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1769 struct timespec to_sleep = {1, 0};
1770 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1772 struct ast_party_caller alice_caller = ALICE_CALLERID;
1773 struct ast_party_caller charlie_caller = CHARLIE_CALLERID;
1774 struct ast_cdr charlie_expected_two = {
1775 .clid = "\"Charlie\" <300>",
1778 .dcontext = "default",
1779 .channel = CHANNEL_TECH_NAME "/Charlie",
1780 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1782 .lastdata = CHANNEL_TECH_NAME "/David",
1783 .amaflags = AST_AMA_DOCUMENTATION,
1785 .disposition = AST_CDR_ANSWERED,
1786 .accountcode = "300",
1787 .peeraccount = "200",
1789 struct ast_cdr charlie_expected_one = {
1790 .clid = "\"Charlie\" <300>",
1793 .dcontext = "default",
1794 .channel = CHANNEL_TECH_NAME "/Charlie",
1795 .dstchannel = CHANNEL_TECH_NAME "/David",
1797 .lastdata = CHANNEL_TECH_NAME "/David",
1798 .amaflags = AST_AMA_DOCUMENTATION,
1800 .disposition = AST_CDR_ANSWERED,
1801 .accountcode = "300",
1802 .peeraccount = "400",
1803 .next = &charlie_expected_two,
1805 struct ast_cdr alice_expected_three = {
1806 .clid = "\"Alice\" <100>",
1809 .dcontext = "default",
1810 .channel = CHANNEL_TECH_NAME "/Alice",
1811 .dstchannel = CHANNEL_TECH_NAME "/David",
1813 .lastdata = CHANNEL_TECH_NAME "/Bob",
1814 .amaflags = AST_AMA_DOCUMENTATION,
1816 .disposition = AST_CDR_ANSWERED,
1817 .accountcode = "100",
1818 .peeraccount = "400",
1819 .next = &charlie_expected_one,
1821 struct ast_cdr alice_expected_two = {
1822 .clid = "\"Alice\" <100>",
1825 .dcontext = "default",
1826 .channel = CHANNEL_TECH_NAME "/Alice",
1827 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1829 .lastdata = CHANNEL_TECH_NAME "/Bob",
1830 .amaflags = AST_AMA_DOCUMENTATION,
1832 .disposition = AST_CDR_ANSWERED,
1833 .accountcode = "100",
1834 .peeraccount = "300",
1835 .next = &alice_expected_three,
1837 struct ast_cdr alice_expected_one = {
1838 .clid = "\"Alice\" <100>",
1841 .dcontext = "default",
1842 .channel = CHANNEL_TECH_NAME "/Alice",
1843 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1845 .lastdata = CHANNEL_TECH_NAME "/Bob",
1846 .amaflags = AST_AMA_DOCUMENTATION,
1848 .disposition = AST_CDR_ANSWERED,
1849 .accountcode = "100",
1850 .peeraccount = "200",
1851 .next = &alice_expected_two,
1856 info->name = __func__;
1857 info->category = TEST_CATEGORY;
1858 info->summary = "Test dialing, answering, and going into a multi-party bridge";
1860 "A little tricky to get to do, but possible with some redirects.\n";
1861 return AST_TEST_NOT_RUN;
1866 SWAP_CONFIG(config, debug_cdr_config);
1868 CREATE_ALICE_CHANNEL(chan_alice, &alice_caller, &alice_expected_one);
1869 COPY_IDS(chan_alice, &alice_expected_two);
1870 COPY_IDS(chan_alice, &alice_expected_three);
1872 EMULATE_APP_DATA(chan_alice, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1874 chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, 0, CHANNEL_TECH_NAME "/Bob");
1875 ast_set_flag(ast_channel_flags(chan_bob), AST_FLAG_OUTGOING);
1876 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
1878 CREATE_CHARLIE_CHANNEL(chan_charlie, &charlie_caller, &charlie_expected_one);
1879 EMULATE_APP_DATA(chan_charlie, 1, "Dial", CHANNEL_TECH_NAME "/David");
1880 ast_copy_string(charlie_expected_one.uniqueid, ast_channel_uniqueid(chan_charlie), sizeof(charlie_expected_one.uniqueid));
1881 ast_copy_string(charlie_expected_one.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected_one.linkedid));
1882 ast_copy_string(charlie_expected_two.uniqueid, ast_channel_uniqueid(chan_charlie), sizeof(charlie_expected_two.uniqueid));
1883 ast_copy_string(charlie_expected_two.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected_two.linkedid));
1885 chan_david = ast_channel_alloc(0, AST_STATE_DOWN, "400", "David", "400", "400", "default", NULL, 0, CHANNEL_TECH_NAME "/David");
1886 ast_set_flag(ast_channel_flags(chan_david), AST_FLAG_OUTGOING);
1887 EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");
1889 ast_channel_publish_dial(chan_alice, chan_bob, "Bob", NULL);
1890 ast_channel_state_set(chan_alice, AST_STATE_RINGING);
1891 ast_channel_publish_dial(chan_charlie, chan_david, "David", NULL);
1892 ast_channel_state_set(chan_charlie, AST_STATE_RINGING);
1893 ast_channel_publish_dial(chan_alice, chan_bob, NULL, "ANSWER");
1894 ast_channel_publish_dial(chan_charlie, chan_david, NULL, "ANSWER");
1896 ast_channel_state_set(chan_alice, AST_STATE_UP);
1897 ast_channel_state_set(chan_bob, AST_STATE_UP);
1898 ast_channel_state_set(chan_charlie, AST_STATE_UP);
1899 ast_channel_state_set(chan_david, AST_STATE_UP);
1901 bridge = ast_bridge_basic_new();
1902 ast_test_validate(test, bridge != NULL);
1904 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1905 ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_charlie, NULL, NULL, 0));
1906 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1907 ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_david, NULL, NULL, 0));
1908 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1909 ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0));
1910 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1911 ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0));
1912 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1913 ast_test_validate(test, 0 == ast_bridge_depart(chan_alice));
1914 ast_test_validate(test, 0 == ast_bridge_depart(chan_bob));
1915 ast_test_validate(test, 0 == ast_bridge_depart(chan_charlie));
1916 ast_test_validate(test, 0 == ast_bridge_depart(chan_david));
1918 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
1919 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
1920 HANGUP_CHANNEL(chan_charlie, AST_CAUSE_NORMAL);
1921 HANGUP_CHANNEL(chan_david, AST_CAUSE_NORMAL);
1923 result = verify_mock_cdr_record(test, &alice_expected_one, 5);
1928 AST_TEST_DEFINE(test_cdr_park)
1930 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
1931 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
1932 RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
1933 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1935 struct timespec to_sleep = {1, 0};
1937 struct ast_party_caller bob_caller = BOB_CALLERID;
1938 struct ast_party_caller alice_caller = ALICE_CALLERID;
1939 struct ast_cdr bob_expected = {
1940 .clid = "\"Bob\" <200>",
1943 .dcontext = "default",
1944 .channel = CHANNEL_TECH_NAME "/Bob",
1948 .amaflags = AST_AMA_DOCUMENTATION,
1949 .disposition = AST_CDR_ANSWERED,
1950 .accountcode = "200",
1952 struct ast_cdr alice_expected = {
1953 .clid = "\"Alice\" <100>",
1956 .dcontext = "default",
1957 .channel = CHANNEL_TECH_NAME "/Alice",
1961 .amaflags = AST_AMA_DOCUMENTATION,
1962 .disposition = AST_CDR_ANSWERED,
1963 .accountcode = "100",
1964 .next = &bob_expected,
1966 enum ast_test_result_state result = AST_TEST_NOT_RUN;
1970 info->name = __func__;
1971 info->category = TEST_CATEGORY;
1972 info->summary = "Test cdrs for a single party entering Park";
1974 "Test the properties of a CDR for calls that are\n"
1975 "answered, enters Park, and leaves it.\n";
1976 return AST_TEST_NOT_RUN;
1980 SWAP_CONFIG(config, debug_cdr_config);
1981 CREATE_ALICE_CHANNEL(chan_alice, &alice_caller, &alice_expected);
1982 CREATE_BOB_CHANNEL(chan_bob, &bob_caller, &bob_expected);
1984 EMULATE_APP_DATA(chan_alice, 1, "Park", "700");
1985 ast_setstate(chan_alice, AST_STATE_UP);
1986 EMULATE_APP_DATA(chan_bob, 1, "Park", "701");
1987 ast_setstate(chan_bob, AST_STATE_UP);
1989 bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING,
1990 AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
1991 | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
1992 ast_test_validate(test, bridge != NULL);
1994 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1995 ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0);
1996 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1997 ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0);
1998 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
1999 ast_bridge_depart(chan_alice);
2000 ast_bridge_depart(chan_bob);
2002 /* And then it hangs up */
2003 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
2004 HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL);
2006 result = verify_mock_cdr_record(test, &alice_expected, 2);
2012 AST_TEST_DEFINE(test_cdr_fields)
2014 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
2015 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
2017 char varbuffer[128];
2020 struct timespec to_sleep = {2, 0};
2021 struct ast_flags fork_options = { 0, };
2023 struct ast_party_caller caller = ALICE_CALLERID;
2024 struct ast_cdr original = {
2025 .clid = "\"Alice\" <100>",
2028 .dcontext = "default",
2029 .channel = CHANNEL_TECH_NAME "/Alice",
2033 .amaflags = AST_AMA_OMIT,
2034 .disposition = AST_CDR_FAILED,
2035 .accountcode = "XXX",
2036 .userfield = "yackity",
2038 struct ast_cdr fork_expected_one = {
2039 .clid = "\"Alice\" <100>",
2042 .dcontext = "default",
2043 .channel = CHANNEL_TECH_NAME "/Alice",
2047 .amaflags = AST_AMA_OMIT,
2048 .disposition = AST_CDR_FAILED,
2049 .accountcode = "XXX",
2050 .userfield = "yackity",
2052 struct ast_cdr fork_expected_two = {
2053 .clid = "\"Alice\" <100>",
2056 .dcontext = "default",
2057 .channel = CHANNEL_TECH_NAME "/Alice",
2058 .lastapp = "Answer",
2060 .amaflags = AST_AMA_OMIT,
2061 .disposition = AST_CDR_ANSWERED,
2062 .accountcode = "ZZZ",
2063 .userfield = "schmackity",
2065 enum ast_test_result_state result = AST_TEST_NOT_RUN;
2067 struct ast_cdr *expected = &original;
2068 original.next = &fork_expected_one;
2069 fork_expected_one.next = &fork_expected_two;
2073 info->name = __func__;
2074 info->category = TEST_CATEGORY;
2075 info->summary = "Test field access CDRs";
2077 "This tests setting/retrieving data on CDR records.\n";
2078 return AST_TEST_NOT_RUN;
2083 SWAP_CONFIG(config, unanswered_cdr_config);
2085 CREATE_ALICE_CHANNEL(chan, &caller, &original);
2086 ast_copy_string(fork_expected_one.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_one.uniqueid));
2087 ast_copy_string(fork_expected_one.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_one.linkedid));
2088 ast_copy_string(fork_expected_two.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_two.uniqueid));
2089 ast_copy_string(fork_expected_two.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_two.linkedid));
2091 /* Channel enters Wait app */
2092 ast_channel_appl_set(chan, "Wait");
2093 ast_channel_data_set(chan, "10");
2094 ast_channel_priority_set(chan, 1);
2095 ast_channel_publish_snapshot(chan);
2097 /* Set properties on the channel that propagate to the CDR */
2098 ast_channel_amaflags_set(chan, AST_AMA_OMIT);
2099 ast_channel_accountcode_set(chan, "XXX");
2101 /* Wait one second so we get a duration. */
2102 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
2104 ast_cdr_setuserfield(ast_channel_name(chan), "foobar");
2105 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_1") == 0);
2107 /* Verify that we can't set read-only fields or other fields directly */
2108 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "clid", "junk") != 0);
2109 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "src", "junk") != 0);
2110 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "dst", "junk") != 0);
2111 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "dcontext", "junk") != 0);
2112 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "channel", "junk") != 0);
2113 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "dstchannel", "junk") != 0);
2114 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "lastapp", "junk") != 0);
2115 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "lastdata", "junk") != 0);
2116 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "start", "junk") != 0);
2117 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "answer", "junk") != 0);
2118 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "end", "junk") != 0);
2119 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "duration", "junk") != 0);
2120 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "billsec", "junk") != 0);
2121 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "disposition", "junk") != 0);
2122 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "amaflags", "junk") != 0);
2123 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "accountcode", "junk") != 0);
2124 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "uniqueid", "junk") != 0);
2125 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "linkedid", "junk") != 0);
2126 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "userfield", "junk") != 0);
2127 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "sequence", "junk") != 0);
2129 /* Verify the values */
2130 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "userfield", varbuffer, sizeof(varbuffer)) == 0);
2131 ast_test_validate(test, strcmp(varbuffer, "foobar") == 0);
2132 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
2133 ast_test_validate(test, strcmp(varbuffer, "record_1") == 0);
2134 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "amaflags", varbuffer, sizeof(varbuffer)) == 0);
2135 sscanf(varbuffer, "%d", &int_buffer);
2136 ast_test_validate(test, int_buffer == AST_AMA_OMIT);
2137 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "accountcode", varbuffer, sizeof(varbuffer)) == 0);
2138 ast_test_validate(test, strcmp(varbuffer, "XXX") == 0);
2139 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "clid", varbuffer, sizeof(varbuffer)) == 0);
2140 ast_test_validate(test, strcmp(varbuffer, "\"Alice\" <100>") == 0);
2141 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "src", varbuffer, sizeof(varbuffer)) == 0);
2142 ast_test_validate(test, strcmp(varbuffer, "100") == 0);
2143 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dst", varbuffer, sizeof(varbuffer)) == 0);
2144 ast_test_validate(test, strcmp(varbuffer, "100") == 0);
2145 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dcontext", varbuffer, sizeof(varbuffer)) == 0);
2146 ast_test_validate(test, strcmp(varbuffer, "default") == 0);
2147 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "channel", varbuffer, sizeof(varbuffer)) == 0);
2148 ast_test_validate(test, strcmp(varbuffer, CHANNEL_TECH_NAME "/Alice") == 0);
2149 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dstchannel", varbuffer, sizeof(varbuffer)) == 0);
2150 ast_test_validate(test, strcmp(varbuffer, "") == 0);
2151 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "lastapp", varbuffer, sizeof(varbuffer)) == 0);
2152 ast_test_validate(test, strcmp(varbuffer, "Wait") == 0);
2153 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "lastdata", varbuffer, sizeof(varbuffer)) == 0);
2154 ast_test_validate(test, strcmp(varbuffer, "10") == 0);
2155 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", varbuffer, sizeof(varbuffer)) == 0);
2156 sscanf(varbuffer, "%lf", &db_buffer);
2157 ast_test_validate(test, fabs(db_buffer) > 0);
2158 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", varbuffer, sizeof(varbuffer)) == 0);
2159 sscanf(varbuffer, "%lf", &db_buffer);
2160 ast_test_validate(test, fabs(db_buffer) < EPSILON);
2161 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "end", varbuffer, sizeof(varbuffer)) == 0);
2162 sscanf(varbuffer, "%lf", &db_buffer);
2163 ast_test_validate(test, fabs(db_buffer) < EPSILON);
2164 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "duration", varbuffer, sizeof(varbuffer)) == 0);
2165 sscanf(varbuffer, "%lf", &db_buffer);
2166 ast_test_validate(test, fabs(db_buffer) > 0);
2167 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "billsec", varbuffer, sizeof(varbuffer)) == 0);
2168 sscanf(varbuffer, "%lf", &db_buffer);
2169 ast_test_validate(test, fabs(db_buffer) < EPSILON);
2170 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "disposition", varbuffer, sizeof(varbuffer)) == 0);
2171 sscanf(varbuffer, "%d", &int_buffer);
2172 ast_test_validate(test, int_buffer == AST_CDR_NULL);
2173 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "uniqueid", varbuffer, sizeof(varbuffer)) == 0);
2174 ast_test_validate(test, strcmp(varbuffer, ast_channel_uniqueid(chan)) == 0);
2175 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "linkedid", varbuffer, sizeof(varbuffer)) == 0);
2176 ast_test_validate(test, strcmp(varbuffer, ast_channel_linkedid(chan)) == 0);
2177 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "sequence", varbuffer, sizeof(varbuffer)) == 0);
2179 /* Fork the CDR, and check that we change the properties on both CDRs. */
2180 ast_set_flag(&fork_options, AST_CDR_FLAG_KEEP_VARS);
2181 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2183 /* Change some properties */
2184 ast_cdr_setuserfield(ast_channel_name(chan), "yackity");
2185 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_1b") == 0);
2187 /* Fork the CDR again, finalizing all current CDRs */
2188 ast_set_flag(&fork_options, AST_CDR_FLAG_KEEP_VARS | AST_CDR_FLAG_FINALIZE);
2189 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2191 /* Channel enters Answer app */
2192 ast_channel_appl_set(chan, "Answer");
2193 ast_channel_data_set(chan, "");
2194 ast_channel_priority_set(chan, 1);
2195 ast_channel_publish_snapshot(chan);
2196 ast_setstate(chan, AST_STATE_UP);
2198 /* Set properties on the last record */
2199 ast_channel_accountcode_set(chan, "ZZZ");
2200 ast_cdr_setuserfield(ast_channel_name(chan), "schmackity");
2201 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
2203 /* Hang up and verify */
2204 ast_channel_hangupcause_set(chan, AST_CAUSE_NORMAL);
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);
2277 result = verify_mock_cdr_record(test, &expected, 1);
2282 AST_TEST_DEFINE(test_cdr_fork_cdr)
2284 RAII_VAR(struct ast_channel *, chan, NULL, safe_channel_release);
2285 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
2287 char varbuffer[128];
2288 char fork_varbuffer[128];
2289 char answer_time[128];
2290 char fork_answer_time[128];
2291 char start_time[128];
2292 char fork_start_time[128];
2293 struct ast_flags fork_options = { 0, };
2294 struct timespec to_sleep = {1, 10000};
2296 struct ast_party_caller caller = ALICE_CALLERID;
2297 struct ast_cdr original = {
2298 .clid = "\"Alice\" <100>",
2301 .dcontext = "default",
2302 .channel = CHANNEL_TECH_NAME "/Alice",
2303 .amaflags = AST_AMA_DOCUMENTATION,
2304 .disposition = AST_CDR_ANSWERED,
2305 .accountcode = "100",
2307 struct ast_cdr fork_expected_one = {
2308 .clid = "\"Alice\" <100>",
2311 .dcontext = "default",
2312 .channel = CHANNEL_TECH_NAME "/Alice",
2313 .amaflags = AST_AMA_DOCUMENTATION,
2314 .disposition = AST_CDR_ANSWERED,
2315 .accountcode = "100",
2317 struct ast_cdr fork_expected_two = {
2318 .clid = "\"Alice\" <100>",
2321 .dcontext = "default",
2322 .channel = CHANNEL_TECH_NAME "/Alice",
2323 .amaflags = AST_AMA_DOCUMENTATION,
2324 .disposition = AST_CDR_ANSWERED,
2325 .accountcode = "100",
2327 enum ast_test_result_state result = AST_TEST_NOT_RUN;
2328 struct ast_cdr *expected = &original;
2329 original.next = &fork_expected_one;
2330 fork_expected_one.next = &fork_expected_two;
2334 info->name = __func__;
2335 info->category = TEST_CATEGORY;
2336 info->summary = "Test field access CDRs";
2338 "This tests setting/retrieving data on CDR records.\n";
2339 return AST_TEST_NOT_RUN;
2344 SWAP_CONFIG(config, debug_cdr_config);
2346 CREATE_ALICE_CHANNEL(chan, &caller, &original);
2347 ast_copy_string(fork_expected_one.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_one.uniqueid));
2348 ast_copy_string(fork_expected_one.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_one.linkedid));
2349 ast_copy_string(fork_expected_two.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_two.uniqueid));
2350 ast_copy_string(fork_expected_two.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_two.linkedid));
2352 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
2354 /* Test blowing away variables */
2355 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_1") == 0);
2356 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
2357 ast_test_validate(test, strcmp(varbuffer, "record_1") == 0);
2358 ast_copy_string(varbuffer, "", sizeof(varbuffer));
2360 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2361 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", fork_varbuffer, sizeof(fork_varbuffer)) == 0);
2362 ast_test_validate(test, strcmp(varbuffer, "record_1") != 0);
2364 /* Test finalizing previous CDRs */
2365 ast_set_flag(&fork_options, AST_CDR_FLAG_FINALIZE);
2366 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2368 /* Test keep variables; setting a new answer time */
2369 ast_setstate(chan, AST_STATE_UP);
2370 while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
2371 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
2372 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
2373 ast_test_validate(test, strcmp(varbuffer, "record_2") == 0);
2374 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", answer_time, sizeof(answer_time)) == 0);
2375 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", start_time, sizeof(start_time)) == 0);
2377 ast_set_flag(&fork_options, AST_CDR_FLAG_FINALIZE);
2378 ast_set_flag(&fork_options, AST_CDR_FLAG_KEEP_VARS);
2379 ast_set_flag(&fork_options, AST_CDR_FLAG_SET_ANSWER);
2380 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2381 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", fork_answer_time, sizeof(fork_answer_time)) == 0);
2382 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", fork_start_time, sizeof(fork_start_time)) == 0);
2383 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", fork_varbuffer, sizeof(fork_varbuffer)) == 0);
2384 ast_test_validate(test, strcmp(fork_varbuffer, varbuffer) == 0);
2385 ast_test_validate(test, strcmp(fork_start_time, start_time) == 0);
2386 ast_test_validate(test, strcmp(fork_answer_time, answer_time) != 0);
2388 ast_clear_flag(&fork_options, AST_CDR_FLAG_SET_ANSWER);
2389 ast_set_flag(&fork_options, AST_CDR_FLAG_RESET);
2390 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2391 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", fork_answer_time, sizeof(fork_answer_time)) == 0);
2392 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", fork_start_time, sizeof(fork_start_time)) == 0);
2393 ast_test_validate(test, strcmp(fork_start_time, start_time) != 0);
2394 ast_test_validate(test, strcmp(fork_answer_time, answer_time) != 0);
2396 ast_channel_hangupcause_set(chan, AST_CAUSE_NORMAL);
2399 result = verify_mock_cdr_record(test, expected, 3);
2405 * \internal \brief Callback function called before each test executes
2407 static int test_cdr_init_cb(struct ast_test_info *info, struct ast_test *test)
2409 /* Back up the real config */
2410 saved_config = ast_cdr_get_config();
2411 clear_mock_cdr_backend();
2416 * \internal \brief Callback function called after each test executes
2418 static int test_cdr_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
2420 /* Restore the real config */
2421 ast_cdr_set_config(saved_config);
2422 ao2_cleanup(saved_config);
2423 saved_config = NULL;
2424 clear_mock_cdr_backend();
2430 static int unload_module(void)
2432 AST_TEST_UNREGISTER(test_cdr_channel_creation);
2433 AST_TEST_UNREGISTER(test_cdr_unanswered_inbound_call);
2434 AST_TEST_UNREGISTER(test_cdr_unanswered_outbound_call);
2436 AST_TEST_UNREGISTER(test_cdr_single_party);
2437 AST_TEST_UNREGISTER(test_cdr_single_bridge);
2438 AST_TEST_UNREGISTER(test_cdr_single_bridge_continue);
2439 AST_TEST_UNREGISTER(test_cdr_single_twoparty_bridge_a);
2440 AST_TEST_UNREGISTER(test_cdr_single_twoparty_bridge_b);
2441 AST_TEST_UNREGISTER(test_cdr_single_multiparty_bridge);
2443 AST_TEST_UNREGISTER(test_cdr_outbound_bridged_call);
2445 AST_TEST_UNREGISTER(test_cdr_dial_unanswered);
2446 AST_TEST_UNREGISTER(test_cdr_dial_congestion);
2447 AST_TEST_UNREGISTER(test_cdr_dial_busy);
2448 AST_TEST_UNREGISTER(test_cdr_dial_unavailable);
2449 AST_TEST_UNREGISTER(test_cdr_dial_caller_cancel);
2450 AST_TEST_UNREGISTER(test_cdr_dial_parallel_failed);
2451 AST_TEST_UNREGISTER(test_cdr_dial_answer_no_bridge);
2452 AST_TEST_UNREGISTER(test_cdr_dial_answer_twoparty_bridge_a);
2453 AST_TEST_UNREGISTER(test_cdr_dial_answer_twoparty_bridge_b);
2454 AST_TEST_UNREGISTER(test_cdr_dial_answer_multiparty);
2456 AST_TEST_UNREGISTER(test_cdr_park);
2458 AST_TEST_UNREGISTER(test_cdr_fields);
2459 AST_TEST_UNREGISTER(test_cdr_no_reset_cdr);
2460 AST_TEST_UNREGISTER(test_cdr_fork_cdr);
2462 ast_cdr_unregister(MOCK_CDR_BACKEND);
2463 ast_channel_unregister(&test_cdr_chan_tech);
2464 clear_mock_cdr_backend();
2469 static int load_module(void)
2471 ast_cond_init(&mock_cdr_cond, NULL);
2473 AST_TEST_REGISTER(test_cdr_channel_creation);
2474 AST_TEST_REGISTER(test_cdr_unanswered_inbound_call);
2475 AST_TEST_REGISTER(test_cdr_unanswered_outbound_call);
2477 AST_TEST_REGISTER(test_cdr_single_party);
2478 AST_TEST_REGISTER(test_cdr_single_bridge);
2479 AST_TEST_REGISTER(test_cdr_single_bridge_continue);
2480 AST_TEST_REGISTER(test_cdr_single_twoparty_bridge_a);
2481 AST_TEST_REGISTER(test_cdr_single_twoparty_bridge_b);
2482 AST_TEST_REGISTER(test_cdr_single_multiparty_bridge);
2484 AST_TEST_REGISTER(test_cdr_outbound_bridged_call);
2486 AST_TEST_REGISTER(test_cdr_dial_unanswered);
2487 AST_TEST_REGISTER(test_cdr_dial_congestion);
2488 AST_TEST_REGISTER(test_cdr_dial_busy);
2489 AST_TEST_REGISTER(test_cdr_dial_unavailable);
2490 AST_TEST_REGISTER(test_cdr_dial_caller_cancel);
2491 AST_TEST_REGISTER(test_cdr_dial_parallel_failed);
2492 AST_TEST_REGISTER(test_cdr_dial_answer_no_bridge);
2493 AST_TEST_REGISTER(test_cdr_dial_answer_twoparty_bridge_a);
2494 AST_TEST_REGISTER(test_cdr_dial_answer_twoparty_bridge_b);
2495 AST_TEST_REGISTER(test_cdr_dial_answer_multiparty);
2497 AST_TEST_REGISTER(test_cdr_park);
2499 AST_TEST_REGISTER(test_cdr_fields);
2500 AST_TEST_REGISTER(test_cdr_no_reset_cdr);
2501 AST_TEST_REGISTER(test_cdr_fork_cdr);
2503 ast_test_register_init(TEST_CATEGORY, test_cdr_init_cb);
2504 ast_test_register_cleanup(TEST_CATEGORY, test_cdr_cleanup_cb);
2506 ast_channel_register(&test_cdr_chan_tech);
2507 ast_cdr_register(MOCK_CDR_BACKEND, "Mock CDR backend", mock_cdr_backend_cb);
2509 return AST_MODULE_LOAD_SUCCESS;
2512 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "CDR unit tests");