51#define TEST_CATEGORY "/main/cdr/"
53#define MOCK_CDR_BACKEND "mock_cdr_backend"
55#define CHANNEL_TECH_NAME "CDRTestChannel"
79#define SWAP_CONFIG(ao2_config, template) do { \
80 *(ao2_config) = (template); \
81 ast_cdr_set_config((ao2_config)); \
93 .description =
"Mock channel technology for CDR tests",
122 cdr_wrapper =
ast_calloc(1,
sizeof(*cdr_wrapper));
151 cdr_prev->
next = cdr_copy;
155 cdr_wrapper->
cdr = mock_cdr;
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; \
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; \
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; \
216#define ALICE_CALLERID { .id.name.str = "Alice", .id.name.valid = 1, .id.number.str = "100", .id.number.valid = 1, }
219#define BOB_CALLERID { .id.name.str = "Bob", .id.name.valid = 1, .id.number.str = "200", .id.number.valid = 1, }
222#define CHARLIE_CALLERID { .id.name.str = "Charlie", .id.name.valid = 1, .id.number.str = "300", .id.number.valid = 1, }
225#define DAVID_CALLERID { .id.name.str = "David", .id.name.valid = 1, .id.number.str = "400", .id.number.valid = 1, }
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)); \
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);\
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)); \
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)); \
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)); \
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)); \
291#define EMULATE_APP_DATA(channel, priority, application, data) do { \
292 if ((priority) > 0) { \
293 ast_channel_priority_set((channel), (priority)); \
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)); \
303#define HANGUP_CHANNEL(channel, cause) \
305 ast_channel_hangupcause_set((channel), (cause)); \
306 ast_hangup(channel); \
316 struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 5, .tv_nsec = wait_now.tv_usec * 1000 };
319 while (count < record) {
331 actual = cdr_wrapper->
cdr;
333 if (!expected && actual) {
365 expected = expected->
next;
401 .
clid =
"\"Alice\" <100>",
404 .dcontext =
"default",
408 .accountcode =
"100",
414 info->name = __func__;
416 info->summary =
"Test that a CDR is created when a channel is created";
418 "Test that a CDR is created when a channel is created";
443 .
clid =
"\"Alice\" <100>",
446 .dcontext =
"default",
452 .accountcode =
"100",
458 info->name = __func__;
460 info->summary =
"Test inbound unanswered calls";
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.";
493 .id.number.valid = 1, };
497 .dcontext =
"default",
499 .lastapp =
"AppDial",
500 .lastdata =
"(Outgoing Line)",
503 .accountcode =
"100",
509 info->name = __func__;
511 info->summary =
"Test outbound unanswered calls";
513 "Test the properties of a CDR for a call that is\n"
514 "outbound to Asterisk but is never answered.";
546 struct ast_cdr alice_expected = {
547 .
clid =
"\"Alice\" <100>",
550 .dcontext =
"default",
558 .accountcode =
"100",
559 .peeraccount =
"200",
561 struct ast_cdr bob_expected = {
565 .dcontext =
"default",
568 .lastapp =
"AppDial",
569 .lastdata =
"(Outgoing Line)",
573 .accountcode =
"200",
575 .next = &alice_expected,
580 info->name = __func__;
582 info->summary =
"Test dialing, answering, and going into a 2-party bridge";
584 "The most 'basic' of scenarios";
596 ast_test_validate(
test, bridge !=
NULL);
601 chan_bob =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_alice, 0,
CHANNEL_TECH_NAME "/Bob");
641 .
clid =
"\"Alice\" <100>",
644 .dcontext =
"default",
647 .lastapp =
"VoiceMailMain",
652 .accountcode =
"100",
658 info->name = __func__;
660 info->summary =
"Test cdrs for a single party";
662 "Test the properties of a CDR for a call that is\n"
663 "answered, but only involves a single channel";
694 .
clid =
"\"Alice\" <100>",
697 .dcontext =
"default",
703 .accountcode =
"100",
709 info->name = __func__;
711 info->summary =
"Test cdrs for a single party entering/leaving a bridge";
713 "Test the properties of a CDR for a call that is\n"
714 "answered, enters a bridge, and leaves it.";
729 ast_test_validate(
test, bridge !=
NULL);
754 struct ast_cdr expected_two = {
755 .
clid =
"\"Alice\" <100>",
758 .dcontext =
"default",
764 .accountcode =
"100",
766 struct ast_cdr expected_one = {
767 .
clid =
"\"Alice\" <100>",
770 .dcontext =
"default",
776 .accountcode =
"100",
777 .next = &expected_two,
784 info->name = __func__;
786 info->summary =
"Test cdrs for a single party entering/leaving a bridge";
788 "Test the properties of a CDR for a call that is\n"
789 "answered, enters a bridge, and leaves it.";
805 ast_test_validate(
test, bridge !=
NULL);
835 struct ast_cdr bob_expected = {
836 .
clid =
"\"Bob\" <200>",
839 .dcontext =
"default",
845 .accountcode =
"200",
847 struct ast_cdr alice_expected = {
848 .
clid =
"\"Alice\" <100>",
851 .dcontext =
"default",
858 .accountcode =
"100",
859 .peeraccount =
"200",
860 .next = &bob_expected,
867 info->name = __func__;
869 info->summary =
"Test cdrs for a single party entering/leaving a bridge";
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.";
891 ast_test_validate(
test, bridge !=
NULL);
927 struct ast_cdr bob_expected = {
928 .
clid =
"\"Bob\" <200>",
931 .dcontext =
"default",
937 .accountcode =
"200",
939 struct ast_cdr alice_expected = {
940 .
clid =
"\"Alice\" <100>",
943 .dcontext =
"default",
950 .accountcode =
"100",
951 .peeraccount =
"200",
952 .next = &bob_expected,
959 info->name = __func__;
961 info->summary =
"Test cdrs for a single party entering/leaving a bridge";
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.";
983 ast_test_validate(
test, bridge !=
NULL);
1022 struct ast_cdr charlie_expected = {
1023 .
clid =
"\"Charlie\" <300>",
1026 .dcontext =
"default",
1028 .lastapp =
"Bridge",
1032 .accountcode =
"300",
1034 struct ast_cdr bob_expected = {
1035 .
clid =
"\"Bob\" <200>",
1038 .dcontext =
"default",
1041 .lastapp =
"Bridge",
1045 .accountcode =
"200",
1046 .peeraccount =
"300",
1047 .next = &charlie_expected,
1049 struct ast_cdr alice_expected_two = {
1050 .
clid =
"\"Alice\" <100>",
1053 .dcontext =
"default",
1056 .lastapp =
"Bridge",
1060 .accountcode =
"100",
1061 .peeraccount =
"300",
1062 .next = &bob_expected,
1064 struct ast_cdr alice_expected_one = {
1065 .
clid =
"\"Alice\" <100>",
1068 .dcontext =
"default",
1071 .lastapp =
"Bridge",
1075 .accountcode =
"100",
1076 .peeraccount =
"200",
1077 .next = &alice_expected_two,
1084 info->name = __func__;
1086 info->summary =
"Test cdrs for a single party entering/leaving a multi-party bridge";
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.";
1097 COPY_IDS(chan_alice, &alice_expected_two);
1110 ast_test_validate(
test, bridge !=
NULL);
1157 .
clid =
"\"Alice\" <100>",
1160 .dcontext =
"default",
1168 .accountcode =
"100",
1169 .peeraccount =
"200",
1175 info->name = __func__;
1177 info->summary =
"Test CDRs for a dial that isn't answered";
1179 "Test the properties of a CDR for a channel that\n"
1180 "performs a dial operation that isn't answered";
1192 chan_callee =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Bob");
1220 .
clid =
"\"Alice\" <100>",
1223 .dcontext =
"default",
1231 .accountcode =
"100",
1232 .peeraccount =
"200",
1238 info->name = __func__;
1240 info->summary =
"Test CDRs for a dial that results in a busy";
1242 "Test the properties of a CDR for a channel that\n"
1243 "performs a dial operation to an endpoint that's busy";
1255 chan_callee =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Bob");
1282 .
clid =
"\"Alice\" <100>",
1285 .dcontext =
"default",
1293 .accountcode =
"100",
1294 .peeraccount =
"200",
1300 info->name = __func__;
1302 info->summary =
"Test CDRs for a dial that results in congestion";
1304 "Test the properties of a CDR for a channel that\n"
1305 "performs a dial operation to an endpoint that's congested";
1317 chan_callee =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Bob");
1344 .
clid =
"\"Alice\" <100>",
1347 .dcontext =
"default",
1355 .accountcode =
"100",
1356 .peeraccount =
"200",
1362 info->name = __func__;
1364 info->summary =
"Test CDRs for a dial that results in unavailable";
1366 "Test the properties of a CDR for a channel that\n"
1367 "performs a dial operation to an endpoint that's unavailable";
1379 chan_callee =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Bob");
1406 .
clid =
"\"Alice\" <100>",
1409 .dcontext =
"default",
1417 .accountcode =
"100",
1418 .peeraccount =
"200",
1424 info->name = __func__;
1426 info->summary =
"Test CDRs for a dial where the caller cancels";
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";
1442 chan_callee =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Bob");
1470 struct ast_cdr bob_expected = {
1471 .
clid =
"\"Alice\" <100>",
1474 .dcontext =
"default",
1482 .accountcode =
"100",
1483 .peeraccount =
"200",
1485 struct ast_cdr charlie_expected = {
1486 .
clid =
"\"Alice\" <100>",
1489 .dcontext =
"default",
1497 .accountcode =
"100",
1498 .peeraccount =
"300",
1500 struct ast_cdr david_expected = {
1501 .
clid =
"\"Alice\" <100>",
1504 .dcontext =
"default",
1512 .accountcode =
"100",
1513 .peeraccount =
"400",
1517 struct ast_cdr *expected = &bob_expected;
1518 bob_expected.
next = &charlie_expected;
1519 charlie_expected.
next = &david_expected;
1523 info->name = __func__;
1525 info->summary =
"Test a parallel dial where all channels fail to answer";
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.";
1538 COPY_IDS(chan_caller, &charlie_expected);
1539 COPY_IDS(chan_caller, &david_expected);
1545 chan_bob =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Bob");
1551 chan_charlie =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"300",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Charlie");
1557 chan_david =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"400",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/David");
1597 struct ast_cdr bob_expected_one = {
1601 .dcontext =
"default",
1607 .accountcode =
"200",
1609 struct ast_cdr alice_expected_two = {
1610 .
clid =
"\"Alice\" <100>",
1613 .dcontext =
"default",
1619 .accountcode =
"100",
1620 .next = &bob_expected_one,
1622 struct ast_cdr alice_expected_one = {
1623 .
clid =
"\"Alice\" <100>",
1626 .dcontext =
"default",
1633 .accountcode =
"100",
1634 .peeraccount =
"200",
1635 .next = &alice_expected_two,
1641 info->name = __func__;
1643 info->summary =
"Test dialing, answering, and not going into a bridge.";
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"
1660 COPY_IDS(chan_caller, &alice_expected_two);
1664 chan_callee =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Bob");
1668 COPY_IDS(chan_callee, &bob_expected_one);
1700 .
clid =
"\"Alice\" <100>",
1703 .dcontext =
"default",
1711 .accountcode =
"100",
1712 .peeraccount =
"200",
1717 info->name = __func__;
1719 info->summary =
"Test dialing, answering, and going into a 2-party bridge";
1721 "The most 'basic' of scenarios";
1733 chan_callee =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Bob");
1747 ast_test_validate(
test, bridge !=
NULL);
1777 .
clid =
"\"Alice\" <100>",
1780 .dcontext =
"default",
1788 .accountcode =
"100",
1789 .peeraccount =
"200",
1794 info->name = __func__;
1796 info->summary =
"Test dialing, answering, and going into a 2-party bridge";
1798 "The most 'basic' of scenarios";
1810 chan_callee =
ast_channel_alloc(0,
AST_STATE_DOWN,
NULL,
NULL,
"200",
NULL,
NULL,
NULL, chan_caller, 0,
CHANNEL_TECH_NAME "/Bob");
1824 ast_test_validate(
test, bridge !=
NULL);
1854 struct ast_cdr charlie_expected_two = {
1855 .
clid =
"\"Charlie\" <300>",
1858 .dcontext =
"default",
1866 .accountcode =
"300",
1867 .peeraccount =
"200",
1869 struct ast_cdr charlie_expected_one = {
1870 .
clid =
"\"Charlie\" <300>",
1873 .dcontext =
"default",
1881 .accountcode =
"300",
1882 .peeraccount =
"400",
1883 .next = &charlie_expected_two,
1885 struct ast_cdr bob_expected_one = {
1886 .
clid =
"\"Bob\" <200>",
1889 .dcontext =
"default",
1892 .lastapp =
"AppDial",
1893 .lastdata =
"(Outgoing Line)",
1897 .accountcode =
"200",
1898 .peeraccount =
"400",
1899 .next = &charlie_expected_one,
1901 struct ast_cdr alice_expected_three = {
1902 .
clid =
"\"Alice\" <100>",
1905 .dcontext =
"default",
1913 .accountcode =
"100",
1914 .peeraccount =
"400",
1915 .next = &bob_expected_one,
1917 struct ast_cdr alice_expected_two = {
1918 .
clid =
"\"Alice\" <100>",
1921 .dcontext =
"default",
1929 .accountcode =
"100",
1930 .peeraccount =
"300",
1931 .next = &alice_expected_three,
1933 struct ast_cdr alice_expected_one = {
1934 .
clid =
"\"Alice\" <100>",
1937 .dcontext =
"default",
1945 .accountcode =
"100",
1946 .peeraccount =
"200",
1947 .next = &alice_expected_two,
1952 info->name = __func__;
1954 info->summary =
"Test dialing, answering, and going into a multi-party bridge";
1956 "A little tricky to get to do, but possible with some redirects.";
1965 COPY_IDS(chan_alice, &alice_expected_two);
1966 COPY_IDS(chan_alice, &alice_expected_three);
1970 chan_bob =
ast_channel_alloc(0,
AST_STATE_DOWN,
"200",
"Bob",
"200",
"200",
"default",
NULL,
NULL, 0,
CHANNEL_TECH_NAME "/Bob");
1985 chan_david =
ast_channel_alloc(0,
AST_STATE_DOWN,
"400",
"David",
"400",
"400",
"default",
NULL,
NULL, 0,
CHANNEL_TECH_NAME "/David");
2004 ast_test_validate(
test, bridge !=
NULL);
2041 struct ast_cdr bob_expected = {
2042 .
clid =
"\"Bob\" <200>",
2045 .dcontext =
"default",
2052 .accountcode =
"200",
2054 struct ast_cdr alice_expected = {
2055 .
clid =
"\"Alice\" <100>",
2058 .dcontext =
"default",
2065 .accountcode =
"100",
2066 .next = &bob_expected,
2072 info->name = __func__;
2074 info->summary =
"Test cdrs for a single party entering Park";
2076 "Test the properties of a CDR for calls that are\n"
2077 "answered, enters Park, and leaves it.";
2099 "test_cdr",
"test_cdr_park",
NULL);
2100 ast_test_validate(
test, bridge !=
NULL);
2125 char varbuffer[128];
2133 .
clid =
"\"Alice\" <100>",
2136 .dcontext =
"default",
2143 .accountcode =
"XXX",
2144 .userfield =
"yackity",
2146 struct ast_cdr fork_expected_one = {
2147 .
clid =
"\"Alice\" <100>",
2150 .dcontext =
"default",
2157 .accountcode =
"XXX",
2158 .userfield =
"yackity",
2160 struct ast_cdr fork_expected_two = {
2161 .
clid =
"\"Alice\" <100>",
2164 .dcontext =
"default",
2166 .lastapp =
"Answer",
2170 .accountcode =
"ZZZ",
2171 .userfield =
"schmackity",
2175 struct ast_cdr *expected = &original;
2176 original.
next = &fork_expected_one;
2177 fork_expected_one.
next = &fork_expected_two;
2181 info->name = __func__;
2183 info->summary =
"Test field access CDRs";
2185 "This tests setting/retrieving data on CDR records.";
2208 ast_channel_accountcode_set(chan,
"XXX");
2241 ast_test_validate(
test, strcmp(varbuffer,
"foobar") == 0);
2243 ast_test_validate(
test, strcmp(varbuffer,
"record_1") == 0);
2245 sscanf(varbuffer,
"%d", &int_buffer);
2248 ast_test_validate(
test, strcmp(varbuffer,
"XXX") == 0);
2250 ast_test_validate(
test, strcmp(varbuffer,
"\"Alice\" <100>") == 0);
2252 ast_test_validate(
test, strcmp(varbuffer,
"100") == 0);
2254 ast_test_validate(
test, strcmp(varbuffer,
"100") == 0);
2256 ast_test_validate(
test, strcmp(varbuffer,
"default") == 0);
2260 ast_test_validate(
test, strcmp(varbuffer,
"") == 0);
2262 ast_test_validate(
test, strcmp(varbuffer,
"Wait") == 0);
2264 ast_test_validate(
test, strcmp(varbuffer,
"10") == 0);
2266 sscanf(varbuffer,
"%lf", &db_buffer);
2267 ast_test_validate(
test, fabs(db_buffer) > 0);
2269 sscanf(varbuffer,
"%lf", &db_buffer);
2270 ast_test_validate(
test, fabs(db_buffer) <
EPSILON);
2272 sscanf(varbuffer,
"%lf", &db_buffer);
2273 ast_test_validate(
test, fabs(db_buffer) <
EPSILON);
2275 sscanf(varbuffer,
"%lf", &db_buffer);
2276 ast_test_validate(
test, fabs(db_buffer) > 0);
2278 sscanf(varbuffer,
"%lf", &db_buffer);
2279 ast_test_validate(
test, fabs(db_buffer) <
EPSILON);
2281 sscanf(varbuffer,
"%d", &int_buffer);
2310 ast_channel_accountcode_set(chan,
"ZZZ");
2334 .
clid =
"\"Alice\" <100>",
2337 .dcontext =
"default",
2342 .accountcode =
"100",
2348 info->name = __func__;
2350 info->summary =
"Test field access CDRs";
2352 "This tests setting/retrieving data on CDR records.";
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];
2406 struct timespec
to_sleep = {1, 10000};
2410 .
clid =
"\"Alice\" <100>",
2413 .dcontext =
"default",
2417 .accountcode =
"100",
2419 struct ast_cdr fork_expected_one = {
2420 .
clid =
"\"Alice\" <100>",
2423 .dcontext =
"default",
2427 .accountcode =
"100",
2429 struct ast_cdr fork_expected_two = {
2430 .
clid =
"\"Alice\" <100>",
2433 .dcontext =
"default",
2437 .accountcode =
"100",
2440 struct ast_cdr *expected = &original;
2441 original.
next = &fork_expected_one;
2442 fork_expected_one.
next = &fork_expected_two;
2446 info->name = __func__;
2448 info->summary =
"Test field access CDRs";
2450 "This tests setting/retrieving data on CDR records.";
2469 ast_test_validate(
test, strcmp(varbuffer,
"record_1") == 0);
2474 ast_test_validate(
test, strcmp(varbuffer,
"record_1") != 0);
2487 ast_test_validate(
test, strcmp(varbuffer,
"record_2") == 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);
2507 ast_test_validate(
test, strcmp(fork_start_time, start_time) != 0);
2508 ast_test_validate(
test, strcmp(fork_answer_time, answer_time) != 0);
Asterisk main include file. File version handling, generic pbx functions.
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_alloc(data_size, destructor_fn)
int ast_bridge_depart(struct ast_channel *chan)
Depart a channel from a bridge.
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.
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
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)
@ AST_BRIDGE_CAPABILITY_HOLDING
@ AST_BRIDGE_IMPART_CHAN_DEPARTABLE
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
#define AST_CAUSE_NO_ROUTE_DESTINATION
#define AST_CAUSE_NO_ANSWER
void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
Set CDR user field for channel (stored in CDR)
void ast_cdr_free(struct ast_cdr *cdr)
Free a CDR record.
@ CDR_CHANNEL_DEFAULT_ENABLED
void ast_cdr_set_config(struct ast_cdr_config *config)
Set the current CDR configuration.
int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
Clear a property on a CDR for a channel.
int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
Set a variable on a CDR.
@ AST_CDR_FLAG_DISABLE_ALL
@ AST_CDR_FLAG_SET_ANSWER
int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
Fork a CDR.
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.
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
struct ast_cdr_config * ast_cdr_get_config(void)
Obtain the current CDR configuration.
int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
Set a property on a CDR for a channel.
static char accountcode[AST_MAX_ACCOUNT_CODE]
static const char config[]
static int answer(void *data)
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.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
#define ast_channel_lock(chan)
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.
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
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 ...
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)
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)
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
#define ast_var_assign(name, value)
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.
#define AST_LIST_HEAD_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
#define ast_cond_init(cond, attr)
#define ast_cond_timedwait(cond, mutex, time)
pthread_cond_t ast_cond_t
#define ast_cond_signal(cond)
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Structure that contains information about a bridge.
The global options available for CDRs.
struct ast_flags settings
Responsible for call detail data.
char dstchannel[AST_MAX_EXTENSION]
char linkedid[AST_MAX_UNIQUEID]
char channel[AST_MAX_EXTENSION]
char clid[AST_MAX_EXTENSION]
char uniqueid[AST_MAX_UNIQUEID]
Structure to describe a channel "technology", ie a channel driver See for examples:
Main Channel structure associated with a channel.
Structure used to handle boolean flags.
Caller Party information.
struct ast_party_id id
Caller party ID.
struct ast_party_name name
Subscriber name.
char * str
Subscriber name (Malloced)
Contains all the initialization information required to store a new test definition.
struct ast_var_t::@211 entries
struct test_cdr_entry::@493 list
#define ast_test_debug(test, fmt,...)
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
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.
#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...
#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...
#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.
static int global_mock_cdr_count
The number of CDRs the mock backend has received.
#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.
static void safe_bridge_destroy(struct ast_bridge *bridge)
#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...
static void clear_mock_cdr_backend(void)
static struct ast_cdr_config unanswered_cdr_config
A configuration suitable for CDRs with unanswered records.
#define BOB_CALLERID
Bob's Caller ID.
static void do_sleep(struct timespec *to_sleep)
#define SET_FORMATS(chan)
Set ulaw format on channel.
AST_TEST_DEFINE(test_cdr_channel_creation)
static int test_cdr_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
static ast_cond_t mock_cdr_cond
The Mock CDR backend condition wait.
static int mock_cdr_backend_cb(struct ast_cdr *cdr)
#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.
#define CHANNEL_TECH_NAME
#define ALICE_CALLERID
Alice's Caller ID.
static void safe_channel_release(struct ast_channel *chan)
static enum ast_test_result_state verify_mock_cdr_record(struct ast_test *test, struct ast_cdr *expected, int record)
static int test_cdr_init_cb(struct ast_test_info *info, struct ast_test *test)
static struct ast_cdr_config * saved_config
A placeholder for Asterisk's 'real' CDR configuration.
static struct ast_channel_tech test_cdr_chan_tech
A channel technology used for the unit tests.
#define EMULATE_APP_DATA(channel, priority, application, data)
Emulate a channel entering into an application.
#define HANGUP_CHANNEL(channel, cause)
Hang up a test channel safely.
static int load_module(void)
static struct ast_cdr_config debug_cdr_config
A configuration suitable for 'normal' CDRs.
static int unload_module(void)
#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 ...
#define CHARLIE_CALLERID
Charlie's Caller ID.
static struct ast_cdr_config congestion_cdr_config
A configuration suitable for CDRs with congestion enabled.
static struct timespec to_sleep
A 1 second sleep.
Time-related functions and macros.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ast_clear_flag(p, flag)
#define ast_set_flag(p, flag)