Merge "ari: Implement 'debug all' and request/response logging"
[asterisk/asterisk.git] / tests / test_cel.c
index 17c4e09..c9ceaf9 100644 (file)
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 #include <math.h>
 #include "asterisk/module.h"
 #include "asterisk/test.h"
 #include "asterisk/cel.h"
 #include "asterisk/channel.h"
+#include "asterisk/format_cache.h"
 #include "asterisk/linkedlists.h"
 #include "asterisk/chanvars.h"
 #include "asterisk/utils.h"
@@ -130,7 +129,7 @@ static void do_sleep(void)
 
 #define BRIDGE_EXIT_EVENT_PEER(channel, bridge, peer) do { \
        RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
-       extra = ast_json_pack("{s: s}", "bridge_id", bridge->uniqueid); \
+       extra = ast_json_pack("{s: s, s: s}", "bridge_id", bridge->uniqueid, "bridge_technology", bridge->technology->name); \
        ast_test_validate(test, extra != NULL); \
        APPEND_EVENT_PEER(channel, AST_CEL_BRIDGE_EXIT, NULL, extra, peer); \
        } while (0)
@@ -140,7 +139,7 @@ static void do_sleep(void)
        RAII_VAR(struct ast_str *, peer_str, NULL, ast_free); \
        peer_str = test_cel_generate_peer_str_snapshot(channel, bridge); \
        ast_test_validate(test, peer_str != NULL); \
-       extra = ast_json_pack("{s: s}", "bridge_id", bridge->uniqueid); \
+       extra = ast_json_pack("{s: s, s: s}", "bridge_id", bridge->uniqueid, "bridge_technology", bridge->technology->name); \
        ast_test_validate(test, extra != NULL); \
        APPEND_EVENT_SNAPSHOT(channel, AST_CEL_BRIDGE_EXIT, NULL, extra, ast_str_buffer(peer_str)); \
        } while (0)
@@ -161,27 +160,34 @@ static void do_sleep(void)
 
 #define BRIDGE_ENTER_EVENT_PEER(channel, bridge, peer) do { \
        RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
-       extra = ast_json_pack("{s: s}", "bridge_id", bridge->uniqueid); \
+       extra = ast_json_pack("{s: s, s: s}", "bridge_id", bridge->uniqueid, "bridge_technology", bridge->technology->name); \
        ast_test_validate(test, extra != NULL); \
        APPEND_EVENT_PEER(channel, AST_CEL_BRIDGE_ENTER, NULL, extra, peer); \
        } while (0)
 
 #define BLINDTRANSFER_EVENT(channel, bridge, extension, context) do { \
        RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
-       extra = ast_json_pack("{s: s, s: s, s: s}", \
+       extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}", \
                "extension", extension, \
                "context", context, \
-               "bridge_id", bridge->uniqueid); \
+               "bridge_id", bridge->uniqueid, \
+               "transferee_channel_name", "N/A", \
+               "transferee_channel_uniqueid", "N/A"); \
        ast_test_validate(test, extra != NULL); \
        APPEND_EVENT(channel, AST_CEL_BLINDTRANSFER, NULL, extra); \
        } while (0)
 
-#define ATTENDEDTRANSFER_BRIDGE(channel1, bridge1, channel2, bridge2) do { \
+#define ATTENDEDTRANSFER_BRIDGE(channel1, bridge1, channel2, bridge2, channel3, channel4) do { \
        RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref); \
-       extra = ast_json_pack("{s: s, s: s, s: s}", \
+       extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}", \
                "bridge1_id", bridge1->uniqueid, \
                "channel2_name", ast_channel_name(channel2), \
-               "bridge2_id", bridge2->uniqueid); \
+               "channel2_uniqueid", ast_channel_uniqueid(channel2), \
+               "bridge2_id", bridge2->uniqueid, \
+               "transferee_channel_name", ast_channel_name(channel4), \
+               "transferee_channel_uniqueid", ast_channel_uniqueid(channel4), \
+               "transfer_target_channel_name", ast_channel_name(channel3), \
+               "transfer_target_channel_uniqueid", ast_channel_uniqueid(channel3)); \
        ast_test_validate(test, extra != NULL); \
        APPEND_EVENT(channel1, AST_CEL_ATTENDEDTRANSFER, NULL, extra); \
        } while (0)
@@ -198,30 +204,47 @@ static void do_sleep(void)
 /*! \brief David's Caller ID */
 #define DAVID_CALLERID { .id.name.str = "David", .id.name.valid = 1, .id.number.str = "400", .id.number.valid = 1, }
 
+/*! \brief Set ulaw format on channel */
+#define SET_FORMATS(chan) do {\
+       struct ast_format_cap *caps;\
+       caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);\
+       ast_format_cap_append(caps, ast_format_ulaw, 0);\
+       ast_channel_nativeformats_set((chan), caps);\
+       ast_channel_set_writeformat((chan), ast_format_ulaw);\
+       ast_channel_set_rawwriteformat((chan), ast_format_ulaw);\
+       ast_channel_set_readformat((chan), ast_format_ulaw);\
+       ast_channel_set_rawreadformat((chan), ast_format_ulaw);\
+       ao2_ref(caps, -1);\
+} while (0)
+
 /*! \brief Create a \ref test_cel_chan_tech for Alice. */
 #define CREATE_ALICE_CHANNEL(channel_var, caller_id) do { \
-       (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "100", "100", "default", NULL, 0, CHANNEL_TECH_NAME "/Alice"); \
+       (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "100", "100", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Alice"); \
+       SET_FORMATS((channel_var));\
        APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
        ast_channel_unlock((channel_var)); \
        } while (0)
 
 /*! \brief Create a \ref test_cel_chan_tech for Bob. */
 #define CREATE_BOB_CHANNEL(channel_var, caller_id) do { \
-       (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "200", "200", "default", NULL, 0, CHANNEL_TECH_NAME "/Bob"); \
+       (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "200", "200", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Bob"); \
+       SET_FORMATS((channel_var));\
        APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
        ast_channel_unlock((channel_var)); \
        } while (0)
 
 /*! \brief Create a \ref test_cel_chan_tech for Charlie. */
 #define CREATE_CHARLIE_CHANNEL(channel_var, caller_id) do { \
-       (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "300", "300", "default", NULL, 0, CHANNEL_TECH_NAME "/Charlie"); \
+       (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "300", "300", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/Charlie"); \
+       SET_FORMATS((channel_var));\
        APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
        ast_channel_unlock((channel_var)); \
        } while (0)
 
 /*! \brief Create a \ref test_cel_chan_tech for David. */
 #define CREATE_DAVID_CHANNEL(channel_var, caller_id) do { \
-       (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "400", "400", "default", NULL, 0, CHANNEL_TECH_NAME "/David"); \
+       (channel_var) = ast_channel_alloc(0, AST_STATE_DOWN, (caller_id)->id.number.str, (caller_id)->id.name.str, "400", "400", "default", NULL, NULL, 0, CHANNEL_TECH_NAME "/David"); \
+       SET_FORMATS((channel_var));\
        APPEND_EVENT(channel_var, AST_CEL_CHANNEL_START, NULL, NULL); \
        ast_channel_unlock((channel_var)); \
        } while (0)
@@ -285,7 +308,9 @@ static int append_expected_event_snapshot(
        struct ast_json *extra,
        const char *peer);
 
+#ifdef RACEY_TESTS
 static int append_dummy_event(void);
+#endif
 
 static struct ast_str *__test_cel_generate_peer_str(struct ast_channel_snapshot *chan, struct ast_bridge_snapshot *bridge)
 {
@@ -403,7 +428,7 @@ AST_TEST_DEFINE(test_cel_unanswered_inbound_call)
                info->description =
                        "Test CEL records for a call that is\n"
                        "inbound to Asterisk, executes some dialplan, but\n"
-                       "is never answered.\n";
+                       "is never answered.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -434,7 +459,7 @@ AST_TEST_DEFINE(test_cel_unanswered_outbound_call)
                info->summary = "Test outbound unanswered calls";
                info->description =
                        "Test CEL records for a call that is\n"
-                       "outbound to Asterisk but is never answered.\n";
+                       "outbound to Asterisk but is never answered.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -463,7 +488,7 @@ AST_TEST_DEFINE(test_cel_single_party)
                info->summary = "Test CEL for a single party";
                info->description =
                        "Test CEL records for a call that is\n"
-                       "answered, but only involves a single channel\n";
+                       "answered, but only involves a single channel";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -492,7 +517,7 @@ AST_TEST_DEFINE(test_cel_single_bridge)
                info->summary = "Test CEL for a single party entering/leaving a bridge";
                info->description =
                        "Test CEL records for a call that is\n"
-                       "answered, enters a bridge, and leaves it.\n";
+                       "answered, enters a bridge, and leaves it.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -530,7 +555,7 @@ AST_TEST_DEFINE(test_cel_single_bridge_continue)
                info->summary = "Test CEL for a single party entering/leaving a bridge";
                info->description =
                        "Test CEL records for a call that is\n"
-                       "answered, enters a bridge, and leaves it.\n";
+                       "answered, enters a bridge, and leaves it.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -574,7 +599,7 @@ AST_TEST_DEFINE(test_cel_single_twoparty_bridge_a)
                info->description =
                        "Test CEL records for a call that is\n"
                        "answered, enters a bridge, and leaves it. In this scenario, the\n"
-                       "Party A should answer the bridge first.\n";
+                       "Party A should answer the bridge first.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -622,7 +647,7 @@ AST_TEST_DEFINE(test_cel_single_twoparty_bridge_b)
                info->description =
                        "Test CEL records for a call that is\n"
                        "answered, enters a bridge, and leaves it. In this scenario, the\n"
-                       "Party B should answer the bridge first.\n";
+                       "Party B should answer the bridge first.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -676,7 +701,7 @@ AST_TEST_DEFINE(test_cel_single_multiparty_bridge)
                info->description =
                        "Test CEL records for a call that is\n"
                        "answered, enters a bridge, and leaves it. A total of three\n"
-                       "parties perform this action.\n";
+                       "parties perform this action.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -729,7 +754,8 @@ AST_TEST_DEFINE(test_cel_single_multiparty_bridge)
        START_DIALED_FULL(caller, callee, "200", "Bob")
 
 #define START_DIALED_FULL(caller, callee, number, name) do { \
-       callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, number, NULL, NULL, ast_channel_linkedid(caller), 0, CHANNEL_TECH_NAME "/" name); \
+       callee = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, number, NULL, NULL, NULL, caller, 0, CHANNEL_TECH_NAME "/" name); \
+       SET_FORMATS(callee);\
        ast_channel_unlock(callee); \
        if (append_expected_event(callee, AST_CEL_CHANNEL_START, NULL, NULL, NULL)) { \
                return AST_TEST_FAIL; \
@@ -752,7 +778,7 @@ AST_TEST_DEFINE(test_cel_dial_unanswered)
                info->summary = "Test CEL for a dial that isn't answered";
                info->description =
                        "Test CEL records for a channel that\n"
-                       "performs a dial operation that isn't answered\n";
+                       "performs a dial operation that isn't answered";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -773,6 +799,40 @@ AST_TEST_DEFINE(test_cel_dial_unanswered)
        return AST_TEST_PASS;
 }
 
+AST_TEST_DEFINE(test_cel_dial_unanswered_filter)
+{
+       RAII_VAR(struct ast_channel *, chan_caller, NULL, safe_channel_release);
+       RAII_VAR(struct ast_channel *, chan_callee, NULL, safe_channel_release);
+       struct ast_party_caller caller = ALICE_CALLERID;
+
+       switch (cmd) {
+       case TEST_INIT:
+               info->name = __func__;
+               info->category = TEST_CATEGORY;
+               info->summary = "Test CEL for a dial that isn't answered";
+               info->description =
+                       "Test CEL records for a channel that\n"
+                       "performs a dial operation that isn't answered";
+               return AST_TEST_NOT_RUN;
+       case TEST_EXECUTE:
+               break;
+       }
+
+       CREATE_ALICE_CHANNEL(chan_caller, &caller);
+
+       EMULATE_DIAL(chan_caller, CHANNEL_TECH_NAME "/Bob");
+
+       START_DIALED(chan_caller, chan_callee);
+
+       ast_channel_state_set(chan_caller, AST_STATE_RINGING);
+       ast_channel_publish_dial(chan_caller, chan_callee, NULL, "NOT A VALID DIAL STATUS");
+       ast_channel_publish_dial(chan_caller, chan_callee, NULL, "NOANSWER");
+
+       HANGUP_CHANNEL(chan_caller, AST_CAUSE_NO_ANSWER, "NOANSWER");
+       HANGUP_CHANNEL(chan_callee, AST_CAUSE_NO_ANSWER, "");
+
+       return AST_TEST_PASS;
+}
 
 AST_TEST_DEFINE(test_cel_dial_busy)
 {
@@ -787,7 +847,7 @@ AST_TEST_DEFINE(test_cel_dial_busy)
                info->summary = "Test CEL for a dial that results in a busy";
                info->description =
                        "Test CEL records for a channel that\n"
-                       "performs a dial operation to an endpoint that's busy\n";
+                       "performs a dial operation to an endpoint that's busy";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -821,7 +881,7 @@ AST_TEST_DEFINE(test_cel_dial_congestion)
                info->summary = "Test CEL for a dial that results in congestion";
                info->description =
                        "Test CEL records for a channel that\n"
-                       "performs a dial operation to an endpoint that's congested\n";
+                       "performs a dial operation to an endpoint that's congested";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -855,7 +915,7 @@ AST_TEST_DEFINE(test_cel_dial_unavailable)
                info->summary = "Test CEL for a dial that results in unavailable";
                info->description =
                        "Test CEL records for a channel that\n"
-                       "performs a dial operation to an endpoint that's unavailable\n";
+                       "performs a dial operation to an endpoint that's unavailable";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -890,7 +950,7 @@ AST_TEST_DEFINE(test_cel_dial_caller_cancel)
                info->description =
                        "Test CEL records for a channel that\n"
                        "performs a dial operation to an endpoint but then decides\n"
-                       "to hang up, cancelling the dial\n";
+                       "to hang up, cancelling the dial";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -927,7 +987,7 @@ AST_TEST_DEFINE(test_cel_dial_parallel_failed)
                info->description =
                        "This tests dialing three parties: Bob, Charlie, David. Charlie\n"
                        "returns BUSY; David returns CONGESTION; Bob fails to answer and\n"
-                       "Alice hangs up. Three records are created for Alice as a result.\n";
+                       "Alice hangs up. Three records are created for Alice as a result.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -980,7 +1040,7 @@ AST_TEST_DEFINE(test_cel_dial_answer_no_bridge)
                        "a dial, then bounce both channels to different priorities and\n"
                        "never have them enter a bridge together. Ew. This makes sure that\n"
                        "when we answer, we get a CEL, it gets ended at that point, and\n"
-                       "that it gets finalized appropriately.\n";
+                       "that it gets finalized appropriately.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1021,7 +1081,7 @@ AST_TEST_DEFINE(test_cel_dial_answer_twoparty_bridge_a)
                info->category = TEST_CATEGORY;
                info->summary = "Test dialing, answering, and going into a 2-party bridge";
                info->description =
-                       "The most 'basic' of scenarios\n";
+                       "The most 'basic' of scenarios";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1068,7 +1128,7 @@ AST_TEST_DEFINE(test_cel_dial_answer_twoparty_bridge_b)
                info->category = TEST_CATEGORY;
                info->summary = "Test dialing, answering, and going into a 2-party bridge";
                info->description =
-                       "The most 'basic' of scenarios\n";
+                       "The most 'basic' of scenarios";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1118,7 +1178,7 @@ AST_TEST_DEFINE(test_cel_dial_answer_multiparty)
                info->category = TEST_CATEGORY;
                info->summary = "Test dialing, answering, and going into a multi-party bridge";
                info->description =
-                       "A little tricky to get to do, but possible with some redirects.\n";
+                       "A little tricky to get to do, but possible with some redirects.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1183,9 +1243,9 @@ AST_TEST_DEFINE(test_cel_blind_transfer)
        RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
        RAII_VAR(struct ast_channel *, chan_bob, NULL, safe_channel_release);
        RAII_VAR(struct ast_bridge *, bridge, NULL, safe_bridge_destroy);
+       RAII_VAR(struct ast_blind_transfer_message *, transfer_msg, NULL, ao2_cleanup);
        struct ast_party_caller alice_caller = ALICE_CALLERID;
        struct ast_party_caller bob_caller = BOB_CALLERID;
-       struct ast_bridge_channel_pair pair;
 
        switch (cmd) {
        case TEST_INIT:
@@ -1194,7 +1254,7 @@ AST_TEST_DEFINE(test_cel_blind_transfer)
                info->summary = "Test blind transfers to an extension";
                info->description =
                        "This test creates two channels, bridges them, and then"
-                       " blind transfers the bridge to an extension.\n";
+                       " blind transfers the bridge to an extension.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1211,10 +1271,23 @@ AST_TEST_DEFINE(test_cel_blind_transfer)
        BRIDGE_ENTER(chan_bob, bridge);
        BRIDGE_ENTER(chan_alice, bridge);
 
-       pair.bridge = bridge;
-       pair.channel = chan_alice;
-       ast_bridge_publish_blind_transfer(1, AST_BRIDGE_TRANSFER_SUCCESS,
-               &pair, "transfer_context", "transfer_extension");
+       ast_bridge_lock(bridge);
+       transfer_msg = ast_blind_transfer_message_create(1, chan_alice,
+                       "transfer_extension", "transfer_context");
+       if (!transfer_msg) {
+               ast_bridge_unlock(bridge);
+               ast_test_status_update(test, "Failed to create transfer Stasis message\n");
+               return AST_TEST_FAIL;
+       }
+       transfer_msg->bridge = ast_bridge_snapshot_create(bridge);
+       if (!transfer_msg->bridge) {
+               ast_bridge_unlock(bridge);
+               ast_test_status_update(test, "Failed to create bridge snapshot\n");
+               return AST_TEST_FAIL;
+       }
+       ast_bridge_unlock(bridge);
+       transfer_msg->result = AST_BRIDGE_TRANSFER_SUCCESS;
+       ast_bridge_publish_blind_transfer(transfer_msg);
        BLINDTRANSFER_EVENT(chan_alice, bridge, "transfer_extension", "transfer_context");
 
        BRIDGE_EXIT(chan_alice, bridge);
@@ -1227,6 +1300,10 @@ AST_TEST_DEFINE(test_cel_blind_transfer)
        return AST_TEST_PASS;
 }
 
+/* XXX Validation needs to take into account the BRIDGE_EXIT for Alice and the
+ * ATTENDEDTRANSFER message are not guaranteed to be ordered
+ */
+#ifdef RACEY_TESTS
 AST_TEST_DEFINE(test_cel_attended_transfer_bridges_swap)
 {
        RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
@@ -1248,7 +1325,7 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_swap)
                info->description =
                        "This test creates four channels, places each pair in"
                        " a bridge, and then attended transfers the bridges"
-                       " together.\n";
+                       " together.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1281,13 +1358,16 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_swap)
        do_sleep();
 
        /* Perform attended transfer */
-       ast_bridge_transfer_attended(chan_alice, chan_david);
+       if (ast_bridge_transfer_attended(chan_alice, chan_david)) {
+               ast_test_status_update(test, "Attended transfer failed!\n");
+               return AST_TEST_FAIL;
+       }
        do_sleep();
        BRIDGE_ENTER_EVENT_PEER(chan_bob, bridge2, "CELTestChannel/David,CELTestChannel/Charlie");
 
        BRIDGE_EXIT_EVENT(chan_david, bridge2);
-       ATTENDEDTRANSFER_BRIDGE(chan_alice, bridge1, chan_david, bridge2);
        BRIDGE_EXIT_EVENT(chan_alice, bridge1);
+       ATTENDEDTRANSFER_BRIDGE(chan_alice, bridge1, chan_david, bridge2, chan_charlie, chan_bob);
 
        do_sleep();
        BRIDGE_EXIT(chan_bob, bridge2);
@@ -1303,6 +1383,7 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_swap)
 
        return AST_TEST_PASS;
 }
+#endif
 
 AST_TEST_DEFINE(test_cel_attended_transfer_bridges_merge)
 {
@@ -1326,7 +1407,7 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_merge)
                info->description =
                        "This test creates four channels, places each pair"
                        " in a bridge, and then attended transfers the bridges"
-                       " together causing a bridge merge.\n";
+                       " together causing a bridge merge.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1334,7 +1415,7 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_merge)
        /* Create first set of bridged parties */
        bridge1 = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_1TO1MIX | AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_MULTIMIX,
                AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED | AST_BRIDGE_FLAG_SMART,
-               "test_cel", "test_cel_atxfer_bridges_merge_1");
+               "test_cel", "test_cel_atxfer_bridges_merge_1", NULL);
        ast_test_validate(test, bridge1 != NULL);
 
        CREATE_ALICE_CHANNEL(chan_alice, &alice_caller);
@@ -1348,7 +1429,7 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_merge)
        /* Create second set of bridged parties */
        bridge2 = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_1TO1MIX | AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_MULTIMIX,
                AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED | AST_BRIDGE_FLAG_SMART,
-               "test_cel", "test_cel_atxfer_bridges_merge_2");
+               "test_cel", "test_cel_atxfer_bridges_merge_2", NULL);
        ast_test_validate(test, bridge2 != NULL);
 
        CREATE_DAVID_CHANNEL(chan_david, &david_caller);
@@ -1361,14 +1442,17 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_merge)
        BRIDGE_ENTER(chan_david, bridge2);
 
        /* Perform attended transfer */
-       ast_bridge_transfer_attended(chan_alice, chan_david);
+       if (ast_bridge_transfer_attended(chan_alice, chan_david)) {
+               ast_test_status_update(test, "Attended transfer failed!\n");
+               return AST_TEST_FAIL;
+       }
        do_sleep();
        BRIDGE_EXIT_EVENT_PEER(chan_charlie, bridge2, "CELTestChannel/David");
        BRIDGE_ENTER_EVENT_PEER(chan_charlie, bridge1, "CELTestChannel/Bob,CELTestChannel/Alice");
        BRIDGE_EXIT_EVENT(chan_david, bridge2);
        BRIDGE_EXIT_EVENT(chan_alice, bridge1);
 
-       ATTENDEDTRANSFER_BRIDGE(chan_alice, bridge1, chan_david, bridge2);
+       ATTENDEDTRANSFER_BRIDGE(chan_alice, bridge1, chan_david, bridge2, chan_charlie, chan_bob);
 
        do_sleep();
        BRIDGE_EXIT(chan_bob, bridge1);
@@ -1385,6 +1469,10 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_merge)
        return AST_TEST_PASS;
 }
 
+/* XXX Validation needs to take into account the BRIDGE_EXIT for David and the
+ * ATTENDEDTRANSFER message are not guaranteed to be ordered
+ */
+#ifdef RACEY_TESTS
 AST_TEST_DEFINE(test_cel_attended_transfer_bridges_link)
 {
        RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release);
@@ -1407,7 +1495,7 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_link)
                info->description =
                        "This test creates four channels, places each pair"
                        " in a bridge, and then attended transfers the bridges"
-                       " together causing a bridge link.\n";
+                       " together causing a bridge link.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1417,7 +1505,7 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_link)
                AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
                | AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM
                | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED | AST_BRIDGE_FLAG_SMART,
-               "test_cel", "test_cel_atxfer_bridges_link_1");
+               "test_cel", "test_cel_atxfer_bridges_link_1", NULL);
        ast_test_validate(test, bridge1 != NULL);
 
        CREATE_ALICE_CHANNEL(chan_alice, &alice_caller);
@@ -1433,7 +1521,7 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_link)
                AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
                | AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM
                | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED | AST_BRIDGE_FLAG_SMART,
-               "test_cel", "test_cel_atxfer_bridges_link_2");
+               "test_cel", "test_cel_atxfer_bridges_link_2", NULL);
        ast_test_validate(test, bridge2 != NULL);
 
        CREATE_DAVID_CHANNEL(chan_david, &david_caller);
@@ -1445,24 +1533,11 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_link)
        BRIDGE_ENTER(chan_david, bridge2);
 
        /* Perform attended transfer */
-
-       /* The following events can not be matched directly since nothing is known
-        * about the linking local channel.
-        * ;1 and ;2 CHAN_START and ;2 ANSWER */
-       APPEND_DUMMY_EVENT();
-       APPEND_DUMMY_EVENT();
-       APPEND_DUMMY_EVENT();
-
-       ATTENDEDTRANSFER_BRIDGE(chan_alice, bridge1, chan_david, bridge2);
+       ATTENDEDTRANSFER_BRIDGE(chan_alice, bridge1, chan_david, bridge2, chan_charlie, chan_bob);
 
        ast_bridge_transfer_attended(chan_alice, chan_david);
        do_sleep();
 
-       /* ;1 and ;2 BRIDGE_ENTER and ;1 ANSWER */
-       APPEND_DUMMY_EVENT();
-       APPEND_DUMMY_EVENT();
-       APPEND_DUMMY_EVENT();
-
        /* BRIDGE_EXIT alice and david */
        APPEND_DUMMY_EVENT();
        APPEND_DUMMY_EVENT();
@@ -1480,16 +1555,9 @@ AST_TEST_DEFINE(test_cel_attended_transfer_bridges_link)
        HANGUP_CHANNEL(chan_charlie, AST_CAUSE_NORMAL, "");
        do_sleep();
 
-       /* ;1 and ;2 BRIDGE_EXIT, HANGUP, and CHAN_END */
-       APPEND_DUMMY_EVENT();
-       APPEND_DUMMY_EVENT();
-       APPEND_DUMMY_EVENT();
-       APPEND_DUMMY_EVENT();
-       APPEND_DUMMY_EVENT();
-       APPEND_DUMMY_EVENT();
-
        return AST_TEST_PASS;
 }
+#endif
 
 AST_TEST_DEFINE(test_cel_dial_pickup)
 {
@@ -1507,7 +1575,7 @@ AST_TEST_DEFINE(test_cel_dial_pickup)
                info->description =
                        "Test CEL records for a call that is\n"
                        "inbound to Asterisk, executes some dialplan, and\n"
-                       "is picked up.\n";
+                       "is picked up.";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1527,7 +1595,8 @@ AST_TEST_DEFINE(test_cel_dial_pickup)
                RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
                SCOPED_CHANNELLOCK(lock, chan_callee);
 
-               extra = ast_json_pack("{s: s}", "pickup_channel", ast_channel_name(chan_charlie));
+               extra = ast_json_pack("{s: s, s: s}", "pickup_channel", ast_channel_name(chan_charlie),
+                       "pickup_channel_uniqueid", ast_channel_uniqueid(chan_charlie));
                ast_test_validate(test, extra != NULL);
 
                APPEND_EVENT(chan_callee, AST_CEL_PICKUP, NULL, extra);
@@ -1566,7 +1635,7 @@ AST_TEST_DEFINE(test_cel_local_optimize)
                info->description =
                        "Test CEL records for two local channels being optimized\n"
                        "out by sending a messages indicating local optimization\n"
-                       "begin and end\n";
+                       "begin and end";
                return AST_TEST_NOT_RUN;
        case TEST_EXECUTE:
                break;
@@ -1600,7 +1669,8 @@ AST_TEST_DEFINE(test_cel_local_optimize)
        stasis_publish(ast_channel_topic(chan_alice), local_opt_begin);
        stasis_publish(ast_channel_topic(chan_alice), local_opt_end);
 
-       extra = ast_json_pack("{s: s}", "local_two", bob_snapshot->name);
+       extra = ast_json_pack("{s: s, s: s}", "local_two", bob_snapshot->name,
+               "local_two_uniqueid", bob_snapshot->uniqueid);
        ast_test_validate(test, extra != NULL);
 
        APPEND_EVENT_SNAPSHOT(alice_snapshot, AST_CEL_LOCAL_OPTIMIZE, NULL, extra, NULL);
@@ -1669,6 +1739,7 @@ static int append_event(struct ast_event *ev)
        return 0;
 }
 
+#ifdef RACEY_TESTS
 static int append_dummy_event(void)
 {
        RAII_VAR(struct ast_event *, ev, NULL, ast_free);
@@ -1681,6 +1752,7 @@ static int append_dummy_event(void)
 
        return append_event(ev);
 }
+#endif
 
 static int append_expected_event_snapshot(
        struct ast_channel_snapshot *snapshot,
@@ -1719,12 +1791,18 @@ static int append_expected_event(
 static void test_sub(struct ast_event *event)
 {
        struct ast_event *event_dup = ao2_dup_event(event);
+       const char *chan_name;
        SCOPED_MUTEX(mid_test_lock, &mid_test_sync_lock);
 
        if (!event_dup) {
                return;
        }
 
+       chan_name = ast_event_get_ie_str(event_dup, AST_EVENT_IE_CEL_CHANNAME);
+       if (chan_name && strncmp(chan_name, CHANNEL_TECH_NAME, 14)) {
+               return;
+       }
+
        /* save the event for later processing */
        ao2_link(cel_received_events, event_dup);
 
@@ -1854,6 +1932,10 @@ static int match_ie_val(
 
                return !strcmp(str1, str2);
        }
+       case AST_EVENT_IE_PLTYPE_RAW:
+       case AST_EVENT_IE_PLTYPE_BITFLAGS:
+               /* Fall through: just pass on these types */
+               return 1;
        default:
                break;
        }
@@ -2034,6 +2116,7 @@ static int unload_module(void)
 #endif
 
        AST_TEST_UNREGISTER(test_cel_dial_unanswered);
+       AST_TEST_UNREGISTER(test_cel_dial_unanswered_filter);
        AST_TEST_UNREGISTER(test_cel_dial_congestion);
        AST_TEST_UNREGISTER(test_cel_dial_busy);
        AST_TEST_UNREGISTER(test_cel_dial_unavailable);
@@ -2044,12 +2127,12 @@ static int unload_module(void)
        AST_TEST_UNREGISTER(test_cel_dial_answer_twoparty_bridge_b);
 #ifdef RACEY_TESTS
        AST_TEST_UNREGISTER(test_cel_dial_answer_multiparty);
+       AST_TEST_UNREGISTER(test_cel_attended_transfer_bridges_swap);
+       AST_TEST_UNREGISTER(test_cel_attended_transfer_bridges_link);
 #endif
 
        AST_TEST_UNREGISTER(test_cel_blind_transfer);
-       AST_TEST_UNREGISTER(test_cel_attended_transfer_bridges_swap);
        AST_TEST_UNREGISTER(test_cel_attended_transfer_bridges_merge);
-       AST_TEST_UNREGISTER(test_cel_attended_transfer_bridges_link);
 
        AST_TEST_UNREGISTER(test_cel_dial_pickup);
 
@@ -2108,6 +2191,7 @@ static int load_module(void)
 #endif
 
        AST_TEST_REGISTER(test_cel_dial_unanswered);
+       AST_TEST_REGISTER(test_cel_dial_unanswered_filter);
        AST_TEST_REGISTER(test_cel_dial_congestion);
        AST_TEST_REGISTER(test_cel_dial_busy);
        AST_TEST_REGISTER(test_cel_dial_unavailable);
@@ -2118,12 +2202,12 @@ static int load_module(void)
        AST_TEST_REGISTER(test_cel_dial_answer_twoparty_bridge_b);
 #ifdef RACEY_TESTS
        AST_TEST_REGISTER(test_cel_dial_answer_multiparty);
+       AST_TEST_REGISTER(test_cel_attended_transfer_bridges_swap);
+       AST_TEST_REGISTER(test_cel_attended_transfer_bridges_link);
 #endif
 
        AST_TEST_REGISTER(test_cel_blind_transfer);
-       AST_TEST_REGISTER(test_cel_attended_transfer_bridges_swap);
        AST_TEST_REGISTER(test_cel_attended_transfer_bridges_merge);
-       AST_TEST_REGISTER(test_cel_attended_transfer_bridges_link);
 
        AST_TEST_REGISTER(test_cel_dial_pickup);