Asterisk - The Open Source Telephony Project GIT-master-a358458
test_cdr.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Matt Jordan <mjordan@digium.com>
7 *
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.
13 *
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.
17 */
18
19/*!
20 * \file
21 * \brief CDR unit tests
22 *
23 * \author Matt Jordan <mjordan@digium.com>
24 *
25 */
26
27/*** MODULEINFO
28 <depend>TEST_FRAMEWORK</depend>
29 <support_level>core</support_level>
30 ***/
31
32#include "asterisk.h"
33
34#include <math.h>
35#include "asterisk/module.h"
36#include "asterisk/test.h"
37#include "asterisk/cdr.h"
39#include "asterisk/chanvars.h"
40#include "asterisk/utils.h"
41#include "asterisk/causes.h"
42#include "asterisk/time.h"
43#include "asterisk/bridge.h"
48
49#define EPSILON 0.001
50
51#define TEST_CATEGORY "/main/cdr/"
52
53#define MOCK_CDR_BACKEND "mock_cdr_backend"
54
55#define CHANNEL_TECH_NAME "CDRTestChannel"
56
57/*! \brief A placeholder for Asterisk's 'real' CDR configuration */
59
60/*! \brief A configuration suitable for 'normal' CDRs */
63};
64
65/*! \brief A configuration suitable for CDRs with unanswered records */
68};
69
70/*! \brief A configuration suitable for CDRs with congestion enabled */
73};
74
75/*! \brief Macro to swap a configuration out from the CDR engine. This should be
76 * used at the beginning of each test to set the needed configuration for that
77 * test.
78 */
79#define SWAP_CONFIG(ao2_config, template) do { \
80 *(ao2_config) = (template); \
81 ast_cdr_set_config((ao2_config)); \
82 } while (0)
83
84/*! \brief A linked list of received CDR entries from the engine */
86
87/*! \brief The Mock CDR backend condition wait */
89
90/*! \brief A channel technology used for the unit tests */
93 .description = "Mock channel technology for CDR tests",
94};
95
97 struct ast_cdr *cdr;
99};
100
101/*! \brief The number of CDRs the mock backend has received */
103
104/*! \internal
105 * \brief Callback function for the mock CDR backend
106 *
107 * This function 'processes' a dispatched CDR record by adding it to the
108 * \ref actual_cdr_entries list. When a test completes, it can verify the
109 * expected records against this list of actual CDRs created by the engine.
110 *
111 * \param cdr The public CDR object created by the engine
112 *
113 * \retval -1 on error
114 * \retval 0 on success
115 */
116static int mock_cdr_backend_cb(struct ast_cdr *cdr)
117{
118 struct ast_cdr *cdr_copy, *cdr_prev = NULL;
119 struct ast_cdr *mock_cdr = NULL;
120 struct test_cdr_entry *cdr_wrapper;
121
122 cdr_wrapper = ast_calloc(1, sizeof(*cdr_wrapper));
123 if (!cdr_wrapper) {
124 return -1;
125 }
126
127 for (; cdr; cdr = cdr->next) {
128 struct ast_var_t *var_entry, *var_copy;
129
130 cdr_copy = ast_calloc(1, sizeof(*cdr_copy));
131 if (!cdr_copy) {
132 return -1;
133 }
134 *cdr_copy = *cdr;
135 cdr_copy->varshead.first = NULL;
136 cdr_copy->varshead.last = NULL;
137 cdr_copy->next = NULL;
138
139 AST_LIST_TRAVERSE(&cdr->varshead, var_entry, entries) {
140 var_copy = ast_var_assign(var_entry->name, var_entry->value);
141 if (!var_copy) {
142 return -1;
143 }
144 AST_LIST_INSERT_TAIL(&cdr_copy->varshead, var_copy, entries);
145 }
146
147 if (!mock_cdr) {
148 mock_cdr = cdr_copy;
149 }
150 if (cdr_prev) {
151 cdr_prev->next = cdr_copy;
152 }
153 cdr_prev = cdr_copy;
154 }
155 cdr_wrapper->cdr = mock_cdr;
156
158 AST_LIST_INSERT_TAIL(&actual_cdr_entries, cdr_wrapper, list);
162
163 return 0;
164}
165
166/*! \internal
167 * \brief Remove all entries from \ref actual_cdr_entries
168 */
169static void clear_mock_cdr_backend(void)
170{
171 struct test_cdr_entry *cdr_wrapper;
172
174 while ((cdr_wrapper = AST_LIST_REMOVE_HEAD(&actual_cdr_entries, list))) {
175 ast_cdr_free(cdr_wrapper->cdr);
176 ast_free(cdr_wrapper);
177 }
180}
181
182/*! \brief Verify a string field. This will set the test status result to fail;
183 * as such, it assumes that (a) test is the test object variable, and (b) that
184 * a return variable res exists.
185 */
186#define VERIFY_STRING_FIELD(field, actual, expected) do { \
187 if (strcmp((actual)->field, (expected)->field)) { \
188 ast_test_status_update(test, "Field %s failed: actual %s, expected %s\n", #field, (actual)->field, (expected)->field); \
189 ast_test_set_result(test, AST_TEST_FAIL); \
190 res = AST_TEST_FAIL; \
191 } } while (0)
192
193/*! \brief Verify a numeric field. This will set the test status result to fail;
194 * as such, it assumes that (a) test is the test object variable, and (b) that
195 * a return variable res exists.
196 */
197#define VERIFY_NUMERIC_FIELD(field, actual, expected) do { \
198 if ((actual)->field != (expected)->field) { \
199 ast_test_status_update(test, "Field %s failed: actual %ld, expected %ld\n", #field, (long)(actual)->field, (long)(expected)->field); \
200 ast_test_set_result(test, AST_TEST_FAIL); \
201 res = AST_TEST_FAIL; \
202 } } while (0)
203
204/*! \brief Verify a time field. This will set the test status result to fail;
205 * as such, it assumes that (a) test is the test object variable, and (b) that
206 * a return variable res exists.
207 */
208#define VERIFY_TIME_VALUE(field, actual) do { \
209 if (ast_tvzero((actual)->field)) { \
210 ast_test_status_update(test, "Field %s failed: should not be 0\n", #field); \
211 ast_test_set_result(test, AST_TEST_FAIL); \
212 res = AST_TEST_FAIL; \
213 } } while (0)
214
215/*! \brief Alice's Caller ID */
216#define ALICE_CALLERID { .id.name.str = "Alice", .id.name.valid = 1, .id.number.str = "100", .id.number.valid = 1, }
217
218/*! \brief Bob's Caller ID */
219#define BOB_CALLERID { .id.name.str = "Bob", .id.name.valid = 1, .id.number.str = "200", .id.number.valid = 1, }
220
221/*! \brief Charlie's Caller ID */
222#define CHARLIE_CALLERID { .id.name.str = "Charlie", .id.name.valid = 1, .id.number.str = "300", .id.number.valid = 1, }
223
224/*! \brief David's Caller ID */
225#define DAVID_CALLERID { .id.name.str = "David", .id.name.valid = 1, .id.number.str = "400", .id.number.valid = 1, }
226
227/*! \brief Copy the linkedid and uniqueid from a channel to an expected CDR */
228#define COPY_IDS(channel_var, expected_record) do { \
229 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
230 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
231 } while (0)
232
233/*! \brief Set ulaw format on channel */
234#define SET_FORMATS(chan) do {\
235 struct ast_format_cap *caps;\
236 caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);\
237 ast_format_cap_append(caps, ast_format_ulaw, 0);\
238 ast_channel_nativeformats_set((chan), caps);\
239 ast_channel_set_writeformat((chan), ast_format_ulaw);\
240 ast_channel_set_rawwriteformat((chan), ast_format_ulaw);\
241 ast_channel_set_readformat((chan), ast_format_ulaw);\
242 ast_channel_set_rawreadformat((chan), ast_format_ulaw);\
243 ao2_ref(caps, -1);\
244} while (0)
245
246/*! \brief Create a \ref test_cdr_chan_tech for Alice, and set the expected
247 * CDR records' linkedid and uniqueid. */
248#define CREATE_ALICE_CHANNEL(channel_var, caller_id, expected_record) do { \
249 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, "100", "Alice", "100", "100", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Alice"); \
250 SET_FORMATS((channel_var));\
251 ast_channel_set_caller((channel_var), (caller_id), NULL); \
252 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
253 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
254 ast_channel_unlock((channel_var)); \
255 } while (0)
256
257/*! \brief Create a \ref test_cdr_chan_tech for Bob, and set the expected
258 * CDR records' linkedid and uniqueid. */
259#define CREATE_BOB_CHANNEL(channel_var, caller_id, expected_record) do { \
260 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Bob"); \
261 SET_FORMATS((channel_var));\
262 ast_channel_set_caller((channel_var), (caller_id), NULL); \
263 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
264 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
265 ast_channel_unlock((channel_var)); \
266 } while (0)
267
268/*! \brief Create a \ref test_cdr_chan_tech for Charlie, and set the expected
269 * CDR records' linkedid and uniqueid. */
270#define CREATE_CHARLIE_CHANNEL(channel_var, caller_id, expected_record) do { \
271 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, "300", "Charlie", "300", "300", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Charlie"); \
272 SET_FORMATS((channel_var));\
273 ast_channel_set_caller((channel_var), (caller_id), NULL); \
274 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
275 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
276 ast_channel_unlock((channel_var)); \
277 } while (0)
278
279/*! \brief Create a \ref test_cdr_chan_tech for Charlie, and set the expected
280 * CDR records' linkedid and uniqueid. */
281#define CREATE_DAVID_CHANNEL(channel_var, caller_id, expected_record) do { \
282 (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, "400", "David", "400", "400", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/David"); \
283 SET_FORMATS((channel_var));\
284 ast_channel_set_caller((channel_var), (caller_id), NULL); \
285 ast_copy_string((expected_record)->uniqueid, ast_channel_uniqueid((channel_var)), sizeof((expected_record)->uniqueid)); \
286 ast_copy_string((expected_record)->linkedid, ast_channel_linkedid((channel_var)), sizeof((expected_record)->linkedid)); \
287 ast_channel_unlock((channel_var)); \
288 } while (0)
289
290/*! \brief Emulate a channel entering into an application */
291#define EMULATE_APP_DATA(channel, priority, application, data) do { \
292 if ((priority) > 0) { \
293 ast_channel_priority_set((channel), (priority)); \
294 } \
295 ast_channel_lock((channel)); \
296 ast_channel_appl_set((channel), (application)); \
297 ast_channel_data_set((channel), (data)); \
298 ast_channel_publish_snapshot((channel)); \
299 ast_channel_unlock((channel)); \
300 } while (0)
301
302/*! \brief Hang up a test channel safely */
303#define HANGUP_CHANNEL(channel, cause) \
304 do { \
305 ast_channel_hangupcause_set((channel), (cause)); \
306 ast_hangup(channel); \
307 channel = NULL; \
308 } while (0)
309
310static enum ast_test_result_state verify_mock_cdr_record(struct ast_test *test, struct ast_cdr *expected, int record)
311{
312 struct ast_cdr *actual = NULL;
313 struct test_cdr_entry *cdr_wrapper;
314 int count = 0;
315 struct timeval wait_now = ast_tvnow();
316 struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 5, .tv_nsec = wait_now.tv_usec * 1000 };
318
319 while (count < record) {
321 if (global_mock_cdr_count < record) {
323 }
324 cdr_wrapper = AST_LIST_REMOVE_HEAD(&actual_cdr_entries, list);
326
327 if (!cdr_wrapper) {
328 ast_test_status_update(test, "Unable to find actual CDR record at %d\n", count);
329 return AST_TEST_FAIL;
330 }
331 actual = cdr_wrapper->cdr;
332
333 if (!expected && actual) {
334 ast_test_status_update(test, "CDRs recorded where no record expected\n");
335 return AST_TEST_FAIL;
336 }
337 ast_test_debug(test, "Verifying expected record %s, %s\n",
338 expected->channel, S_OR(expected->dstchannel, "<none>"));
339 VERIFY_STRING_FIELD(accountcode, actual, expected);
340 VERIFY_NUMERIC_FIELD(amaflags, actual, expected);
341 VERIFY_STRING_FIELD(channel, actual, expected);
342 VERIFY_STRING_FIELD(clid, actual, expected);
343 VERIFY_STRING_FIELD(dcontext, actual, expected);
344 VERIFY_NUMERIC_FIELD(disposition, actual, expected);
345 VERIFY_STRING_FIELD(dst, actual, expected);
346 VERIFY_STRING_FIELD(dstchannel, actual, expected);
347 VERIFY_STRING_FIELD(lastapp, actual, expected);
348 VERIFY_STRING_FIELD(lastdata, actual, expected);
349 VERIFY_STRING_FIELD(linkedid, actual, expected);
350 VERIFY_STRING_FIELD(peeraccount, actual, expected);
351 VERIFY_STRING_FIELD(src, actual, expected);
352 VERIFY_STRING_FIELD(uniqueid, actual, expected);
353 VERIFY_STRING_FIELD(userfield, actual, expected);
354 VERIFY_TIME_VALUE(start, actual);
355 VERIFY_TIME_VALUE(end, actual);
356 /* Note: there's no way we can really calculate a duration or
357 * billsec - the unit tests are too short. However, if billsec is
358 * non-zero in the expected, then make sure we have an answer time
359 */
360 if (expected->billsec) {
361 VERIFY_TIME_VALUE(answer, actual);
362 }
363 ast_test_debug(test, "Finished expected record %s, %s\n",
364 expected->channel, S_OR(expected->dstchannel, "<none>"));
365 expected = expected->next;
366 ++count;
367 }
368 return res;
369}
370
371static void safe_channel_release(struct ast_channel *chan)
372{
373 if (!chan) {
374 return;
375 }
377}
378
379static void safe_bridge_destroy(struct ast_bridge *bridge)
380{
381 if (!bridge) {
382 return;
383 }
384 ast_bridge_destroy(bridge, 0);
385}
386
387static void do_sleep(struct timespec *to_sleep)
388{
389 while ((nanosleep(to_sleep, to_sleep) == -1) && (errno == EINTR)) {
390 }
391}
392
393AST_TEST_DEFINE(test_cdr_channel_creation)
394{
396 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
398
399 struct ast_party_caller caller = ALICE_CALLERID;
400 struct ast_cdr expected = {
401 .clid = "\"Alice\" <100>",
402 .src = "100",
403 .dst = "100",
404 .dcontext = "default",
405 .channel = CHANNEL_TECH_NAME "/Alice",
406 .amaflags = AST_AMA_DOCUMENTATION,
407 .disposition = AST_CDR_NOANSWER,
408 .accountcode = "100",
409 };
411
412 switch (cmd) {
413 case TEST_INIT:
414 info->name = __func__;
415 info->category = TEST_CATEGORY;
416 info->summary = "Test that a CDR is created when a channel is created";
417 info->description =
418 "Test that a CDR is created when a channel is created";
419 return AST_TEST_NOT_RUN;
420 case TEST_EXECUTE:
421 break;
422 }
423
425
426 CREATE_ALICE_CHANNEL(chan, (&caller), &expected);
427
429
430 result = verify_mock_cdr_record(test, &expected, 1);
431
432 return result;
433}
434
435AST_TEST_DEFINE(test_cdr_unanswered_inbound_call)
436{
438 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
440
441 struct ast_party_caller caller = ALICE_CALLERID;
442 struct ast_cdr expected = {
443 .clid = "\"Alice\" <100>",
444 .src = "100",
445 .dst = "100",
446 .dcontext = "default",
447 .channel = CHANNEL_TECH_NAME "/Alice",
448 .lastapp = "Wait",
449 .lastdata = "1",
450 .amaflags = AST_AMA_DOCUMENTATION,
451 .disposition = AST_CDR_NOANSWER,
452 .accountcode = "100",
453 };
455
456 switch (cmd) {
457 case TEST_INIT:
458 info->name = __func__;
459 info->category = TEST_CATEGORY;
460 info->summary = "Test inbound unanswered calls";
461 info->description =
462 "Test the properties of a CDR for a call that is\n"
463 "inbound to Asterisk, executes some dialplan, but\n"
464 "is never answered.";
465 return AST_TEST_NOT_RUN;
466 case TEST_EXECUTE:
467 break;
468 }
469
471
472 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
473
474 EMULATE_APP_DATA(chan, 1, "Wait", "1");
475
477
478 result = verify_mock_cdr_record(test, &expected, 1);
479
480 return result;
481}
482
483AST_TEST_DEFINE(test_cdr_unanswered_outbound_call)
484{
486 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
488
489 struct ast_party_caller caller = {
490 .id.name.str = "",
491 .id.name.valid = 1,
492 .id.number.str = "",
493 .id.number.valid = 1, };
494 struct ast_cdr expected = {
495 .clid = "\"\" <>",
496 .dst = "s",
497 .dcontext = "default",
498 .channel = CHANNEL_TECH_NAME "/Alice",
499 .lastapp = "AppDial",
500 .lastdata = "(Outgoing Line)",
501 .amaflags = AST_AMA_DOCUMENTATION,
502 .disposition = AST_CDR_NOANSWER,
503 .accountcode = "100",
504 };
506
507 switch (cmd) {
508 case TEST_INIT:
509 info->name = __func__;
510 info->category = TEST_CATEGORY;
511 info->summary = "Test outbound unanswered calls";
512 info->description =
513 "Test the properties of a CDR for a call that is\n"
514 "outbound to Asterisk but is never answered.";
515 return AST_TEST_NOT_RUN;
516 case TEST_EXECUTE:
517 break;
518 }
519
521
522 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
523
524 ast_channel_exten_set(chan, "s");
525 ast_channel_context_set(chan, "default");
527 EMULATE_APP_DATA(chan, 0, "AppDial", "(Outgoing Line)");
529
530 result = verify_mock_cdr_record(test, &expected, 1);
531
532 return result;
533}
534
535AST_TEST_DEFINE(test_cdr_outbound_bridged_call)
536{
537 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
538 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
539 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
540 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
542 struct timespec to_sleep = {1, 0};
544
545 struct ast_party_caller caller = ALICE_CALLERID;
546 struct ast_cdr alice_expected = {
547 .clid = "\"Alice\" <100>",
548 .src = "100",
549 .dst = "100",
550 .dcontext = "default",
551 .channel = CHANNEL_TECH_NAME "/Alice",
552 .dstchannel = CHANNEL_TECH_NAME "/Bob",
553 .lastapp = "",
554 .lastdata = "",
555 .amaflags = AST_AMA_DOCUMENTATION,
556 .billsec = 1,
557 .disposition = AST_CDR_ANSWERED,
558 .accountcode = "100",
559 .peeraccount = "200",
560 };
561 struct ast_cdr bob_expected = {
562 .clid = "\"\" <>",
563 .src = "",
564 .dst = "s",
565 .dcontext = "default",
566 .channel = CHANNEL_TECH_NAME "/Bob",
567 .dstchannel = "",
568 .lastapp = "AppDial",
569 .lastdata = "(Outgoing Line)",
570 .amaflags = AST_AMA_DOCUMENTATION,
571 .billsec = 1,
572 .disposition = AST_CDR_ANSWERED,
573 .accountcode = "200",
574 .peeraccount = "",
575 .next = &alice_expected,
576 };
577
578 switch (cmd) {
579 case TEST_INIT:
580 info->name = __func__;
581 info->category = TEST_CATEGORY;
582 info->summary = "Test dialing, answering, and going into a 2-party bridge";
583 info->description =
584 "The most 'basic' of scenarios";
585 return AST_TEST_NOT_RUN;
586 case TEST_EXECUTE:
587 break;
588 }
589
591
592 CREATE_ALICE_CHANNEL(chan_alice, &caller, &alice_expected);
594
595 bridge = ast_bridge_basic_new();
596 ast_test_validate(test, bridge != NULL);
598
599 ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
600
601 chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_alice, 0, CHANNEL_TECH_NAME "/Bob");
602 SET_FORMATS(chan_bob);
603 ast_channel_unlock(chan_bob);
604 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_bob), sizeof(bob_expected.linkedid));
605 ast_copy_string(bob_expected.uniqueid, ast_channel_uniqueid(chan_bob), sizeof(bob_expected.uniqueid));
608 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
609
610 ast_channel_publish_dial(NULL, chan_bob, "Bob", NULL);
612 ast_channel_publish_dial(NULL, chan_bob, NULL, "ANSWER");
613
615
617
618 ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
619
621
622 ast_bridge_depart(chan_bob);
623 ast_bridge_depart(chan_alice);
624
626 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
627
628 result = verify_mock_cdr_record(test, &bob_expected, 2);
629 return result;
630}
631
632
633AST_TEST_DEFINE(test_cdr_single_party)
634{
636 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
638
639 struct ast_party_caller caller = ALICE_CALLERID;
640 struct ast_cdr expected = {
641 .clid = "\"Alice\" <100>",
642 .src = "100",
643 .dst = "100",
644 .dcontext = "default",
645 .channel = CHANNEL_TECH_NAME "/Alice",
646 .dstchannel = "",
647 .lastapp = "VoiceMailMain",
648 .lastdata = "1",
649 .billsec = 1,
650 .amaflags = AST_AMA_DOCUMENTATION,
651 .disposition = AST_CDR_ANSWERED,
652 .accountcode = "100",
653 };
655
656 switch (cmd) {
657 case TEST_INIT:
658 info->name = __func__;
659 info->category = TEST_CATEGORY;
660 info->summary = "Test cdrs for a single party";
661 info->description =
662 "Test the properties of a CDR for a call that is\n"
663 "answered, but only involves a single channel";
664 return AST_TEST_NOT_RUN;
665 case TEST_EXECUTE:
666 break;
667 }
669 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
670
671 ast_channel_lock(chan);
672 EMULATE_APP_DATA(chan, 1, "Answer", "");
674 EMULATE_APP_DATA(chan, 2, "VoiceMailMain", "1");
675 ast_channel_unlock(chan);
676
678
679 result = verify_mock_cdr_record(test, &expected, 1);
680
681 return result;
682}
683
684AST_TEST_DEFINE(test_cdr_single_bridge)
685{
687 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
688 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
690 struct timespec to_sleep = {1, 0};
691
692 struct ast_party_caller caller = ALICE_CALLERID;
693 struct ast_cdr expected = {
694 .clid = "\"Alice\" <100>",
695 .src = "100",
696 .dst = "100",
697 .dcontext = "default",
698 .channel = CHANNEL_TECH_NAME "/Alice",
699 .lastapp = "Bridge",
700 .billsec = 1,
701 .amaflags = AST_AMA_DOCUMENTATION,
702 .disposition = AST_CDR_ANSWERED,
703 .accountcode = "100",
704 };
706
707 switch (cmd) {
708 case TEST_INIT:
709 info->name = __func__;
710 info->category = TEST_CATEGORY;
711 info->summary = "Test cdrs for a single party entering/leaving a bridge";
712 info->description =
713 "Test the properties of a CDR for a call that is\n"
714 "answered, enters a bridge, and leaves it.";
715 return AST_TEST_NOT_RUN;
716 case TEST_EXECUTE:
717 break;
718 }
720 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
721
722 ast_channel_lock(chan);
723 EMULATE_APP_DATA(chan, 1, "Answer", "");
725 EMULATE_APP_DATA(chan, 2, "Bridge", "");
726 ast_channel_unlock(chan);
727
728 bridge = ast_bridge_basic_new();
729 ast_test_validate(test, bridge != NULL);
730
732 ast_test_validate(test, !ast_bridge_impart(bridge, chan, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
733
735
736 ast_bridge_depart(chan);
737
739
740 result = verify_mock_cdr_record(test, &expected, 1);
741
742 return result;
743}
744
745AST_TEST_DEFINE(test_cdr_single_bridge_continue)
746{
748 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
749 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
751 struct timespec to_sleep = {1, 0};
752
753 struct ast_party_caller caller = ALICE_CALLERID;
754 struct ast_cdr expected_two = {
755 .clid = "\"Alice\" <100>",
756 .src = "100",
757 .dst = "100",
758 .dcontext = "default",
759 .channel = CHANNEL_TECH_NAME "/Alice",
760 .lastapp = "Wait",
761 .billsec = 1,
762 .amaflags = AST_AMA_DOCUMENTATION,
763 .disposition = AST_CDR_ANSWERED,
764 .accountcode = "100",
765 };
766 struct ast_cdr expected_one = {
767 .clid = "\"Alice\" <100>",
768 .src = "100",
769 .dst = "100",
770 .dcontext = "default",
771 .channel = CHANNEL_TECH_NAME "/Alice",
772 .lastapp = "Bridge",
773 .billsec = 1,
774 .amaflags = AST_AMA_DOCUMENTATION,
775 .disposition = AST_CDR_ANSWERED,
776 .accountcode = "100",
777 .next = &expected_two,
778 };
779
781
782 switch (cmd) {
783 case TEST_INIT:
784 info->name = __func__;
785 info->category = TEST_CATEGORY;
786 info->summary = "Test cdrs for a single party entering/leaving a bridge";
787 info->description =
788 "Test the properties of a CDR for a call that is\n"
789 "answered, enters a bridge, and leaves it.";
790 return AST_TEST_NOT_RUN;
791 case TEST_EXECUTE:
792 break;
793 }
795 CREATE_ALICE_CHANNEL(chan, &caller, &expected_one);
796 COPY_IDS(chan, &expected_two);
797
798 ast_channel_lock(chan);
799 EMULATE_APP_DATA(chan, 1, "Answer", "");
801 EMULATE_APP_DATA(chan, 2, "Bridge", "");
802 ast_channel_unlock(chan);
803
804 bridge = ast_bridge_basic_new();
805 ast_test_validate(test, bridge != NULL);
807
808 ast_test_validate(test, !ast_bridge_impart(bridge, chan, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
809
811
812 ast_bridge_depart(chan);
813
814 EMULATE_APP_DATA(chan, 3, "Wait", "");
815
816 /* And then it hangs up */
818
819 result = verify_mock_cdr_record(test, &expected_one, 2);
820
821 return result;
822}
823
824AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_a)
825{
826 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
827 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
828 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
829 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
831 struct timespec to_sleep = {1, 0};
832
833 struct ast_party_caller caller_alice = ALICE_CALLERID;
834 struct ast_party_caller caller_bob = BOB_CALLERID;
835 struct ast_cdr bob_expected = {
836 .clid = "\"Bob\" <200>",
837 .src = "200",
838 .dst = "200",
839 .dcontext = "default",
840 .channel = CHANNEL_TECH_NAME "/Bob",
841 .lastapp = "Bridge",
842 .billsec = 1,
843 .amaflags = AST_AMA_DOCUMENTATION,
844 .disposition = AST_CDR_ANSWERED,
845 .accountcode = "200",
846 };
847 struct ast_cdr alice_expected = {
848 .clid = "\"Alice\" <100>",
849 .src = "100",
850 .dst = "100",
851 .dcontext = "default",
852 .channel = CHANNEL_TECH_NAME "/Alice",
853 .dstchannel = CHANNEL_TECH_NAME "/Bob",
854 .lastapp = "Bridge",
855 .billsec = 1,
856 .amaflags = AST_AMA_DOCUMENTATION,
857 .disposition = AST_CDR_ANSWERED,
858 .accountcode = "100",
859 .peeraccount = "200",
860 .next = &bob_expected,
861 };
862
864
865 switch (cmd) {
866 case TEST_INIT:
867 info->name = __func__;
868 info->category = TEST_CATEGORY;
869 info->summary = "Test cdrs for a single party entering/leaving a bridge";
870 info->description =
871 "Test the properties of a CDR for a call that is\n"
872 "answered, enters a bridge, and leaves it. In this scenario, the\n"
873 "Party A should answer the bridge first.";
874 return AST_TEST_NOT_RUN;
875 case TEST_EXECUTE:
876 break;
877 }
879 CREATE_ALICE_CHANNEL(chan_alice, &caller_alice, &alice_expected);
880
881 CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
882 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
883
884 ast_channel_lock(chan_alice);
885 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
886 ast_setstate(chan_alice, AST_STATE_UP);
887 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
888 ast_channel_unlock(chan_alice);
889
890 bridge = ast_bridge_basic_new();
891 ast_test_validate(test, bridge != NULL);
892
893 ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
895
896 ast_channel_lock(chan_bob);
897 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
898 ast_setstate(chan_bob, AST_STATE_UP);
899 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
900 ast_channel_unlock(chan_bob);
901
902 ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
904
905 ast_bridge_depart(chan_alice);
906 ast_bridge_depart(chan_bob);
907
908 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
910
911 result = verify_mock_cdr_record(test, &alice_expected, 2);
912
913 return result;
914}
915
916AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_b)
917{
918 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
919 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
920 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
921 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
923 struct timespec to_sleep = {1, 0};
924
925 struct ast_party_caller caller_alice = ALICE_CALLERID;
926 struct ast_party_caller caller_bob = BOB_CALLERID;
927 struct ast_cdr bob_expected = {
928 .clid = "\"Bob\" <200>",
929 .src = "200",
930 .dst = "200",
931 .dcontext = "default",
932 .channel = CHANNEL_TECH_NAME "/Bob",
933 .lastapp = "Bridge",
934 .billsec = 1,
935 .amaflags = AST_AMA_DOCUMENTATION,
936 .disposition = AST_CDR_ANSWERED,
937 .accountcode = "200",
938 };
939 struct ast_cdr alice_expected = {
940 .clid = "\"Alice\" <100>",
941 .src = "100",
942 .dst = "100",
943 .dcontext = "default",
944 .channel = CHANNEL_TECH_NAME "/Alice",
945 .dstchannel = CHANNEL_TECH_NAME "/Bob",
946 .lastapp = "Bridge",
947 .billsec = 1,
948 .amaflags = AST_AMA_DOCUMENTATION,
949 .disposition = AST_CDR_ANSWERED,
950 .accountcode = "100",
951 .peeraccount = "200",
952 .next = &bob_expected,
953 };
954
956
957 switch (cmd) {
958 case TEST_INIT:
959 info->name = __func__;
960 info->category = TEST_CATEGORY;
961 info->summary = "Test cdrs for a single party entering/leaving a bridge";
962 info->description =
963 "Test the properties of a CDR for a call that is\n"
964 "answered, enters a bridge, and leaves it. In this scenario, the\n"
965 "Party B should answer the bridge first.";
966 return AST_TEST_NOT_RUN;
967 case TEST_EXECUTE:
968 break;
969 }
971 CREATE_ALICE_CHANNEL(chan_alice, &caller_alice, &alice_expected);
972
973 CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
974 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
975
976 ast_channel_unlock(chan_alice);
977 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
978 ast_setstate(chan_alice, AST_STATE_UP);
979 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
980 ast_channel_unlock(chan_alice);
981
982 bridge = ast_bridge_basic_new();
983 ast_test_validate(test, bridge != NULL);
984
985 ast_channel_lock(chan_bob);
986 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
987 ast_setstate(chan_bob, AST_STATE_UP);
988 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
989 ast_channel_unlock(chan_bob);
991
992 ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
994
995 ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
997
998 ast_bridge_depart(chan_alice);
999 ast_bridge_depart(chan_bob);
1000
1001 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
1003
1004 result = verify_mock_cdr_record(test, &alice_expected, 2);
1005
1006 return result;
1007}
1008
1009AST_TEST_DEFINE(test_cdr_single_multiparty_bridge)
1010{
1011 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
1012 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
1013 RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
1014 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
1015 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1016 ao2_cleanup);
1017 struct timespec to_sleep = {1, 0};
1018
1019 struct ast_party_caller caller_alice = ALICE_CALLERID;
1020 struct ast_party_caller caller_bob = BOB_CALLERID;
1021 struct ast_party_caller caller_charlie = CHARLIE_CALLERID;
1022 struct ast_cdr charlie_expected = {
1023 .clid = "\"Charlie\" <300>",
1024 .src = "300",
1025 .dst = "300",
1026 .dcontext = "default",
1027 .channel = CHANNEL_TECH_NAME "/Charlie",
1028 .lastapp = "Bridge",
1029 .billsec = 1,
1030 .amaflags = AST_AMA_DOCUMENTATION,
1031 .disposition = AST_CDR_ANSWERED,
1032 .accountcode = "300",
1033 };
1034 struct ast_cdr bob_expected = {
1035 .clid = "\"Bob\" <200>",
1036 .src = "200",
1037 .dst = "200",
1038 .dcontext = "default",
1039 .channel = CHANNEL_TECH_NAME "/Bob",
1040 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1041 .lastapp = "Bridge",
1042 .billsec = 1,
1043 .amaflags = AST_AMA_DOCUMENTATION,
1044 .disposition = AST_CDR_ANSWERED,
1045 .accountcode = "200",
1046 .peeraccount = "300",
1047 .next = &charlie_expected,
1048 };
1049 struct ast_cdr alice_expected_two = {
1050 .clid = "\"Alice\" <100>",
1051 .src = "100",
1052 .dst = "100",
1053 .dcontext = "default",
1054 .channel = CHANNEL_TECH_NAME "/Alice",
1055 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1056 .lastapp = "Bridge",
1057 .billsec = 1,
1058 .amaflags = AST_AMA_DOCUMENTATION,
1059 .disposition = AST_CDR_ANSWERED,
1060 .accountcode = "100",
1061 .peeraccount = "300",
1062 .next = &bob_expected,
1063 };
1064 struct ast_cdr alice_expected_one = {
1065 .clid = "\"Alice\" <100>",
1066 .src = "100",
1067 .dst = "100",
1068 .dcontext = "default",
1069 .channel = CHANNEL_TECH_NAME "/Alice",
1070 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1071 .lastapp = "Bridge",
1072 .billsec = 1,
1073 .amaflags = AST_AMA_DOCUMENTATION,
1074 .disposition = AST_CDR_ANSWERED,
1075 .accountcode = "100",
1076 .peeraccount = "200",
1077 .next = &alice_expected_two,
1078 };
1079
1081
1082 switch (cmd) {
1083 case TEST_INIT:
1084 info->name = __func__;
1085 info->category = TEST_CATEGORY;
1086 info->summary = "Test cdrs for a single party entering/leaving a multi-party bridge";
1087 info->description =
1088 "Test the properties of a CDR for a call that is\n"
1089 "answered, enters a bridge, and leaves it. A total of three\n"
1090 "parties perform this action.";
1091 return AST_TEST_NOT_RUN;
1092 case TEST_EXECUTE:
1093 break;
1094 }
1096 CREATE_ALICE_CHANNEL(chan_alice, &caller_alice, &alice_expected_one);
1097 COPY_IDS(chan_alice, &alice_expected_two);
1098 CREATE_BOB_CHANNEL(chan_bob, &caller_bob, &bob_expected);
1099 ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected.linkedid));
1100 CREATE_CHARLIE_CHANNEL(chan_charlie, &caller_charlie, &charlie_expected);
1101 ast_copy_string(charlie_expected.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected.linkedid));
1102
1103 ast_channel_lock(chan_alice);
1104 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
1105 ast_setstate(chan_alice, AST_STATE_UP);
1106 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
1107 ast_channel_unlock(chan_alice);
1108
1109 bridge = ast_bridge_basic_new();
1110 ast_test_validate(test, bridge != NULL);
1112
1113 ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
1114
1115 ast_channel_lock(chan_bob);
1116 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
1117 ast_setstate(chan_bob, AST_STATE_UP);
1118 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
1119 ast_channel_unlock(chan_bob);
1121
1122 ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
1123
1125
1126 ast_channel_lock(chan_charlie);
1127 EMULATE_APP_DATA(chan_charlie, 1, "Answer", "");
1128 ast_setstate(chan_charlie, AST_STATE_UP);
1129 EMULATE_APP_DATA(chan_charlie, 2, "Bridge", "");
1130 ast_channel_unlock(chan_charlie);
1131 ast_test_validate(test, !ast_bridge_impart(bridge, chan_charlie, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
1132
1134
1135 ast_bridge_depart(chan_alice);
1136 ast_bridge_depart(chan_bob);
1137 ast_bridge_depart(chan_charlie);
1138
1139 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
1141 HANGUP_CHANNEL(chan_charlie, AST_CAUSE_NORMAL);
1142
1143 result = verify_mock_cdr_record(test, &alice_expected_one, 4);
1144
1145 return result;
1146}
1147
1148AST_TEST_DEFINE(test_cdr_dial_unanswered)
1149{
1150 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1151 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1152 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1153 ao2_cleanup);
1154
1155 struct ast_party_caller caller = ALICE_CALLERID;
1156 struct ast_cdr expected = {
1157 .clid = "\"Alice\" <100>",
1158 .src = "100",
1159 .dst = "100",
1160 .dcontext = "default",
1161 .channel = CHANNEL_TECH_NAME "/Alice",
1162 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1163 .lastapp = "Dial",
1164 .lastdata = CHANNEL_TECH_NAME "/Bob",
1165 .billsec = 0,
1166 .amaflags = AST_AMA_DOCUMENTATION,
1167 .disposition = AST_CDR_NOANSWER,
1168 .accountcode = "100",
1169 .peeraccount = "200",
1170 };
1172
1173 switch (cmd) {
1174 case TEST_INIT:
1175 info->name = __func__;
1176 info->category = TEST_CATEGORY;
1177 info->summary = "Test CDRs for a dial that isn't answered";
1178 info->description =
1179 "Test the properties of a CDR for a channel that\n"
1180 "performs a dial operation that isn't answered";
1181 return AST_TEST_NOT_RUN;
1182 case TEST_EXECUTE:
1183 break;
1184 }
1185
1187
1188 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1189
1190 EMULATE_APP_DATA(chan_caller, 1, "Dial", "CDRTestChannel/Bob");
1191
1192 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Bob");
1193 SET_FORMATS(chan_callee);
1194 ast_channel_unlock(chan_callee);
1196 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1197
1198 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1200 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "NOANSWER");
1201
1202 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NO_ANSWER);
1203 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NO_ANSWER);
1204
1205 result = verify_mock_cdr_record(test, &expected, 1);
1206
1207 return result;
1208}
1209
1210
1211AST_TEST_DEFINE(test_cdr_dial_busy)
1212{
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),
1216 ao2_cleanup);
1217
1218 struct ast_party_caller caller = ALICE_CALLERID;
1219 struct ast_cdr expected = {
1220 .clid = "\"Alice\" <100>",
1221 .src = "100",
1222 .dst = "100",
1223 .dcontext = "default",
1224 .channel = CHANNEL_TECH_NAME "/Alice",
1225 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1226 .lastapp = "Dial",
1227 .lastdata = CHANNEL_TECH_NAME "/Bob",
1228 .billsec = 0,
1229 .amaflags = AST_AMA_DOCUMENTATION,
1230 .disposition = AST_CDR_BUSY,
1231 .accountcode = "100",
1232 .peeraccount = "200",
1233 };
1235
1236 switch (cmd) {
1237 case TEST_INIT:
1238 info->name = __func__;
1239 info->category = TEST_CATEGORY;
1240 info->summary = "Test CDRs for a dial that results in a busy";
1241 info->description =
1242 "Test the properties of a CDR for a channel that\n"
1243 "performs a dial operation to an endpoint that's busy";
1244 return AST_TEST_NOT_RUN;
1245 case TEST_EXECUTE:
1246 break;
1247 }
1248
1250
1251 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1252
1253 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1254
1255 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Bob");
1256 SET_FORMATS(chan_callee);
1257 ast_channel_unlock(chan_callee);
1259 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1260
1261 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1263 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "BUSY");
1264
1265 HANGUP_CHANNEL(chan_caller, AST_CAUSE_BUSY);
1266 HANGUP_CHANNEL(chan_callee, AST_CAUSE_BUSY);
1267
1268 result = verify_mock_cdr_record(test, &expected, 1);
1269
1270 return result;
1271}
1272
1273AST_TEST_DEFINE(test_cdr_dial_congestion)
1274{
1275 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1276 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1277 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1278 ao2_cleanup);
1279
1280 struct ast_party_caller caller = ALICE_CALLERID;
1281 struct ast_cdr expected = {
1282 .clid = "\"Alice\" <100>",
1283 .src = "100",
1284 .dst = "100",
1285 .dcontext = "default",
1286 .channel = CHANNEL_TECH_NAME "/Alice",
1287 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1288 .lastapp = "Dial",
1289 .lastdata = CHANNEL_TECH_NAME "/Bob",
1290 .billsec = 0,
1291 .amaflags = AST_AMA_DOCUMENTATION,
1292 .disposition = AST_CDR_CONGESTION,
1293 .accountcode = "100",
1294 .peeraccount = "200",
1295 };
1297
1298 switch (cmd) {
1299 case TEST_INIT:
1300 info->name = __func__;
1301 info->category = TEST_CATEGORY;
1302 info->summary = "Test CDRs for a dial that results in congestion";
1303 info->description =
1304 "Test the properties of a CDR for a channel that\n"
1305 "performs a dial operation to an endpoint that's congested";
1306 return AST_TEST_NOT_RUN;
1307 case TEST_EXECUTE:
1308 break;
1309 }
1310
1312
1313 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1314
1315 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1316
1317 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Bob");
1318 SET_FORMATS(chan_callee);
1319 ast_channel_unlock(chan_callee);
1321 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1322
1323 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1325 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "CONGESTION");
1326
1329
1330 result = verify_mock_cdr_record(test, &expected, 1);
1331
1332 return result;
1333}
1334
1335AST_TEST_DEFINE(test_cdr_dial_unavailable)
1336{
1337 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1338 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1339 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1340 ao2_cleanup);
1341
1342 struct ast_party_caller caller = ALICE_CALLERID;
1343 struct ast_cdr expected = {
1344 .clid = "\"Alice\" <100>",
1345 .src = "100",
1346 .dst = "100",
1347 .dcontext = "default",
1348 .channel = CHANNEL_TECH_NAME "/Alice",
1349 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1350 .lastapp = "Dial",
1351 .lastdata = CHANNEL_TECH_NAME "/Bob",
1352 .billsec = 0,
1353 .amaflags = AST_AMA_DOCUMENTATION,
1354 .disposition = AST_CDR_FAILED,
1355 .accountcode = "100",
1356 .peeraccount = "200",
1357 };
1359
1360 switch (cmd) {
1361 case TEST_INIT:
1362 info->name = __func__;
1363 info->category = TEST_CATEGORY;
1364 info->summary = "Test CDRs for a dial that results in unavailable";
1365 info->description =
1366 "Test the properties of a CDR for a channel that\n"
1367 "performs a dial operation to an endpoint that's unavailable";
1368 return AST_TEST_NOT_RUN;
1369 case TEST_EXECUTE:
1370 break;
1371 }
1372
1374
1375 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1376
1377 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1378
1379 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Bob");
1380 SET_FORMATS(chan_callee);
1381 ast_channel_unlock(chan_callee);
1383 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1384
1385 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1387 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "CHANUNAVAIL");
1388
1391
1392 result = verify_mock_cdr_record(test, &expected, 1);
1393
1394 return result;
1395}
1396
1397AST_TEST_DEFINE(test_cdr_dial_caller_cancel)
1398{
1399 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1400 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1401 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1402 ao2_cleanup);
1403
1404 struct ast_party_caller caller = ALICE_CALLERID;
1405 struct ast_cdr expected = {
1406 .clid = "\"Alice\" <100>",
1407 .src = "100",
1408 .dst = "100",
1409 .dcontext = "default",
1410 .channel = CHANNEL_TECH_NAME "/Alice",
1411 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1412 .lastapp = "Dial",
1413 .lastdata = CHANNEL_TECH_NAME "/Bob",
1414 .billsec = 0,
1415 .amaflags = AST_AMA_DOCUMENTATION,
1416 .disposition = AST_CDR_NOANSWER,
1417 .accountcode = "100",
1418 .peeraccount = "200",
1419 };
1421
1422 switch (cmd) {
1423 case TEST_INIT:
1424 info->name = __func__;
1425 info->category = TEST_CATEGORY;
1426 info->summary = "Test CDRs for a dial where the caller cancels";
1427 info->description =
1428 "Test the properties of a CDR for a channel that\n"
1429 "performs a dial operation to an endpoint but then decides\n"
1430 "to hang up, cancelling the dial";
1431 return AST_TEST_NOT_RUN;
1432 case TEST_EXECUTE:
1433 break;
1434 }
1435
1437
1438 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1439
1440 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1441
1442 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Bob");
1443 SET_FORMATS(chan_callee);
1444 ast_channel_unlock(chan_callee);
1446 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1447
1448 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1450 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "CANCEL");
1451
1452 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1453 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1454
1455 result = verify_mock_cdr_record(test, &expected, 1);
1456
1457 return result;
1458}
1459
1460AST_TEST_DEFINE(test_cdr_dial_parallel_failed)
1461{
1462 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1463 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
1464 RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
1465 RAII_VAR(struct ast_channel *, chan_david, NULL, safe_channel_release);
1466 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1467 ao2_cleanup);
1468
1469 struct ast_party_caller caller = ALICE_CALLERID;
1470 struct ast_cdr bob_expected = {
1471 .clid = "\"Alice\" <100>",
1472 .src = "100",
1473 .dst = "100",
1474 .dcontext = "default",
1475 .channel = CHANNEL_TECH_NAME "/Alice",
1476 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1477 .lastapp = "Dial",
1478 .lastdata = CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David",
1479 .billsec = 0,
1480 .amaflags = AST_AMA_DOCUMENTATION,
1481 .disposition = AST_CDR_NOANSWER,
1482 .accountcode = "100",
1483 .peeraccount = "200",
1484 };
1485 struct ast_cdr charlie_expected = {
1486 .clid = "\"Alice\" <100>",
1487 .src = "100",
1488 .dst = "100",
1489 .dcontext = "default",
1490 .channel = CHANNEL_TECH_NAME "/Alice",
1491 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1492 .lastapp = "Dial",
1493 .lastdata = CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David",
1494 .billsec = 0,
1495 .amaflags = AST_AMA_DOCUMENTATION,
1496 .disposition = AST_CDR_BUSY,
1497 .accountcode = "100",
1498 .peeraccount = "300",
1499 };
1500 struct ast_cdr david_expected = {
1501 .clid = "\"Alice\" <100>",
1502 .src = "100",
1503 .dst = "100",
1504 .dcontext = "default",
1505 .channel = CHANNEL_TECH_NAME "/Alice",
1506 .dstchannel = CHANNEL_TECH_NAME "/David",
1507 .lastapp = "Dial",
1508 .lastdata = CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David",
1509 .billsec = 0,
1510 .amaflags = AST_AMA_DOCUMENTATION,
1511 .disposition = AST_CDR_CONGESTION,
1512 .accountcode = "100",
1513 .peeraccount = "400",
1514 };
1516
1517 struct ast_cdr *expected = &bob_expected;
1518 bob_expected.next = &charlie_expected;
1519 charlie_expected.next = &david_expected;
1520
1521 switch (cmd) {
1522 case TEST_INIT:
1523 info->name = __func__;
1524 info->category = TEST_CATEGORY;
1525 info->summary = "Test a parallel dial where all channels fail to answer";
1526 info->description =
1527 "This tests dialing three parties: Bob, Charlie, David. Charlie\n"
1528 "returns BUSY; David returns CONGESTION; Bob fails to answer and\n"
1529 "Alice hangs up. Three records are created for Alice as a result.";
1530 return AST_TEST_NOT_RUN;
1531 case TEST_EXECUTE:
1532 break;
1533 }
1534
1536
1537 CREATE_ALICE_CHANNEL(chan_caller, &caller, &bob_expected);
1538 COPY_IDS(chan_caller, &charlie_expected);
1539 COPY_IDS(chan_caller, &david_expected);
1540
1541 /* Channel enters Dial app */
1542 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob&" CHANNEL_TECH_NAME "/Charlie&" CHANNEL_TECH_NAME "/David");
1543
1544 /* Outbound channels are created */
1545 chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Bob");
1546 SET_FORMATS(chan_bob);
1547 ast_channel_unlock(chan_bob);
1549 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
1550
1551 chan_charlie = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "300", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Charlie");
1552 SET_FORMATS(chan_charlie);
1553 ast_channel_unlock(chan_charlie);
1555 EMULATE_APP_DATA(chan_charlie, 0, "AppDial", "(Outgoing Line)");
1556
1557 chan_david = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "400", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/David");
1558 SET_FORMATS(chan_charlie);
1559 ast_channel_unlock(chan_david);
1561 EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");
1562
1563 /* Dial starts */
1564 ast_channel_publish_dial(chan_caller, chan_bob, "Bob", NULL);
1565 ast_channel_publish_dial(chan_caller, chan_charlie, "Charlie", NULL);
1566 ast_channel_publish_dial(chan_caller, chan_david, "David", NULL);
1568
1569 /* Charlie is busy */
1570 ast_channel_publish_dial(chan_caller, chan_charlie, NULL, "BUSY");
1571 HANGUP_CHANNEL(chan_charlie, AST_CAUSE_BUSY);
1572
1573 /* David is congested */
1574 ast_channel_publish_dial(chan_caller, chan_david, NULL, "CONGESTION");
1576
1577 /* Bob is canceled */
1578 ast_channel_publish_dial(chan_caller, chan_bob, NULL, "CANCEL");
1580
1581 /* Alice hangs up */
1582 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1583
1584 result = verify_mock_cdr_record(test, expected, 3);
1585
1586 return result;
1587}
1588
1589AST_TEST_DEFINE(test_cdr_dial_answer_no_bridge)
1590{
1591 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1592 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1593 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1594 ao2_cleanup);
1595
1596 struct ast_party_caller caller = ALICE_CALLERID;
1597 struct ast_cdr bob_expected_one = {
1598 .clid = "\"\" <>",
1599 .src = "",
1600 .dst = "s",
1601 .dcontext = "default",
1602 .channel = CHANNEL_TECH_NAME "/Bob",
1603 .lastapp = "Wait",
1604 .lastdata = "1",
1605 .amaflags = AST_AMA_DOCUMENTATION,
1606 .disposition = AST_CDR_ANSWERED,
1607 .accountcode = "200",
1608 };
1609 struct ast_cdr alice_expected_two = {
1610 .clid = "\"Alice\" <100>",
1611 .src = "100",
1612 .dst = "100",
1613 .dcontext = "default",
1614 .channel = CHANNEL_TECH_NAME "/Alice",
1615 .lastapp = "Wait",
1616 .lastdata = "1",
1617 .amaflags = AST_AMA_DOCUMENTATION,
1618 .disposition = AST_CDR_ANSWERED,
1619 .accountcode = "100",
1620 .next = &bob_expected_one,
1621 };
1622 struct ast_cdr alice_expected_one = {
1623 .clid = "\"Alice\" <100>",
1624 .src = "100",
1625 .dst = "100",
1626 .dcontext = "default",
1627 .channel = CHANNEL_TECH_NAME "/Alice",
1628 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1629 .lastapp = "Dial",
1630 .lastdata = CHANNEL_TECH_NAME "/Bob",
1631 .amaflags = AST_AMA_DOCUMENTATION,
1632 .disposition = AST_CDR_ANSWERED,
1633 .accountcode = "100",
1634 .peeraccount = "200",
1635 .next = &alice_expected_two,
1636 };
1638
1639 switch (cmd) {
1640 case TEST_INIT:
1641 info->name = __func__;
1642 info->category = TEST_CATEGORY;
1643 info->summary = "Test dialing, answering, and not going into a bridge.";
1644 info->description =
1645 "This is a weird one, but theoretically possible. You can perform\n"
1646 "a dial, then bounce both channels to different priorities and\n"
1647 "never have them enter a bridge together. Ew. This makes sure that\n"
1648 "when we answer, we get a CDR, it gets ended at that point, and\n"
1649 "that it gets finalized appropriately. We should get three CDRs in\n"
1650 "the end - one for the dial, and one for each CDR as they continued\n"
1651 "on.";
1652 return AST_TEST_NOT_RUN;
1653 case TEST_EXECUTE:
1654 break;
1655 }
1656
1658
1659 CREATE_ALICE_CHANNEL(chan_caller, &caller, &alice_expected_one);
1660 COPY_IDS(chan_caller, &alice_expected_two);
1661
1662 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1663
1664 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Bob");
1665 SET_FORMATS(chan_callee);
1666 ast_channel_unlock(chan_callee);
1668 COPY_IDS(chan_callee, &bob_expected_one);
1669
1670 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1672 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "ANSWER");
1673
1674 ast_channel_state_set(chan_caller, AST_STATE_UP);
1676 ast_channel_state_set(chan_callee, AST_STATE_UP);
1677
1678 EMULATE_APP_DATA(chan_caller, 2, "Wait", "1");
1679 EMULATE_APP_DATA(chan_callee, 1, "Wait", "1");
1680
1681 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1682 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1683
1684 result = verify_mock_cdr_record(test, &alice_expected_one, 3);
1685 return result;
1686}
1687
1688AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_a)
1689{
1690 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1691 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1692 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
1693 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1694 ao2_cleanup);
1695 struct timespec to_sleep = {1, 0};
1697
1698 struct ast_party_caller caller = ALICE_CALLERID;
1699 struct ast_cdr expected = {
1700 .clid = "\"Alice\" <100>",
1701 .src = "100",
1702 .dst = "100",
1703 .dcontext = "default",
1704 .channel = CHANNEL_TECH_NAME "/Alice",
1705 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1706 .lastapp = "Dial",
1707 .lastdata = CHANNEL_TECH_NAME "/Bob",
1708 .amaflags = AST_AMA_DOCUMENTATION,
1709 .billsec = 1,
1710 .disposition = AST_CDR_ANSWERED,
1711 .accountcode = "100",
1712 .peeraccount = "200",
1713 };
1714
1715 switch (cmd) {
1716 case TEST_INIT:
1717 info->name = __func__;
1718 info->category = TEST_CATEGORY;
1719 info->summary = "Test dialing, answering, and going into a 2-party bridge";
1720 info->description =
1721 "The most 'basic' of scenarios";
1722 return AST_TEST_NOT_RUN;
1723 case TEST_EXECUTE:
1724 break;
1725 }
1726
1728
1729 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1730
1731 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1732
1733 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Bob");
1734 SET_FORMATS(chan_callee);
1735 ast_channel_unlock(chan_callee);
1737 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1738
1739 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1741 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "ANSWER");
1742
1743 ast_channel_state_set(chan_caller, AST_STATE_UP);
1744 ast_channel_state_set(chan_callee, AST_STATE_UP);
1745
1746 bridge = ast_bridge_basic_new();
1747 ast_test_validate(test, bridge != NULL);
1749
1750 ast_test_validate(test, !ast_bridge_impart(bridge, chan_caller, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
1751 ast_test_validate(test, !ast_bridge_impart(bridge, chan_callee, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
1752
1754
1755 ast_bridge_depart(chan_caller);
1756 ast_bridge_depart(chan_callee);
1757
1758 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1759 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1760
1761 result = verify_mock_cdr_record(test, &expected, 1);
1762 return result;
1763}
1764
1765AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_b)
1766{
1767 RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
1768 RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
1769 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
1770 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1771 ao2_cleanup);
1772 struct timespec to_sleep = {1, 0};
1774
1775 struct ast_party_caller caller = ALICE_CALLERID;
1776 struct ast_cdr expected = {
1777 .clid = "\"Alice\" <100>",
1778 .src = "100",
1779 .dst = "100",
1780 .dcontext = "default",
1781 .channel = CHANNEL_TECH_NAME "/Alice",
1782 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1783 .lastapp = "Dial",
1784 .lastdata = CHANNEL_TECH_NAME "/Bob",
1785 .amaflags = AST_AMA_DOCUMENTATION,
1786 .billsec = 1,
1787 .disposition = AST_CDR_ANSWERED,
1788 .accountcode = "100",
1789 .peeraccount = "200",
1790 };
1791
1792 switch (cmd) {
1793 case TEST_INIT:
1794 info->name = __func__;
1795 info->category = TEST_CATEGORY;
1796 info->summary = "Test dialing, answering, and going into a 2-party bridge";
1797 info->description =
1798 "The most 'basic' of scenarios";
1799 return AST_TEST_NOT_RUN;
1800 case TEST_EXECUTE:
1801 break;
1802 }
1803
1805
1806 CREATE_ALICE_CHANNEL(chan_caller, &caller, &expected);
1807
1808 EMULATE_APP_DATA(chan_caller, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1809
1810 chan_callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, NULL, chan_caller, 0, CHANNEL_TECH_NAME "/Bob");
1811 SET_FORMATS(chan_callee);
1812 ast_channel_unlock(chan_callee);
1814 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1815
1816 ast_channel_publish_dial(chan_caller, chan_callee, "Bob", NULL);
1818 ast_channel_publish_dial(chan_caller, chan_callee, NULL, "ANSWER");
1819
1820 ast_channel_state_set(chan_caller, AST_STATE_UP);
1821 ast_channel_state_set(chan_callee, AST_STATE_UP);
1822
1823 bridge = ast_bridge_basic_new();
1824 ast_test_validate(test, bridge != NULL);
1826 ast_test_validate(test, !ast_bridge_impart(bridge, chan_callee, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
1828 ast_test_validate(test, !ast_bridge_impart(bridge, chan_caller, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
1830 ast_bridge_depart(chan_caller);
1831 ast_bridge_depart(chan_callee);
1832
1833 HANGUP_CHANNEL(chan_caller, AST_CAUSE_NORMAL);
1834 HANGUP_CHANNEL(chan_callee, AST_CAUSE_NORMAL);
1835
1836 result = verify_mock_cdr_record(test, &expected, 1);
1837 return result;
1838}
1839
1840AST_TEST_DEFINE(test_cdr_dial_answer_multiparty)
1841{
1842 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
1843 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
1844 RAII_VAR(struct ast_channel *, chan_charlie, NULL, safe_channel_release);
1845 RAII_VAR(struct ast_channel *, chan_david, NULL, safe_channel_release);
1846 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
1847 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
1848 ao2_cleanup);
1849 struct timespec to_sleep = {1, 0};
1851
1852 struct ast_party_caller alice_caller = ALICE_CALLERID;
1853 struct ast_party_caller charlie_caller = CHARLIE_CALLERID;
1854 struct ast_cdr charlie_expected_two = {
1855 .clid = "\"Charlie\" <300>",
1856 .src = "300",
1857 .dst = "300",
1858 .dcontext = "default",
1859 .channel = CHANNEL_TECH_NAME "/Charlie",
1860 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1861 .lastapp = "Dial",
1862 .lastdata = CHANNEL_TECH_NAME "/David",
1863 .amaflags = AST_AMA_DOCUMENTATION,
1864 .billsec = 1,
1865 .disposition = AST_CDR_ANSWERED,
1866 .accountcode = "300",
1867 .peeraccount = "200",
1868 };
1869 struct ast_cdr charlie_expected_one = {
1870 .clid = "\"Charlie\" <300>",
1871 .src = "300",
1872 .dst = "300",
1873 .dcontext = "default",
1874 .channel = CHANNEL_TECH_NAME "/Charlie",
1875 .dstchannel = CHANNEL_TECH_NAME "/David",
1876 .lastapp = "Dial",
1877 .lastdata = CHANNEL_TECH_NAME "/David",
1878 .amaflags = AST_AMA_DOCUMENTATION,
1879 .billsec = 1,
1880 .disposition = AST_CDR_ANSWERED,
1881 .accountcode = "300",
1882 .peeraccount = "400",
1883 .next = &charlie_expected_two,
1884 };
1885 struct ast_cdr bob_expected_one = {
1886 .clid = "\"Bob\" <200>",
1887 .src = "200",
1888 .dst = "200",
1889 .dcontext = "default",
1890 .channel = CHANNEL_TECH_NAME "/Bob",
1891 .dstchannel = CHANNEL_TECH_NAME "/David",
1892 .lastapp = "AppDial",
1893 .lastdata = "(Outgoing Line)",
1894 .amaflags = AST_AMA_DOCUMENTATION,
1895 .billsec = 1,
1896 .disposition = AST_CDR_ANSWERED,
1897 .accountcode = "200",
1898 .peeraccount = "400",
1899 .next = &charlie_expected_one,
1900 };
1901 struct ast_cdr alice_expected_three = {
1902 .clid = "\"Alice\" <100>",
1903 .src = "100",
1904 .dst = "100",
1905 .dcontext = "default",
1906 .channel = CHANNEL_TECH_NAME "/Alice",
1907 .dstchannel = CHANNEL_TECH_NAME "/David",
1908 .lastapp = "Dial",
1909 .lastdata = CHANNEL_TECH_NAME "/Bob",
1910 .amaflags = AST_AMA_DOCUMENTATION,
1911 .billsec = 1,
1912 .disposition = AST_CDR_ANSWERED,
1913 .accountcode = "100",
1914 .peeraccount = "400",
1915 .next = &bob_expected_one,
1916 };
1917 struct ast_cdr alice_expected_two = {
1918 .clid = "\"Alice\" <100>",
1919 .src = "100",
1920 .dst = "100",
1921 .dcontext = "default",
1922 .channel = CHANNEL_TECH_NAME "/Alice",
1923 .dstchannel = CHANNEL_TECH_NAME "/Charlie",
1924 .lastapp = "Dial",
1925 .lastdata = CHANNEL_TECH_NAME "/Bob",
1926 .amaflags = AST_AMA_DOCUMENTATION,
1927 .billsec = 1,
1928 .disposition = AST_CDR_ANSWERED,
1929 .accountcode = "100",
1930 .peeraccount = "300",
1931 .next = &alice_expected_three,
1932 };
1933 struct ast_cdr alice_expected_one = {
1934 .clid = "\"Alice\" <100>",
1935 .src = "100",
1936 .dst = "100",
1937 .dcontext = "default",
1938 .channel = CHANNEL_TECH_NAME "/Alice",
1939 .dstchannel = CHANNEL_TECH_NAME "/Bob",
1940 .lastapp = "Dial",
1941 .lastdata = CHANNEL_TECH_NAME "/Bob",
1942 .amaflags = AST_AMA_DOCUMENTATION,
1943 .billsec = 1,
1944 .disposition = AST_CDR_ANSWERED,
1945 .accountcode = "100",
1946 .peeraccount = "200",
1947 .next = &alice_expected_two,
1948 };
1949
1950 switch (cmd) {
1951 case TEST_INIT:
1952 info->name = __func__;
1953 info->category = TEST_CATEGORY;
1954 info->summary = "Test dialing, answering, and going into a multi-party bridge";
1955 info->description =
1956 "A little tricky to get to do, but possible with some redirects.";
1957 return AST_TEST_NOT_RUN;
1958 case TEST_EXECUTE:
1959 break;
1960 }
1961
1963
1964 CREATE_ALICE_CHANNEL(chan_alice, &alice_caller, &alice_expected_one);
1965 COPY_IDS(chan_alice, &alice_expected_two);
1966 COPY_IDS(chan_alice, &alice_expected_three);
1967
1968 EMULATE_APP_DATA(chan_alice, 1, "Dial", CHANNEL_TECH_NAME "/Bob");
1969
1970 chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, "200", "Bob", "200", "200", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Bob");
1971 SET_FORMATS(chan_bob);
1972 ast_channel_unlock(chan_bob);
1974 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
1975 ast_copy_string(bob_expected_one.uniqueid, ast_channel_uniqueid(chan_bob), sizeof(bob_expected_one.uniqueid));
1976 ast_copy_string(bob_expected_one.linkedid, ast_channel_linkedid(chan_alice), sizeof(bob_expected_one.linkedid));
1977
1978 CREATE_CHARLIE_CHANNEL(chan_charlie, &charlie_caller, &charlie_expected_one);
1979 EMULATE_APP_DATA(chan_charlie, 1, "Dial", CHANNEL_TECH_NAME "/David");
1980 ast_copy_string(charlie_expected_one.uniqueid, ast_channel_uniqueid(chan_charlie), sizeof(charlie_expected_one.uniqueid));
1981 ast_copy_string(charlie_expected_one.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected_one.linkedid));
1982 ast_copy_string(charlie_expected_two.uniqueid, ast_channel_uniqueid(chan_charlie), sizeof(charlie_expected_two.uniqueid));
1983 ast_copy_string(charlie_expected_two.linkedid, ast_channel_linkedid(chan_alice), sizeof(charlie_expected_two.linkedid));
1984
1985 chan_david = ast_channel_alloc(0, AST_STATE_DOWN, "400", "David", "400", "400", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/David");
1986 SET_FORMATS(chan_david);
1987 ast_channel_unlock(chan_david);
1989 EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");
1990
1991 ast_channel_publish_dial(chan_alice, chan_bob, "Bob", NULL);
1993 ast_channel_publish_dial(chan_charlie, chan_david, "David", NULL);
1995 ast_channel_publish_dial(chan_alice, chan_bob, NULL, "ANSWER");
1996 ast_channel_publish_dial(chan_charlie, chan_david, NULL, "ANSWER");
1997
2000 ast_channel_state_set(chan_charlie, AST_STATE_UP);
2002
2003 bridge = ast_bridge_basic_new();
2004 ast_test_validate(test, bridge != NULL);
2005
2007 ast_test_validate(test, !ast_bridge_impart(bridge, chan_charlie, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
2009 ast_test_validate(test, !ast_bridge_impart(bridge, chan_david, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
2011 ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
2013 ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
2015 ast_test_validate(test, !ast_bridge_depart(chan_alice));
2016 ast_test_validate(test, !ast_bridge_depart(chan_bob));
2017 ast_test_validate(test, !ast_bridge_depart(chan_charlie));
2018 ast_test_validate(test, !ast_bridge_depart(chan_david));
2019
2020 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
2022 HANGUP_CHANNEL(chan_charlie, AST_CAUSE_NORMAL);
2023 HANGUP_CHANNEL(chan_david, AST_CAUSE_NORMAL);
2024
2025 result = verify_mock_cdr_record(test, &alice_expected_one, 6);
2026
2027 return result;
2028}
2029
2030AST_TEST_DEFINE(test_cdr_park)
2031{
2032 RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
2033 RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
2034 RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
2035 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
2036 ao2_cleanup);
2037 struct timespec to_sleep = {1, 0};
2038
2039 struct ast_party_caller bob_caller = BOB_CALLERID;
2040 struct ast_party_caller alice_caller = ALICE_CALLERID;
2041 struct ast_cdr bob_expected = {
2042 .clid = "\"Bob\" <200>",
2043 .src = "200",
2044 .dst = "200",
2045 .dcontext = "default",
2046 .channel = CHANNEL_TECH_NAME "/Bob",
2047 .lastapp = "Park",
2048 .lastdata = "701",
2049 .billsec = 1,
2050 .amaflags = AST_AMA_DOCUMENTATION,
2051 .disposition = AST_CDR_ANSWERED,
2052 .accountcode = "200",
2053 };
2054 struct ast_cdr alice_expected = {
2055 .clid = "\"Alice\" <100>",
2056 .src = "100",
2057 .dst = "100",
2058 .dcontext = "default",
2059 .channel = CHANNEL_TECH_NAME "/Alice",
2060 .lastapp = "Park",
2061 .lastdata = "700",
2062 .billsec = 1,
2063 .amaflags = AST_AMA_DOCUMENTATION,
2064 .disposition = AST_CDR_ANSWERED,
2065 .accountcode = "100",
2066 .next = &bob_expected,
2067 };
2069
2070 switch (cmd) {
2071 case TEST_INIT:
2072 info->name = __func__;
2073 info->category = TEST_CATEGORY;
2074 info->summary = "Test cdrs for a single party entering Park";
2075 info->description =
2076 "Test the properties of a CDR for calls that are\n"
2077 "answered, enters Park, and leaves it.";
2078 return AST_TEST_NOT_RUN;
2079 case TEST_EXECUTE:
2080 break;
2081 }
2083 CREATE_ALICE_CHANNEL(chan_alice, &alice_caller, &alice_expected);
2084 CREATE_BOB_CHANNEL(chan_bob, &bob_caller, &bob_expected);
2085
2086 ast_channel_lock(chan_alice);
2087 EMULATE_APP_DATA(chan_alice, 1, "Park", "700");
2088 ast_setstate(chan_alice, AST_STATE_UP);
2089 ast_channel_unlock(chan_alice);
2090
2091 ast_channel_lock(chan_bob);
2092 EMULATE_APP_DATA(chan_bob, 1, "Park", "701");
2093 ast_setstate(chan_bob, AST_STATE_UP);
2094 ast_channel_unlock(chan_bob);
2095
2099 "test_cdr", "test_cdr_park", NULL);
2100 ast_test_validate(test, bridge != NULL);
2101
2103 ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
2105 ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE));
2107 ast_bridge_depart(chan_alice);
2108 ast_bridge_depart(chan_bob);
2109
2110 /* And then it hangs up */
2111 HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL);
2113
2114 result = verify_mock_cdr_record(test, &alice_expected, 2);
2115
2116 return result;
2117}
2118
2119
2120AST_TEST_DEFINE(test_cdr_fields)
2121{
2123 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
2124 ao2_cleanup);
2125 char varbuffer[128];
2126 int int_buffer;
2127 double db_buffer;
2128 struct timespec to_sleep = {2, 0};
2129 struct ast_flags fork_options = { 0, };
2130
2131 struct ast_party_caller caller = ALICE_CALLERID;
2132 struct ast_cdr original = {
2133 .clid = "\"Alice\" <100>",
2134 .src = "100",
2135 .dst = "100",
2136 .dcontext = "default",
2137 .channel = CHANNEL_TECH_NAME "/Alice",
2138 .lastapp = "Wait",
2139 .lastdata = "10",
2140 .billsec = 0,
2141 .amaflags = AST_AMA_OMIT,
2142 .disposition = AST_CDR_FAILED,
2143 .accountcode = "XXX",
2144 .userfield = "yackity",
2145 };
2146 struct ast_cdr fork_expected_one = {
2147 .clid = "\"Alice\" <100>",
2148 .src = "100",
2149 .dst = "100",
2150 .dcontext = "default",
2151 .channel = CHANNEL_TECH_NAME "/Alice",
2152 .lastapp = "Wait",
2153 .lastdata = "10",
2154 .billsec = 0,
2155 .amaflags = AST_AMA_OMIT,
2156 .disposition = AST_CDR_FAILED,
2157 .accountcode = "XXX",
2158 .userfield = "yackity",
2159 };
2160 struct ast_cdr fork_expected_two = {
2161 .clid = "\"Alice\" <100>",
2162 .src = "100",
2163 .dst = "100",
2164 .dcontext = "default",
2165 .channel = CHANNEL_TECH_NAME "/Alice",
2166 .lastapp = "Answer",
2167 .billsec = 0,
2168 .amaflags = AST_AMA_OMIT,
2169 .disposition = AST_CDR_ANSWERED,
2170 .accountcode = "ZZZ",
2171 .userfield = "schmackity",
2172 };
2174
2175 struct ast_cdr *expected = &original;
2176 original.next = &fork_expected_one;
2177 fork_expected_one.next = &fork_expected_two;
2178
2179 switch (cmd) {
2180 case TEST_INIT:
2181 info->name = __func__;
2182 info->category = TEST_CATEGORY;
2183 info->summary = "Test field access CDRs";
2184 info->description =
2185 "This tests setting/retrieving data on CDR records.";
2186 return AST_TEST_NOT_RUN;
2187 case TEST_EXECUTE:
2188 break;
2189 }
2190
2192
2193 CREATE_ALICE_CHANNEL(chan, &caller, &original);
2194 ast_copy_string(fork_expected_one.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_one.uniqueid));
2195 ast_copy_string(fork_expected_one.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_one.linkedid));
2196 ast_copy_string(fork_expected_two.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_two.uniqueid));
2197 ast_copy_string(fork_expected_two.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_two.linkedid));
2198
2199 /* Channel enters Wait app */
2200 ast_channel_lock(chan);
2201 ast_channel_appl_set(chan, "Wait");
2202 ast_channel_data_set(chan, "10");
2203 ast_channel_priority_set(chan, 1);
2205
2206 /* Set properties on the channel that propagate to the CDR */
2208 ast_channel_accountcode_set(chan, "XXX");
2209 ast_channel_unlock(chan);
2210
2211 /* Wait one second so we get a duration. */
2213
2214 ast_cdr_setuserfield(ast_channel_name(chan), "foobar");
2215 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_1") == 0);
2216
2217 /* Verify that we can't set read-only fields or other fields directly */
2218 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "clid", "junk") != 0);
2219 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "src", "junk") != 0);
2220 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "dst", "junk") != 0);
2221 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "dcontext", "junk") != 0);
2222 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "channel", "junk") != 0);
2223 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "dstchannel", "junk") != 0);
2224 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "lastapp", "junk") != 0);
2225 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "lastdata", "junk") != 0);
2226 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "start", "junk") != 0);
2227 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "answer", "junk") != 0);
2228 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "end", "junk") != 0);
2229 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "duration", "junk") != 0);
2230 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "billsec", "junk") != 0);
2231 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "disposition", "junk") != 0);
2232 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "amaflags", "junk") != 0);
2233 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "accountcode", "junk") != 0);
2234 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "uniqueid", "junk") != 0);
2235 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "linkedid", "junk") != 0);
2236 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "userfield", "junk") != 0);
2237 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "sequence", "junk") != 0);
2238
2239 /* Verify the values */
2240 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "userfield", varbuffer, sizeof(varbuffer)) == 0);
2241 ast_test_validate(test, strcmp(varbuffer, "foobar") == 0);
2242 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
2243 ast_test_validate(test, strcmp(varbuffer, "record_1") == 0);
2244 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "amaflags", varbuffer, sizeof(varbuffer)) == 0);
2245 sscanf(varbuffer, "%d", &int_buffer);
2246 ast_test_validate(test, int_buffer == AST_AMA_OMIT);
2247 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "accountcode", varbuffer, sizeof(varbuffer)) == 0);
2248 ast_test_validate(test, strcmp(varbuffer, "XXX") == 0);
2249 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "clid", varbuffer, sizeof(varbuffer)) == 0);
2250 ast_test_validate(test, strcmp(varbuffer, "\"Alice\" <100>") == 0);
2251 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "src", varbuffer, sizeof(varbuffer)) == 0);
2252 ast_test_validate(test, strcmp(varbuffer, "100") == 0);
2253 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dst", varbuffer, sizeof(varbuffer)) == 0);
2254 ast_test_validate(test, strcmp(varbuffer, "100") == 0);
2255 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dcontext", varbuffer, sizeof(varbuffer)) == 0);
2256 ast_test_validate(test, strcmp(varbuffer, "default") == 0);
2257 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "channel", varbuffer, sizeof(varbuffer)) == 0);
2258 ast_test_validate(test, strcmp(varbuffer, CHANNEL_TECH_NAME "/Alice") == 0);
2259 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dstchannel", varbuffer, sizeof(varbuffer)) == 0);
2260 ast_test_validate(test, strcmp(varbuffer, "") == 0);
2261 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "lastapp", varbuffer, sizeof(varbuffer)) == 0);
2262 ast_test_validate(test, strcmp(varbuffer, "Wait") == 0);
2263 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "lastdata", varbuffer, sizeof(varbuffer)) == 0);
2264 ast_test_validate(test, strcmp(varbuffer, "10") == 0);
2265 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", varbuffer, sizeof(varbuffer)) == 0);
2266 sscanf(varbuffer, "%lf", &db_buffer);
2267 ast_test_validate(test, fabs(db_buffer) > 0);
2268 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", varbuffer, sizeof(varbuffer)) == 0);
2269 sscanf(varbuffer, "%lf", &db_buffer);
2270 ast_test_validate(test, fabs(db_buffer) < EPSILON);
2271 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "end", varbuffer, sizeof(varbuffer)) == 0);
2272 sscanf(varbuffer, "%lf", &db_buffer);
2273 ast_test_validate(test, fabs(db_buffer) < EPSILON);
2274 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "duration", varbuffer, sizeof(varbuffer)) == 0);
2275 sscanf(varbuffer, "%lf", &db_buffer);
2276 ast_test_validate(test, fabs(db_buffer) > 0);
2277 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "billsec", varbuffer, sizeof(varbuffer)) == 0);
2278 sscanf(varbuffer, "%lf", &db_buffer);
2279 ast_test_validate(test, fabs(db_buffer) < EPSILON);
2280 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "disposition", varbuffer, sizeof(varbuffer)) == 0);
2281 sscanf(varbuffer, "%d", &int_buffer);
2282 ast_test_validate(test, int_buffer == AST_CDR_NULL);
2283 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "uniqueid", varbuffer, sizeof(varbuffer)) == 0);
2284 ast_test_validate(test, strcmp(varbuffer, ast_channel_uniqueid(chan)) == 0);
2285 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "linkedid", varbuffer, sizeof(varbuffer)) == 0);
2286 ast_test_validate(test, strcmp(varbuffer, ast_channel_linkedid(chan)) == 0);
2287 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "sequence", varbuffer, sizeof(varbuffer)) == 0);
2288
2289 /* Fork the CDR, and check that we change the properties on both CDRs. */
2290 ast_set_flag(&fork_options, AST_CDR_FLAG_KEEP_VARS);
2291 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2292
2293 /* Change some properties */
2294 ast_cdr_setuserfield(ast_channel_name(chan), "yackity");
2295 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_1b") == 0);
2296
2297 /* Fork the CDR again, finalizing all current CDRs */
2299 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2300
2301 /* Channel enters Answer app */
2302 ast_channel_lock(chan);
2303 ast_channel_appl_set(chan, "Answer");
2304 ast_channel_data_set(chan, "");
2305 ast_channel_priority_set(chan, 1);
2308
2309 /* Set properties on the last record */
2310 ast_channel_accountcode_set(chan, "ZZZ");
2311 ast_channel_unlock(chan);
2312 ast_cdr_setuserfield(ast_channel_name(chan), "schmackity");
2313 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
2314
2315 /* Hang up and verify */
2317 ast_hangup(chan);
2318 chan = NULL;
2319 result = verify_mock_cdr_record(test, expected, 3);
2320
2321 return result;
2322}
2323
2324AST_TEST_DEFINE(test_cdr_no_reset_cdr)
2325{
2327 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
2328 ao2_cleanup);
2329 struct ast_flags fork_options = { 0, };
2330 struct timespec to_sleep = {1, 0};
2331
2332 struct ast_party_caller caller = ALICE_CALLERID;
2333 struct ast_cdr expected = {
2334 .clid = "\"Alice\" <100>",
2335 .src = "100",
2336 .dst = "100",
2337 .dcontext = "default",
2338 .channel = CHANNEL_TECH_NAME "/Alice",
2339 .billsec = 0,
2340 .amaflags = AST_AMA_DOCUMENTATION,
2341 .disposition = AST_CDR_FAILED,
2342 .accountcode = "100",
2343 };
2345
2346 switch (cmd) {
2347 case TEST_INIT:
2348 info->name = __func__;
2349 info->category = TEST_CATEGORY;
2350 info->summary = "Test field access CDRs";
2351 info->description =
2352 "This tests setting/retrieving data on CDR records.";
2353 return AST_TEST_NOT_RUN;
2354 case TEST_EXECUTE:
2355 break;
2356 }
2357
2359
2360 CREATE_ALICE_CHANNEL(chan, &caller, &expected);
2361
2363
2364 /* Disable the CDR */
2365 ast_test_validate(test, ast_cdr_set_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE) == 0);
2366
2367 /* Fork the CDR. This should be enabled */
2368 ast_set_flag(&fork_options, AST_CDR_FLAG_FINALIZE);
2369 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2370
2371 /* Disable and enable the forked CDR */
2372 ast_test_validate(test, ast_cdr_set_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE) == 0);
2373 ast_test_validate(test, ast_cdr_clear_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE) == 0);
2374
2375 /* Fork and finalize again. This CDR should be propagated */
2376 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2377
2378 /* Disable all future CDRs */
2379 ast_test_validate(test, ast_cdr_set_property(ast_channel_name(chan), AST_CDR_FLAG_DISABLE_ALL) == 0);
2380
2381 /* Fork a few more */
2382 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2383 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2384 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2385
2387 ast_hangup(chan);
2388 chan = NULL;
2389 result = verify_mock_cdr_record(test, &expected, 1);
2390
2391 return result;
2392}
2393
2394AST_TEST_DEFINE(test_cdr_fork_cdr)
2395{
2397 RAII_VAR(struct ast_cdr_config *, config, ao2_alloc(sizeof(*config), NULL),
2398 ao2_cleanup);
2399 char varbuffer[128];
2400 char fork_varbuffer[128];
2401 char answer_time[128];
2402 char fork_answer_time[128];
2403 char start_time[128];
2404 char fork_start_time[128];
2405 struct ast_flags fork_options = { 0, };
2406 struct timespec to_sleep = {1, 10000};
2407
2408 struct ast_party_caller caller = ALICE_CALLERID;
2409 struct ast_cdr original = {
2410 .clid = "\"Alice\" <100>",
2411 .src = "100",
2412 .dst = "100",
2413 .dcontext = "default",
2414 .channel = CHANNEL_TECH_NAME "/Alice",
2415 .amaflags = AST_AMA_DOCUMENTATION,
2416 .disposition = AST_CDR_ANSWERED,
2417 .accountcode = "100",
2418 };
2419 struct ast_cdr fork_expected_one = {
2420 .clid = "\"Alice\" <100>",
2421 .src = "100",
2422 .dst = "100",
2423 .dcontext = "default",
2424 .channel = CHANNEL_TECH_NAME "/Alice",
2425 .amaflags = AST_AMA_DOCUMENTATION,
2426 .disposition = AST_CDR_ANSWERED,
2427 .accountcode = "100",
2428 };
2429 struct ast_cdr fork_expected_two = {
2430 .clid = "\"Alice\" <100>",
2431 .src = "100",
2432 .dst = "100",
2433 .dcontext = "default",
2434 .channel = CHANNEL_TECH_NAME "/Alice",
2435 .amaflags = AST_AMA_DOCUMENTATION,
2436 .disposition = AST_CDR_ANSWERED,
2437 .accountcode = "100",
2438 };
2440 struct ast_cdr *expected = &original;
2441 original.next = &fork_expected_one;
2442 fork_expected_one.next = &fork_expected_two;
2443
2444 switch (cmd) {
2445 case TEST_INIT:
2446 info->name = __func__;
2447 info->category = TEST_CATEGORY;
2448 info->summary = "Test field access CDRs";
2449 info->description =
2450 "This tests setting/retrieving data on CDR records.";
2451 return AST_TEST_NOT_RUN;
2452 case TEST_EXECUTE:
2453 break;
2454 }
2455
2457
2458 CREATE_ALICE_CHANNEL(chan, &caller, &original);
2459 ast_copy_string(fork_expected_one.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_one.uniqueid));
2460 ast_copy_string(fork_expected_one.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_one.linkedid));
2461 ast_copy_string(fork_expected_two.uniqueid, ast_channel_uniqueid(chan), sizeof(fork_expected_two.uniqueid));
2462 ast_copy_string(fork_expected_two.linkedid, ast_channel_linkedid(chan), sizeof(fork_expected_two.linkedid));
2463
2465
2466 /* Test blowing away variables */
2467 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_1") == 0);
2468 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
2469 ast_test_validate(test, strcmp(varbuffer, "record_1") == 0);
2470 ast_copy_string(varbuffer, "", sizeof(varbuffer));
2471
2472 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2473 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", fork_varbuffer, sizeof(fork_varbuffer)) == 0);
2474 ast_test_validate(test, strcmp(varbuffer, "record_1") != 0);
2475
2476 /* Test finalizing previous CDRs */
2477 ast_set_flag(&fork_options, AST_CDR_FLAG_FINALIZE);
2478 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2479
2480 /* Test keep variables; setting a new answer time */
2481 ast_channel_lock(chan);
2483 ast_channel_unlock(chan);
2485 ast_test_validate(test, ast_cdr_setvar(ast_channel_name(chan), "test_variable", "record_2") == 0);
2486 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", varbuffer, sizeof(varbuffer)) == 0);
2487 ast_test_validate(test, strcmp(varbuffer, "record_2") == 0);
2488 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", answer_time, sizeof(answer_time)) == 0);
2489 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", start_time, sizeof(start_time)) == 0);
2490
2491 ast_set_flag(&fork_options, AST_CDR_FLAG_FINALIZE);
2492 ast_set_flag(&fork_options, AST_CDR_FLAG_KEEP_VARS);
2493 ast_set_flag(&fork_options, AST_CDR_FLAG_SET_ANSWER);
2494 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2495 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", fork_answer_time, sizeof(fork_answer_time)) == 0);
2496 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", fork_start_time, sizeof(fork_start_time)) == 0);
2497 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", fork_varbuffer, sizeof(fork_varbuffer)) == 0);
2498 ast_test_validate(test, strcmp(fork_varbuffer, varbuffer) == 0);
2499 ast_test_validate(test, strcmp(fork_start_time, start_time) == 0);
2500 ast_test_validate(test, strcmp(fork_answer_time, answer_time) != 0);
2501
2503 ast_set_flag(&fork_options, AST_CDR_FLAG_RESET);
2504 ast_test_validate(test, ast_cdr_fork(ast_channel_name(chan), &fork_options) == 0);
2505 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", fork_answer_time, sizeof(fork_answer_time)) == 0);
2506 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", fork_start_time, sizeof(fork_start_time)) == 0);
2507 ast_test_validate(test, strcmp(fork_start_time, start_time) != 0);
2508 ast_test_validate(test, strcmp(fork_answer_time, answer_time) != 0);
2509
2511 ast_hangup(chan);
2512 chan = NULL;
2513 result = verify_mock_cdr_record(test, expected, 3);
2514
2515 return result;
2516}
2517
2518/*!
2519 * \internal
2520 * \brief Callback function called before each test executes
2521 */
2522static int test_cdr_init_cb(struct ast_test_info *info, struct ast_test *test)
2523{
2524 /* Back up the real config */
2527 return 0;
2528}
2529
2530/*!
2531 * \internal
2532 * \brief Callback function called after each test executes
2533 */
2534static int test_cdr_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
2535{
2536 /* Restore the real config */
2541
2542 return 0;
2543}
2544
2545
2546static int unload_module(void)
2547{
2548 AST_TEST_UNREGISTER(test_cdr_channel_creation);
2549 AST_TEST_UNREGISTER(test_cdr_unanswered_inbound_call);
2550 AST_TEST_UNREGISTER(test_cdr_unanswered_outbound_call);
2551
2552 AST_TEST_UNREGISTER(test_cdr_single_party);
2553 AST_TEST_UNREGISTER(test_cdr_single_bridge);
2554 AST_TEST_UNREGISTER(test_cdr_single_bridge_continue);
2555 AST_TEST_UNREGISTER(test_cdr_single_twoparty_bridge_a);
2556 AST_TEST_UNREGISTER(test_cdr_single_twoparty_bridge_b);
2557 AST_TEST_UNREGISTER(test_cdr_single_multiparty_bridge);
2558
2559 AST_TEST_UNREGISTER(test_cdr_outbound_bridged_call);
2560
2561 AST_TEST_UNREGISTER(test_cdr_dial_unanswered);
2562 AST_TEST_UNREGISTER(test_cdr_dial_congestion);
2563 AST_TEST_UNREGISTER(test_cdr_dial_busy);
2564 AST_TEST_UNREGISTER(test_cdr_dial_unavailable);
2565 AST_TEST_UNREGISTER(test_cdr_dial_caller_cancel);
2566 AST_TEST_UNREGISTER(test_cdr_dial_parallel_failed);
2567 AST_TEST_UNREGISTER(test_cdr_dial_answer_no_bridge);
2568 AST_TEST_UNREGISTER(test_cdr_dial_answer_twoparty_bridge_a);
2569 AST_TEST_UNREGISTER(test_cdr_dial_answer_twoparty_bridge_b);
2570 AST_TEST_UNREGISTER(test_cdr_dial_answer_multiparty);
2571
2572 AST_TEST_UNREGISTER(test_cdr_park);
2573
2574 AST_TEST_UNREGISTER(test_cdr_fields);
2575 AST_TEST_UNREGISTER(test_cdr_no_reset_cdr);
2576 AST_TEST_UNREGISTER(test_cdr_fork_cdr);
2577
2581
2582 return 0;
2583}
2584
2585static int load_module(void)
2586{
2588
2589 AST_TEST_REGISTER(test_cdr_channel_creation);
2590 AST_TEST_REGISTER(test_cdr_unanswered_inbound_call);
2591 AST_TEST_REGISTER(test_cdr_unanswered_outbound_call);
2592
2593 AST_TEST_REGISTER(test_cdr_single_party);
2594 AST_TEST_REGISTER(test_cdr_single_bridge);
2595 AST_TEST_REGISTER(test_cdr_single_bridge_continue);
2596 AST_TEST_REGISTER(test_cdr_single_twoparty_bridge_a);
2597 AST_TEST_REGISTER(test_cdr_single_twoparty_bridge_b);
2598 AST_TEST_REGISTER(test_cdr_single_multiparty_bridge);
2599
2600 AST_TEST_REGISTER(test_cdr_outbound_bridged_call);
2601
2602 AST_TEST_REGISTER(test_cdr_dial_unanswered);
2603 AST_TEST_REGISTER(test_cdr_dial_congestion);
2604 AST_TEST_REGISTER(test_cdr_dial_busy);
2605 AST_TEST_REGISTER(test_cdr_dial_unavailable);
2606 AST_TEST_REGISTER(test_cdr_dial_caller_cancel);
2607 AST_TEST_REGISTER(test_cdr_dial_parallel_failed);
2608 AST_TEST_REGISTER(test_cdr_dial_answer_no_bridge);
2609 AST_TEST_REGISTER(test_cdr_dial_answer_twoparty_bridge_a);
2610 AST_TEST_REGISTER(test_cdr_dial_answer_twoparty_bridge_b);
2611 AST_TEST_REGISTER(test_cdr_dial_answer_multiparty);
2612
2613 AST_TEST_REGISTER(test_cdr_park);
2614
2615 AST_TEST_REGISTER(test_cdr_fields);
2616 AST_TEST_REGISTER(test_cdr_no_reset_cdr);
2617 AST_TEST_REGISTER(test_cdr_fork_cdr);
2618
2619 ast_test_register_init(TEST_CATEGORY, test_cdr_init_cb);
2620 ast_test_register_cleanup(TEST_CATEGORY, test_cdr_cleanup_cb);
2621
2624
2626}
2627
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
Bridging API.
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
Definition: bridge.c:1906
struct ast_bridge * ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Create a new base class bridge.
Definition: bridge.c:934
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:944
int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, enum ast_bridge_impart_flags flags) attribute_warn_unused_result
Impart a channel to a bridge (non-blocking)
Definition: bridge.c:1878
@ AST_BRIDGE_CAPABILITY_HOLDING
Definition: bridge.h:86
@ AST_BRIDGE_IMPART_CHAN_DEPARTABLE
Definition: bridge.h:588
Basic bridge subclass API.
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
@ AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM
@ AST_BRIDGE_FLAG_TRANSFER_PROHIBITED
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_TO
@ AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
Internal Asterisk hangup causes.
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_NORMAL
Definition: causes.h:151
#define AST_CAUSE_NO_ROUTE_DESTINATION
Definition: causes.h:100
#define AST_CAUSE_BUSY
Definition: causes.h:149
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:109
Call Detail Record API.
void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:3539
void ast_cdr_free(struct ast_cdr *cdr)
Free a CDR record.
Definition: cdr.c:3473
@ CDR_UNANSWERED
Definition: cdr.h:222
@ CDR_ENABLED
Definition: cdr.h:220
@ CDR_CHANNEL_DEFAULT_ENABLED
Definition: cdr.h:227
@ CDR_CONGESTION
Definition: cdr.h:223
@ CDR_DEBUG
Definition: cdr.h:226
void ast_cdr_set_config(struct ast_cdr_config *config)
Set the current CDR configuration.
Definition: cdr.c:2902
int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
Clear a property on a CDR for a channel.
Definition: cdr.c:3637
int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
Set a variable on a CDR.
Definition: cdr.c:3240
@ AST_CDR_CONGESTION
Definition: cdr.h:262
@ AST_CDR_NULL
Definition: cdr.h:258
@ AST_CDR_NOANSWER
Definition: cdr.h:257
@ AST_CDR_ANSWERED
Definition: cdr.h:261
@ AST_CDR_BUSY
Definition: cdr.h:260
@ AST_CDR_FAILED
Definition: cdr.h:259
@ AST_CDR_FLAG_DISABLE_ALL
Definition: cdr.h:245
@ AST_CDR_FLAG_FINALIZE
Definition: cdr.h:247
@ AST_CDR_FLAG_DISABLE
Definition: cdr.h:244
@ AST_CDR_FLAG_KEEP_VARS
Definition: cdr.h:243
@ AST_CDR_FLAG_RESET
Definition: cdr.h:249
@ AST_CDR_FLAG_SET_ANSWER
Definition: cdr.h:248
int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
Fork a CDR.
Definition: cdr.c:3699
int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
Retrieve a CDR variable from a channel's current CDR.
Definition: cdr.c:3386
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:3050
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:3005
struct ast_cdr_config * ast_cdr_get_config(void)
Obtain the current CDR configuration.
Definition: cdr.c:2888
int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
Set a property on a CDR for a channel.
Definition: cdr.c:3610
static PGresult * result
Definition: cel_pgsql.c:84
static int amaflags
Definition: chan_iax2.c:476
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:473
static const char config[]
Definition: chan_ooh323.c:111
static int answer(void *data)
Definition: chan_pjsip.c:683
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
const char * ast_channel_linkedid(const struct ast_channel *chan)
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_appl_set(struct ast_channel *chan, const char *value)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
#define ast_channel_lock(chan)
Definition: channel.h:2922
void ast_channel_data_set(struct ast_channel *chan, const char *value)
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
@ AST_AMA_DOCUMENTATION
Definition: channel.h:1181
@ AST_AMA_OMIT
Definition: channel.h:1179
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1584
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
void ast_channel_state_set(struct ast_channel *chan, enum ast_channel_state)
@ AST_FLAG_OUTGOING
Definition: channel.h:999
@ AST_FLAG_ORIGINATED
Definition: channel.h:1039
void ast_channel_priority_set(struct ast_channel *chan, int value)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_UP
Definition: channelstate.h:42
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7386
Channel Variables.
#define ast_var_assign(name, value)
Definition: chanvars.h:40
char * end
Definition: eagi_proxy.c:73
Media Format Cache API.
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
void ast_channel_publish_snapshot(struct ast_channel *chan)
Publish a ast_channel_snapshot for a channel.
A set of macros to manage forward-linked lists.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_HEAD_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD.
Definition: linkedlists.h:234
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Definition: linkedlists.h:173
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
pthread_cond_t ast_cond_t
Definition: lock.h:178
#define ast_cond_signal(cond)
Definition: lock.h:203
int errno
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
#define NULL
Definition: resample.c:96
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Structure that contains information about a bridge.
Definition: bridge.h:349
The global options available for CDRs.
Definition: cdr.h:267
struct ast_flags settings
Definition: cdr.h:268
Responsible for call detail data.
Definition: cdr.h:279
char dstchannel[AST_MAX_EXTENSION]
Definition: cdr.h:291
char linkedid[AST_MAX_UNIQUEID]
Definition: cdr.h:319
long int billsec
Definition: cdr.h:305
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:289
struct ast_cdr * next
Definition: cdr.h:328
struct varshead varshead
Definition: cdr.h:326
char clid[AST_MAX_EXTENSION]
Definition: cdr.h:281
char uniqueid[AST_MAX_UNIQUEID]
Definition: cdr.h:317
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:628
const char *const type
Definition: channel.h:629
Main Channel structure associated with a channel.
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
Caller Party information.
Definition: channel.h:418
struct ast_party_id id
Caller party ID.
Definition: channel.h:420
struct ast_party_name name
Subscriber name.
Definition: channel.h:340
char * str
Subscriber name (Malloced)
Definition: channel.h:264
Contains all the initialization information required to store a new test definition.
Definition: test.h:235
char name[0]
Definition: chanvars.h:31
char * value
Definition: chanvars.h:30
struct ast_var_t::@211 entries
Definition: test_cdr.c:96
struct ast_cdr * cdr
Definition: test_cdr.c:97
struct test_cdr_entry::@493 list
struct ast_var_t * last
Definition: chanvars.h:34
struct ast_var_t * first
Definition: chanvars.h:34
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define ast_test_debug(test, fmt,...)
Definition: test.h:130
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
ast_test_result_state
Definition: test.h:193
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
#define EPSILON
Definition: test_cdr.c:49
static struct @492 actual_cdr_entries
A linked list of received CDR entries from the engine.
#define COPY_IDS(channel_var, expected_record)
Copy the linkedid and uniqueid from a channel to an expected CDR.
Definition: test_cdr.c:228
#define VERIFY_STRING_FIELD(field, actual, expected)
Verify a string field. This will set the test status result to fail; as such, it assumes that (a) tes...
Definition: test_cdr.c:186
#define SWAP_CONFIG(ao2_config, template)
Macro to swap a configuration out from the CDR engine. This should be used at the beginning of each t...
Definition: test_cdr.c:79
#define CREATE_ALICE_CHANNEL(channel_var, caller_id, expected_record)
Create a test_cdr_chan_tech for Alice, and set the expected CDR records' linkedid and uniqueid.
Definition: test_cdr.c:248
static int global_mock_cdr_count
The number of CDRs the mock backend has received.
Definition: test_cdr.c:102
#define CREATE_BOB_CHANNEL(channel_var, caller_id, expected_record)
Create a test_cdr_chan_tech for Bob, and set the expected CDR records' linkedid and uniqueid.
Definition: test_cdr.c:259
static void safe_bridge_destroy(struct ast_bridge *bridge)
Definition: test_cdr.c:379
#define VERIFY_NUMERIC_FIELD(field, actual, expected)
Verify a numeric field. This will set the test status result to fail; as such, it assumes that (a) te...
Definition: test_cdr.c:197
static void clear_mock_cdr_backend(void)
Definition: test_cdr.c:169
static struct ast_cdr_config unanswered_cdr_config
A configuration suitable for CDRs with unanswered records.
Definition: test_cdr.c:66
#define BOB_CALLERID
Bob's Caller ID.
Definition: test_cdr.c:219
static void do_sleep(struct timespec *to_sleep)
Definition: test_cdr.c:387
#define SET_FORMATS(chan)
Set ulaw format on channel.
Definition: test_cdr.c:234
AST_TEST_DEFINE(test_cdr_channel_creation)
Definition: test_cdr.c:393
static int test_cdr_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
Definition: test_cdr.c:2534
static ast_cond_t mock_cdr_cond
The Mock CDR backend condition wait.
Definition: test_cdr.c:88
static int mock_cdr_backend_cb(struct ast_cdr *cdr)
Definition: test_cdr.c:116
#define CREATE_CHARLIE_CHANNEL(channel_var, caller_id, expected_record)
Create a test_cdr_chan_tech for Charlie, and set the expected CDR records' linkedid and uniqueid.
Definition: test_cdr.c:270
#define CHANNEL_TECH_NAME
Definition: test_cdr.c:55
#define ALICE_CALLERID
Alice's Caller ID.
Definition: test_cdr.c:216
static void safe_channel_release(struct ast_channel *chan)
Definition: test_cdr.c:371
static enum ast_test_result_state verify_mock_cdr_record(struct ast_test *test, struct ast_cdr *expected, int record)
Definition: test_cdr.c:310
static int test_cdr_init_cb(struct ast_test_info *info, struct ast_test *test)
Definition: test_cdr.c:2522
static struct ast_cdr_config * saved_config
A placeholder for Asterisk's 'real' CDR configuration.
Definition: test_cdr.c:58
static struct ast_channel_tech test_cdr_chan_tech
A channel technology used for the unit tests.
Definition: test_cdr.c:91
#define EMULATE_APP_DATA(channel, priority, application, data)
Emulate a channel entering into an application.
Definition: test_cdr.c:291
#define HANGUP_CHANNEL(channel, cause)
Hang up a test channel safely.
Definition: test_cdr.c:303
static int load_module(void)
Definition: test_cdr.c:2585
static struct ast_cdr_config debug_cdr_config
A configuration suitable for 'normal' CDRs.
Definition: test_cdr.c:61
static int unload_module(void)
Definition: test_cdr.c:2546
#define MOCK_CDR_BACKEND
Definition: test_cdr.c:53
#define TEST_CATEGORY
Definition: test_cdr.c:51
#define VERIFY_TIME_VALUE(field, actual)
Verify a time field. This will set the test status result to fail; as such, it assumes that (a) test ...
Definition: test_cdr.c:208
#define CHARLIE_CALLERID
Charlie's Caller ID.
Definition: test_cdr.c:222
static struct ast_cdr_config congestion_cdr_config
A configuration suitable for CDRs with congestion enabled.
Definition: test_cdr.c:71
static struct timespec to_sleep
A 1 second sleep.
Definition: test_cel.c:85
Time-related functions and macros.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
Utility functions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70