<p>Friendly Automation <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/10740">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Joshua C. Colp: Looks good to me, but someone else must approve
Kevin Harwell: Looks good to me, approved
Friendly Automation: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">stasis: Allow filtering by formatter<br><br>A subscriber can now indicate that it only wants messages<br>that have formatters of a specific type. For instance,<br>manager can indicate that it only wants messages that have a<br>"to_ami" formatter. You can combine this with the existing<br>filter for message type to get only messages with specific<br>formatters or messages of specific types.<br><br>ASTERISK-28186<br><br>Change-Id: Ifdb7a222a73b6b56c6bb9e4ee93dc8a394a5494c<br>---<br>M include/asterisk/stasis.h<br>M include/asterisk/stasis_message_router.h<br>M main/stasis.c<br>M main/stasis_message.c<br>M main/stasis_message_router.c<br>M tests/test_stasis.c<br>6 files changed, 548 insertions(+), 10 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/stasis.h b/include/asterisk/stasis.h</span><br><span>index 85e78dc..6d423d9 100644</span><br><span>--- a/include/asterisk/stasis.h</span><br><span>+++ b/include/asterisk/stasis.h</span><br><span>@@ -301,6 +301,21 @@</span><br><span> };</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Stasis subscription formatter filters</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * There should be an entry here for each member of \ref stasis_message_vtable</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.25.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.2.0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+enum stasis_subscription_message_formatters {</span><br><span style="color: hsl(120, 100%, 40%);">+ STASIS_SUBSCRIPTION_FORMATTER_NONE = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ STASIS_SUBSCRIPTION_FORMATTER_JSON = 1 << 0, /*!< Allow messages with a to_json formatter */</span><br><span style="color: hsl(120, 100%, 40%);">+ STASIS_SUBSCRIPTION_FORMATTER_AMI = 1 << 1, /*!< Allow messages with a to_ami formatter */</span><br><span style="color: hsl(120, 100%, 40%);">+ STASIS_SUBSCRIPTION_FORMATTER_EVENT = 1 << 2, /*!< Allow messages with a to_event formatter */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Create a new message type.</span><br><span> *</span><br><span> * \ref stasis_message_type is an AO2 object, so ao2_cleanup() when you're done</span><br><span>@@ -676,6 +691,30 @@</span><br><span> enum stasis_subscription_message_filter filter);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Indicate to a subscription that we are interested in messages with one or more formatters.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param subscription Subscription to alter.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param formatters A bitmap of \ref stasis_subscription_message_formatters we wish to receive.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.25.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.2.0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void stasis_subscription_accept_formatters(struct stasis_subscription *subscription,</span><br><span style="color: hsl(120, 100%, 40%);">+ enum stasis_subscription_message_formatters formatters);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Get a bitmap of available formatters for a message type</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param message_type Message type</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return A bitmap of \ref stasis_subscription_message_formatters</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.25.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.2.0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+enum stasis_subscription_message_formatters stasis_message_type_available_formatters(</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct stasis_message_type *message_type);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Cancel a subscription.</span><br><span> *</span><br><span> * Note that in an asynchronous system, there may still be messages queued or</span><br><span>diff --git a/include/asterisk/stasis_message_router.h b/include/asterisk/stasis_message_router.h</span><br><span>index 8dcdfcc..9897d62 100644</span><br><span>--- a/include/asterisk/stasis_message_router.h</span><br><span>+++ b/include/asterisk/stasis_message_router.h</span><br><span>@@ -242,4 +242,23 @@</span><br><span> stasis_subscription_cb callback,</span><br><span> void *data);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Indicate to a message router that we are interested in messages with one or more formatters.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The formatters are passed on to the underlying subscription.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \warning With direct subscriptions, adding a formatter filter is an OR operation</span><br><span style="color: hsl(120, 100%, 40%);">+ * with any message type filters. In the current implementation of message router however,</span><br><span style="color: hsl(120, 100%, 40%);">+ * it's an AND operation. Even when setting a default route, the callback will only get</span><br><span style="color: hsl(120, 100%, 40%);">+ * messages that have the formatters provides in this call.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param router Router to set the formatters of.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param formatters A bitmap of \ref stasis_subscription_message_formatters we wish to receive.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.25.0</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 16.2.0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void stasis_message_router_accept_formatters(struct stasis_message_router *router,</span><br><span style="color: hsl(120, 100%, 40%);">+ enum stasis_subscription_message_formatters formatters);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif /* _ASTERISK_STASIS_MESSAGE_ROUTER_H */</span><br><span>diff --git a/main/stasis.c b/main/stasis.c</span><br><span>index 0c60b13..69ec1a5 100644</span><br><span>--- a/main/stasis.c</span><br><span>+++ b/main/stasis.c</span><br><span>@@ -399,6 +399,8 @@</span><br><span> </span><br><span> /*! The message types this subscription is accepting */</span><br><span> AST_VECTOR(, char) accepted_message_types;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! The message formatters this subscription is accepting */</span><br><span style="color: hsl(120, 100%, 40%);">+ enum stasis_subscription_message_formatters accepted_formatters;</span><br><span> /*! The message filter currently in use */</span><br><span> enum stasis_subscription_message_filter filter;</span><br><span> };</span><br><span>@@ -443,6 +445,10 @@</span><br><span> ao2_unlock(sub);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * If filtering is turned on and this is a 'final' message, we only invoke the callback</span><br><span style="color: hsl(120, 100%, 40%);">+ * if the subscriber accepts subscription_change message types.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> if (!final || sub->filter != STASIS_SUBSCRIPTION_FILTER_SELECTIVE ||</span><br><span> (message_type_id < AST_VECTOR_SIZE(&sub->accepted_message_types) && AST_VECTOR_GET(&sub->accepted_message_types, message_type_id))) {</span><br><span> /* Since sub is mostly immutable, no need to lock sub */</span><br><span>@@ -520,6 +526,7 @@</span><br><span> ast_cond_init(&sub->join_cond, NULL);</span><br><span> sub->filter = STASIS_SUBSCRIPTION_FILTER_NONE;</span><br><span> AST_VECTOR_INIT(&sub->accepted_message_types, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ sub->accepted_formatters = STASIS_SUBSCRIPTION_FORMATTER_NONE;</span><br><span> </span><br><span> if (topic_add_subscription(topic, sub) != 0) {</span><br><span> ao2_ref(sub, -1);</span><br><span>@@ -676,6 +683,18 @@</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void stasis_subscription_accept_formatters(struct stasis_subscription *subscription,</span><br><span style="color: hsl(120, 100%, 40%);">+ enum stasis_subscription_message_formatters formatters)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(subscription != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_lock(subscription->topic);</span><br><span style="color: hsl(120, 100%, 40%);">+ subscription->accepted_formatters = formatters;</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_unlock(subscription->topic);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void stasis_subscription_join(struct stasis_subscription *subscription)</span><br><span> {</span><br><span> if (subscription) {</span><br><span>@@ -871,17 +890,57 @@</span><br><span> struct stasis_message *message,</span><br><span> int synchronous)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- /* Determine if this subscription is interested in this message. Note that final</span><br><span style="color: hsl(0, 100%, 40%);">- * messages are special and are always invoked on the subscription.</span><br><span style="color: hsl(120, 100%, 40%);">+ int is_final = stasis_subscription_final_message(sub, message);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * The 'do while' gives us an easy way to skip remaining logic once</span><br><span style="color: hsl(120, 100%, 40%);">+ * we determine the message should be accepted.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The code looks more verbose than it needs to be but it optimizes</span><br><span style="color: hsl(120, 100%, 40%);">+ * down very nicely. It's just easier to understand and debug this way.</span><br><span> */</span><br><span style="color: hsl(0, 100%, 40%);">- if (sub->filter == STASIS_SUBSCRIPTION_FILTER_SELECTIVE) {</span><br><span style="color: hsl(0, 100%, 40%);">- int message_type_id = stasis_message_type_id(stasis_message_type(message));</span><br><span style="color: hsl(0, 100%, 40%);">- if ((message_type_id >= AST_VECTOR_SIZE(&sub->accepted_message_types) ||</span><br><span style="color: hsl(0, 100%, 40%);">- !AST_VECTOR_GET(&sub->accepted_message_types, message_type_id)) &&</span><br><span style="color: hsl(0, 100%, 40%);">- !stasis_subscription_final_message(sub, message)) {</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(120, 100%, 40%);">+ do {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *message_type = stasis_message_type(message);</span><br><span style="color: hsl(120, 100%, 40%);">+ int type_id = stasis_message_type_id(message_type);</span><br><span style="color: hsl(120, 100%, 40%);">+ int type_filter_specified = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int formatter_filter_specified = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int type_filter_passed = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ int formatter_filter_passed = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We always accept final messages so only run the filter logic if not final */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (is_final) {</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ type_filter_specified = sub->filter & STASIS_SUBSCRIPTION_FILTER_SELECTIVE;</span><br><span style="color: hsl(120, 100%, 40%);">+ formatter_filter_specified = sub->accepted_formatters != STASIS_SUBSCRIPTION_FORMATTER_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Accept if no filters of either type were specified */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!type_filter_specified && !formatter_filter_specified) {</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ type_filter_passed = type_filter_specified</span><br><span style="color: hsl(120, 100%, 40%);">+ && type_id < AST_VECTOR_SIZE(&sub->accepted_message_types)</span><br><span style="color: hsl(120, 100%, 40%);">+ && AST_VECTOR_GET(&sub->accepted_message_types, type_id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Since the type and formatter filters are OR'd, we can skip</span><br><span style="color: hsl(120, 100%, 40%);">+ * the formatter check if the type check passes.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (type_filter_passed) {</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ formatter_filter_passed = formatter_filter_specified</span><br><span style="color: hsl(120, 100%, 40%);">+ && (sub->accepted_formatters & stasis_message_type_available_formatters(message_type));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (formatter_filter_passed) {</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ } while (0);</span><br><span> </span><br><span> if (!sub->mailbox) {</span><br><span> /* Dispatch directly */</span><br><span>diff --git a/main/stasis_message.c b/main/stasis_message.c</span><br><span>index 1fdbe85..d3f304c 100644</span><br><span>--- a/main/stasis_message.c</span><br><span>+++ b/main/stasis_message.c</span><br><span>@@ -40,6 +40,7 @@</span><br><span> char *name;</span><br><span> unsigned int hash;</span><br><span> int id;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum stasis_subscription_message_formatters available_formatters;</span><br><span> };</span><br><span> </span><br><span> static struct stasis_message_vtable null_vtable = {};</span><br><span>@@ -80,6 +81,15 @@</span><br><span> }</span><br><span> type->hash = ast_hashtab_hash_string(name);</span><br><span> type->vtable = vtable;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (vtable->to_json) {</span><br><span style="color: hsl(120, 100%, 40%);">+ type->available_formatters |= STASIS_SUBSCRIPTION_FORMATTER_JSON;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (vtable->to_ami) {</span><br><span style="color: hsl(120, 100%, 40%);">+ type->available_formatters |= STASIS_SUBSCRIPTION_FORMATTER_AMI;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (vtable->to_event) {</span><br><span style="color: hsl(120, 100%, 40%);">+ type->available_formatters |= STASIS_SUBSCRIPTION_FORMATTER_EVENT;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> type->id = ast_atomic_fetchadd_int(&message_type_id, +1);</span><br><span> *result = type;</span><br><span> </span><br><span>@@ -101,6 +111,12 @@</span><br><span> return type->id;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+enum stasis_subscription_message_formatters stasis_message_type_available_formatters(</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct stasis_message_type *type)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return type->available_formatters;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \internal */</span><br><span> struct stasis_message {</span><br><span> /*! Time the message was created */</span><br><span>diff --git a/main/stasis_message_router.c b/main/stasis_message_router.c</span><br><span>index 41ebc7e..197f7f9 100644</span><br><span>--- a/main/stasis_message_router.c</span><br><span>+++ b/main/stasis_message_router.c</span><br><span>@@ -399,3 +399,13 @@</span><br><span> /* While this implementation can never fail, it used to be able to */</span><br><span> return 0;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void stasis_message_router_accept_formatters(struct stasis_message_router *router,</span><br><span style="color: hsl(120, 100%, 40%);">+ enum stasis_subscription_message_formatters formatters)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(router != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_subscription_accept_formatters(router->subscription, formatters);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/tests/test_stasis.c b/tests/test_stasis.c</span><br><span>index 5bc38c5..e620039 100644</span><br><span>--- a/tests/test_stasis.c</span><br><span>+++ b/tests/test_stasis.c</span><br><span>@@ -38,7 +38,13 @@</span><br><span> #include "asterisk/stasis_message_router.h"</span><br><span> #include "asterisk/test.h"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static const char *test_category = "/stasis/core/";</span><br><span style="color: hsl(120, 100%, 40%);">+#define test_category "/stasis/core/"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_event *fake_event(struct stasis_message *message)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_event_new(AST_EVENT_CUSTOM,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_EVENT_IE_DESCRIPTION, AST_EVENT_IE_PLTYPE_STR, "Dummy", AST_EVENT_IE_END);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> static struct ast_json *fake_json(struct stasis_message *message, const struct stasis_message_sanitizer *sanitize)</span><br><span> {</span><br><span>@@ -2044,6 +2050,389 @@</span><br><span> return AST_TEST_PASS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct test_message_types {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *none;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *ami;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *json;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *event;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *amievent;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *type1;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *type2;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *type3;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_type *change;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void destroy_message_types(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct test_message_types *types = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(types->none);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(types->ami);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(types->json);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(types->event);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(types->amievent);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(types->type1);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(types->type2);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(types->type3);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* N.B. Don't cleanup types->change! */</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct test_message_types *create_message_types(struct ast_test *test)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message_vtable vtable = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+ struct test_message_types *types;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_test_result_state __attribute__ ((unused)) rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ types = ao2_alloc(sizeof(*types), destroy_message_types);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!types) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test,</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_create("TestMessageNONE", &vtable, &types->none) == STASIS_MESSAGE_TYPE_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vtable.to_ami = fake_ami;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test,</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_create("TestMessageAMI", &vtable, &types->ami) == STASIS_MESSAGE_TYPE_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vtable.to_ami = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ vtable.to_json = fake_json;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test,</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_create("TestMessageJSON", &vtable, &types->json) == STASIS_MESSAGE_TYPE_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vtable.to_ami = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ vtable.to_json = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ vtable.to_event = fake_event;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test,</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_create("TestMessageEVENT", &vtable, &types->event) == STASIS_MESSAGE_TYPE_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ vtable.to_ami = fake_ami;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test,</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_create("TestMessageAMIEVENT", &vtable, &types->amievent) == STASIS_MESSAGE_TYPE_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test,</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_create("TestMessageType1", NULL, &types->type1) == STASIS_MESSAGE_TYPE_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test,</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_create("TestMessageType2", NULL, &types->type2) == STASIS_MESSAGE_TYPE_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test,</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_create("TestMessageType3", NULL, &types->type3) == STASIS_MESSAGE_TYPE_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ types->change = stasis_subscription_change_type();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return types;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(types);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct cts {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct consumer *consumer;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_topic *topic;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_subscription *sub;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void destroy_cts(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cts *c = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_unsubscribe(c->sub);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(c->topic);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(c->consumer);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct cts *create_cts(struct ast_test *test)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cts *cts = ao2_alloc(sizeof(*cts), destroy_cts);</span><br><span style="color: hsl(120, 100%, 40%);">+ enum ast_test_result_state __attribute__ ((unused)) rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test, cts, rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cts->topic = stasis_topic_create("TestTopic");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test, NULL != cts->topic, rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cts->consumer = consumer_create(0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test, NULL != cts->consumer, rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(cts->consumer, +1);</span><br><span style="color: hsl(120, 100%, 40%);">+ cts->sub = stasis_subscribe(cts->topic, consumer_exec, cts->consumer);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate_cleanup(test, NULL != cts->sub, rc, cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return cts;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cleanup:</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(cts);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int is_msg(struct stasis_message *msg, struct stasis_message_type *mtype, const char *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_subscription_change *msg_data = stasis_message_data(msg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (stasis_message_type(msg) != mtype) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (data) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return (strcmp(data, msg_data->description) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void dump_consumer(struct ast_test *test, struct cts *cts)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_subscription_change *data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Messages received: %ld Final? %s\n", cts->consumer->messages_rxed_len,</span><br><span style="color: hsl(120, 100%, 40%);">+ cts->consumer->complete ? "yes" : "no");</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < cts->consumer->messages_rxed_len; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ data = stasis_message_data(cts->consumer->messages_rxed[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Message type received: %s %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_name(stasis_message_type(cts->consumer->messages_rxed[i])),</span><br><span style="color: hsl(120, 100%, 40%);">+ data && data->description ? data->description : "no data");</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int send_msg(struct ast_test *test, struct cts *cts, struct stasis_message_type *msg_type,</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_message *msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_subscription_change *test_data =</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_alloc(sizeof(*test_data) + (data ? strlen(data) : strlen("no data")) + 1, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!test_data) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ strcpy(test_data->description, S_OR(data, "no data")); /* Safe */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg = stasis_message_create(msg_type, test_data);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(test_data, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unable to create %s message\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_message_type_name(msg_type));</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_publish(cts->topic, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(msg, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(type_filters)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct cts *, cts, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct test_message_types *, types, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ int ix = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = __func__;</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = test_category "filtering/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Test message filtering by type";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Test message filtering by type";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ types = create_message_types(test);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, NULL != types);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cts = create_cts(test);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, NULL != cts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, stasis_subscription_accept_message_type(cts->sub, types->type1) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, stasis_subscription_accept_message_type(cts->sub, types->type2) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, stasis_subscription_accept_message_type(cts->sub, types->change) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, stasis_subscription_set_filter(cts->sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should get these */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type1, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type2, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* ... but not this one */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type3, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Wait for change(subscribe) and "Pass" messages */</span><br><span style="color: hsl(120, 100%, 40%);">+ consumer_wait_for(cts->consumer, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Remove type 1 */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, stasis_subscription_decline_message_type(cts->sub, types->type1) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should now NOT get this one */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type1, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should get this one (again) */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type2, "Pass2"));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We still should NOT get this one */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type3, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should now have a second type2 */</span><br><span style="color: hsl(120, 100%, 40%);">+ consumer_wait_for(cts->consumer, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_unsubscribe(cts->sub);</span><br><span style="color: hsl(120, 100%, 40%);">+ cts->sub = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ consumer_wait_for_completion(cts->consumer);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_consumer(test, cts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, 1 == cts->consumer->complete);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, 5 == cts->consumer->messages_rxed_len);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->change, "Subscribe"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->type1, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->type2, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->type2, "Pass2"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->change, "Unsubscribe"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(formatter_filters)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct cts *, cts, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct test_message_types *, types, NULL, ao2_cleanup) ;</span><br><span style="color: hsl(120, 100%, 40%);">+ int ix = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = __func__;</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = test_category "filtering/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Test message filtering by formatter";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Test message filtering by formatter";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ types = create_message_types(test);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, NULL != types);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cts = create_cts(test);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, NULL != cts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_subscription_accept_formatters(cts->sub,</span><br><span style="color: hsl(120, 100%, 40%);">+ STASIS_SUBSCRIPTION_FORMATTER_AMI | STASIS_SUBSCRIPTION_FORMATTER_JSON);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should get these */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->ami, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->json, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->amievent, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* ... but not these */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->none, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->event, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type1, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Wait for change(subscribe) and the "Pass" messages */</span><br><span style="color: hsl(120, 100%, 40%);">+ consumer_wait_for(cts->consumer, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Change the subscription to accept only event formatters */</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_subscription_accept_formatters(cts->sub, STASIS_SUBSCRIPTION_FORMATTER_EVENT);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should NOT get these now */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->ami, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->json, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* ... but we should still get this one */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->amievent, "Pass2"));</span><br><span style="color: hsl(120, 100%, 40%);">+ /* ... and this one should be new */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->event, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should now have a second amievent */</span><br><span style="color: hsl(120, 100%, 40%);">+ consumer_wait_for(cts->consumer, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_unsubscribe(cts->sub);</span><br><span style="color: hsl(120, 100%, 40%);">+ cts->sub = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ consumer_wait_for_completion(cts->consumer);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_consumer(test, cts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, 1 == cts->consumer->complete);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, 7 == cts->consumer->messages_rxed_len);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->change, "Subscribe"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->ami, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->json, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->amievent, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->amievent, "Pass2"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->event, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->change, "Unsubscribe"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(combo_filters)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct cts *, cts, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct test_message_types *, types, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ int ix = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = __func__;</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = test_category "filtering/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Test message filtering by type and formatter";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Test message filtering by type and formatter";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ types = create_message_types(test);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, NULL != types);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cts = create_cts(test);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, NULL != cts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, stasis_subscription_accept_message_type(cts->sub, types->type1) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, stasis_subscription_accept_message_type(cts->sub, types->type2) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, stasis_subscription_accept_message_type(cts->sub, types->change) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, stasis_subscription_set_filter(cts->sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_subscription_accept_formatters(cts->sub,</span><br><span style="color: hsl(120, 100%, 40%);">+ STASIS_SUBSCRIPTION_FORMATTER_AMI | STASIS_SUBSCRIPTION_FORMATTER_JSON);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* We should get these */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type1, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type2, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->ami, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->amievent, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->json, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* ... but not these */</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->type3, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, send_msg(test, cts, types->event, "FAIL"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Wait for change(subscribe) and the "Pass" messages */</span><br><span style="color: hsl(120, 100%, 40%);">+ consumer_wait_for(cts->consumer, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ stasis_unsubscribe(cts->sub);</span><br><span style="color: hsl(120, 100%, 40%);">+ cts->sub = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ consumer_wait_for_completion(cts->consumer);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_consumer(test, cts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, 1 == cts->consumer->complete);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, 7 == cts->consumer->messages_rxed_len);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->change, "Subscribe"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->type1, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->type2, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->ami, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->amievent, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->json, "Pass"));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_validate(test, is_msg(cts->consumer->messages_rxed[ix++], types->change, "Unsubscribe"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int unload_module(void)</span><br><span> {</span><br><span> AST_TEST_UNREGISTER(message_type);</span><br><span>@@ -2070,6 +2459,9 @@</span><br><span> AST_TEST_UNREGISTER(to_ami);</span><br><span> AST_TEST_UNREGISTER(dtor_order);</span><br><span> AST_TEST_UNREGISTER(caching_dtor_order);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(type_filters);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(formatter_filters);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(combo_filters);</span><br><span> return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -2099,6 +2491,9 @@</span><br><span> AST_TEST_REGISTER(to_ami);</span><br><span> AST_TEST_REGISTER(dtor_order);</span><br><span> AST_TEST_REGISTER(caching_dtor_order);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(type_filters);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(formatter_filters);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(combo_filters);</span><br><span> return AST_MODULE_LOAD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10740">change 10740</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10740"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Ifdb7a222a73b6b56c6bb9e4ee93dc8a394a5494c </div>
<div style="display:none"> Gerrit-Change-Number: 10740 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation (1000185) </div>
<div style="display:none"> Gerrit-Reviewer: Joshua C. Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>