Asterisk - The Open Source Telephony Project GIT-master-b023714
Loading...
Searching...
No Matches
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 */
64
65/*! \brief A configuration suitable for CDRs with unanswered records */
69
70/*! \brief A configuration suitable for CDRs with congestion enabled */
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
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
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
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
536{
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
594
595 bridge = ast_bridge_basic_new();
596 ast_test_validate(test, bridge != NULL);
598
600
608 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
609
613
615
617
619
621
624
627
629 return result;
630}
631
632
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
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
733
735
736 ast_bridge_depart(chan);
737
739
740 result = verify_mock_cdr_record(test, &expected, 1);
741
742 return result;
743}
744
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
809
811
812 ast_bridge_depart(chan);
813
814 EMULATE_APP_DATA(chan, 3, "Wait", "");
815
816 /* And then it hangs up */
818
820
821 return result;
822}
823
825{
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 }
880
883
885 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
887 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
889
890 bridge = ast_bridge_basic_new();
891 ast_test_validate(test, bridge != NULL);
892
895
897 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
899 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
901
904
907
910
912
913 return result;
914}
915
917{
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 }
972
975
977 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
979 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
981
982 bridge = ast_bridge_basic_new();
983 ast_test_validate(test, bridge != NULL);
984
986 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
988 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
991
994
997
1000
1003
1005
1006 return result;
1007}
1008
1010{
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 }
1102
1104 EMULATE_APP_DATA(chan_alice, 1, "Answer", "");
1106 EMULATE_APP_DATA(chan_alice, 2, "Bridge", "");
1108
1109 bridge = ast_bridge_basic_new();
1110 ast_test_validate(test, bridge != NULL);
1112
1114
1116 EMULATE_APP_DATA(chan_bob, 1, "Answer", "");
1118 EMULATE_APP_DATA(chan_bob, 2, "Bridge", "");
1121
1123
1125
1127 EMULATE_APP_DATA(chan_charlie, 1, "Answer", "");
1129 EMULATE_APP_DATA(chan_charlie, 2, "Bridge", "");
1132
1134
1138
1142
1144
1145 return result;
1146}
1147
1149{
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
1196 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1197
1201
1204
1205 result = verify_mock_cdr_record(test, &expected, 1);
1206
1207 return result;
1208}
1209
1210
1212{
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
1254
1259 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1260
1264
1267
1268 result = verify_mock_cdr_record(test, &expected, 1);
1269
1270 return result;
1271}
1272
1274{
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
1316
1321 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1322
1326
1329
1330 result = verify_mock_cdr_record(test, &expected, 1);
1331
1332 return result;
1333}
1334
1336{
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
1378
1383 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1384
1388
1391
1392 result = verify_mock_cdr_record(test, &expected, 1);
1393
1394 return result;
1395}
1396
1398{
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
1441
1446 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1447
1451
1454
1455 result = verify_mock_cdr_record(test, &expected, 1);
1456
1457 return result;
1458}
1459
1461{
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;
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
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 */
1549 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
1550
1555 EMULATE_APP_DATA(chan_charlie, 0, "AppDial", "(Outgoing Line)");
1556
1561 EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");
1562
1563 /* Dial starts */
1568
1569 /* Charlie is busy */
1572
1573 /* David is congested */
1576
1577 /* Bob is canceled */
1580
1581 /* Alice hangs up */
1583
1584 result = verify_mock_cdr_record(test, expected, 3);
1585
1586 return result;
1587}
1588
1590{
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
1661
1663
1669
1673
1677
1678 EMULATE_APP_DATA(chan_caller, 2, "Wait", "1");
1679 EMULATE_APP_DATA(chan_callee, 1, "Wait", "1");
1680
1683
1685 return result;
1686}
1687
1689{
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
1732
1737 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1738
1742
1745
1746 bridge = ast_bridge_basic_new();
1747 ast_test_validate(test, bridge != NULL);
1749
1752
1754
1757
1760
1761 result = verify_mock_cdr_record(test, &expected, 1);
1762 return result;
1763}
1764
1766{
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
1809
1814 EMULATE_APP_DATA(chan_callee, 0, "AppDial", "(Outgoing Line)");
1815
1819
1822
1823 bridge = ast_bridge_basic_new();
1824 ast_test_validate(test, bridge != NULL);
1832
1835
1836 result = verify_mock_cdr_record(test, &expected, 1);
1837 return result;
1838}
1839
1841{
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
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");
1974 EMULATE_APP_DATA(chan_bob, 0, "AppDial", "(Outgoing Line)");
1977
1979 EMULATE_APP_DATA(chan_charlie, 1, "Dial", CHANNEL_TECH_NAME "/David");
1984
1985 chan_david = ast_channel_alloc(0, AST_STATE_DOWN, "400", "David", "400", "400", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/David");
1989 EMULATE_APP_DATA(chan_david, 0, "AppDial", "(Outgoing Line)");
1990
1997
2002
2003 bridge = ast_bridge_basic_new();
2004 ast_test_validate(test, bridge != NULL);
2005
2019
2024
2026
2027 return result;
2028}
2029
2031{
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 }
2085
2087 EMULATE_APP_DATA(chan_alice, 1, "Park", "700");
2090
2092 EMULATE_APP_DATA(chan_bob, 1, "Park", "701");
2095
2099 "test_cdr", "test_cdr_park", NULL);
2100 ast_test_validate(test, bridge != NULL);
2101
2109
2110 /* And then it hangs up */
2113
2115
2116 return result;
2117}
2118
2119
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;
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);
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);
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);
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);
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);
2259 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "dstchannel", varbuffer, sizeof(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);
2266 sscanf(varbuffer, "%lf", &db_buffer);
2268 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "answer", varbuffer, sizeof(varbuffer)) == 0);
2269 sscanf(varbuffer, "%lf", &db_buffer);
2272 sscanf(varbuffer, "%lf", &db_buffer);
2274 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "duration", varbuffer, sizeof(varbuffer)) == 0);
2275 sscanf(varbuffer, "%lf", &db_buffer);
2277 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "billsec", varbuffer, sizeof(varbuffer)) == 0);
2278 sscanf(varbuffer, "%lf", &db_buffer);
2280 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "disposition", varbuffer, sizeof(varbuffer)) == 0);
2281 sscanf(varbuffer, "%d", &int_buffer);
2283 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "uniqueid", varbuffer, sizeof(varbuffer)) == 0);
2285 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "linkedid", varbuffer, sizeof(varbuffer)) == 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. */
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 */
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
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 */
2366
2367 /* Fork the CDR. This should be enabled */
2370
2371 /* Disable and enable the forked CDR */
2374
2375 /* Fork and finalize again. This CDR should be propagated */
2377
2378 /* Disable all future CDRs */
2380
2381 /* Fork a few more */
2385
2387 ast_hangup(chan);
2388 chan = NULL;
2389 result = verify_mock_cdr_record(test, &expected, 1);
2390
2391 return result;
2392}
2393
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;
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);
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
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 */
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);
2489 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "start", start_time, sizeof(start_time)) == 0);
2490
2497 ast_test_validate(test, ast_cdr_getvar(ast_channel_name(chan), "test_variable", fork_varbuffer, sizeof(fork_varbuffer)) == 0);
2499 ast_test_validate(test, strcmp(fork_start_time, start_time) == 0);
2501
2507 ast_test_validate(test, strcmp(fork_start_time, start_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{
2551
2558
2560
2571
2573
2577
2581
2582 return 0;
2583}
2584
2585static int load_module(void)
2586{
2588
2592
2599
2601
2612
2614
2618
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:1975
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:999
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition bridge.c:1009
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:1947
@ AST_BRIDGE_CAPABILITY_HOLDING
Definition bridge.h:90
@ AST_BRIDGE_IMPART_CHAN_DEPARTABLE
Definition bridge.h:592
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
#define CDR_DEBUG(fmt,...)
Definition cdr.c:314
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:3625
void ast_cdr_free(struct ast_cdr *cdr)
Free a CDR record.
Definition cdr.c:3557
@ 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
void ast_cdr_set_config(struct ast_cdr_config *config)
Set the current CDR configuration.
Definition cdr.c:2973
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:3723
int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
Set a variable on a CDR.
Definition cdr.c:3316
@ AST_CDR_CONGESTION
Definition cdr.h:263
@ AST_CDR_NULL
Definition cdr.h:259
@ AST_CDR_NOANSWER
Definition cdr.h:258
@ AST_CDR_ANSWERED
Definition cdr.h:262
@ AST_CDR_BUSY
Definition cdr.h:261
@ AST_CDR_FAILED
Definition cdr.h:260
@ AST_CDR_FLAG_DISABLE_ALL
Definition cdr.h:246
@ AST_CDR_FLAG_FINALIZE
Definition cdr.h:248
@ AST_CDR_FLAG_DISABLE
Definition cdr.h:245
@ AST_CDR_FLAG_KEEP_VARS
Definition cdr.h:244
@ AST_CDR_FLAG_RESET
Definition cdr.h:250
@ AST_CDR_FLAG_SET_ANSWER
Definition cdr.h:249
int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
Fork a CDR.
Definition cdr.c:3785
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:3470
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition cdr.c:3121
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition cdr.c:3076
struct ast_cdr_config * ast_cdr_get_config(void)
Obtain the current CDR configuration.
Definition cdr.c:2959
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:3696
static PGresult * result
Definition cel_pgsql.c:84
static int amaflags
Definition chan_iax2.c:500
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition chan_iax2.c:497
static const char config[]
static int answer(void *data)
Definition chan_pjsip.c:687
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:2513
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition channel.h:1299
#define ast_channel_lock(chan)
Definition channel.h:2982
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:1201
@ AST_AMA_OMIT
Definition channel.h:1199
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition channel.c:1552
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:1019
@ AST_FLAG_ORIGINATED
Definition channel.h:1059
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:2983
@ AST_STATE_RINGING
@ AST_STATE_DOWN
@ AST_STATE_UP
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition channel.c:7373
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.
#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.
Definition linkedlists.h:40
#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)
Definition lock.h:208
#define ast_cond_timedwait(cond, mutex, time)
Definition lock.h:213
pthread_cond_t ast_cond_t
Definition lock.h:185
#define ast_cond_signal(cond)
Definition lock.h:210
int errno
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
#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:353
The global options available for CDRs.
Definition cdr.h:269
struct ast_flags settings
Definition cdr.h:270
Responsible for call detail data.
Definition cdr.h:281
char dstchannel[AST_MAX_EXTENSION]
Definition cdr.h:293
long int billsec
Definition cdr.h:307
char channel[AST_MAX_EXTENSION]
Definition cdr.h:291
struct ast_cdr * next
Definition cdr.h:334
struct varshead varshead
Definition cdr.h:332
char clid[AST_MAX_EXTENSION]
Definition cdr.h:283
struct timeval start
Definition cdr.h:299
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition channel.h:648
const char *const type
Definition channel.h:649
Main Channel structure associated with a channel.
Structure used to handle boolean flags.
Definition utils.h:217
unsigned int flags
Definition utils.h:218
Caller Party information.
Definition channel.h:420
struct ast_party_id id
Caller party ID.
Definition channel.h:422
struct ast_party_name name
Subscriber name.
Definition channel.h:342
char * str
Subscriber name (Malloced)
Definition channel.h:266
Contains all the initialization information required to store a new test definition.
Definition test.h:235
char name[0]
Definition chanvars.h:31
struct ast_var_t::@224 entries
char * value
Definition chanvars.h:30
Definition test_cdr.c:96
struct ast_cdr * cdr
Definition test_cdr.c:97
struct test_cdr_entry::@531 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
#define AST_TEST_DEFINE(hdr)
Definition test.h:126
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
#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
#define SET_FORMATS(chan)
Set ulaw format on channel.
Definition test_cdr.c:234
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 struct @530 actual_cdr_entries
A linked list of received CDR entries from the engine.
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 void do_sleep(void)
Definition test_cel.c:87
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:978
#define ast_clear_flag(p, flag)
Definition utils.h:77
#define ast_set_flag(p, flag)
Definition utils.h:70