<p>George Joseph has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/10739">View Change</a></p><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, 543 insertions(+), 10 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/39/10739/1</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 dd9583e..06ddc7e 100644</span><br><span>--- a/include/asterisk/stasis.h</span><br><span>+++ b/include/asterisk/stasis.h</span><br><span>@@ -303,6 +303,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>@@ -686,6 +701,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..9aa3706 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,18 @@</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%);">+ * \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 f869821..0400b75 100644</span><br><span>--- a/main/stasis.c</span><br><span>+++ b/main/stasis.c</span><br><span>@@ -401,6 +401,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>@@ -445,6 +447,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>@@ -522,6 +528,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>@@ -678,6 +685,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>@@ -873,17 +892,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 2685a43..f77b9a4 100644</span><br><span>--- a/main/stasis_message.c</span><br><span>+++ b/main/stasis_message.c</span><br><span>@@ -42,6 +42,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>@@ -82,6 +83,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>@@ -103,6 +113,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 e9aebe8..edeff1d 100644</span><br><span>--- a/main/stasis_message_router.c</span><br><span>+++ b/main/stasis_message_router.c</span><br><span>@@ -401,3 +401,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 5c7ab10..c8bde5d 100644</span><br><span>--- a/tests/test_stasis.c</span><br><span>+++ b/tests/test_stasis.c</span><br><span>@@ -39,7 +39,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>@@ -2045,6 +2051,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>@@ -2071,6 +2460,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>@@ -2100,6 +2492,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/10739">change 10739</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/10739"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ifdb7a222a73b6b56c6bb9e4ee93dc8a394a5494c </div>
<div style="display:none"> Gerrit-Change-Number: 10739 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>