[RFC PATCH] huawei: handle disconnection via ^NDISSTAT unsolicited message

Aleksander Morgado aleksander at lanedo.com
Tue Sep 17 00:12:24 PDT 2013


On 17/09/13 01:17, Ben Chan wrote:
> This patch changes MMBroadbandModemHuawei to use ^NDISSTAT unsolicited
> messages to handle network-initiated disconnection. As a ^NDISSTAT
> unsolicited message is similar to a ^NDISSTATQRY response, the patch
> refactors and reuses the ^NDISSTATQRY parser code to handle both
> ^NDISSTAT and ^NDISSTATQRY responses.
> ---
> Hey Aleksander and Dan,
> 
> This follows up the discussion on
> http://lists.freedesktop.org/archives/modemmanager-devel/2013-September/000236.html
> 
> We're not entirely sure whether the ^NDISSTAT unsolicited message can replace
> the ^NDISSTATQRY poll for obtaining connection status, so this patch doesn't
> particularly address that.
> 
> This patch may miss a few corner cases, but it's better to get some feedback
> from you at this stage.
> 
> There is also one outstanding issue we observe from MU736 that we may need to
> delay the invocation of mm_bearer_report_disconnection upon receiving
> ^NDISSTAT by seconds to tens of second. Otherwise, the modem may run into a
> weird state if we try to reconnect too soon.
> 

Is there any way to avoid needing the
"mm_broadband_modem_huawei_ignore_ndisstat_unsolicited_msg()" method?
Why not always listen to NDISSTAT messages in the modem object and check
whether the bearers are being connected/disconnected and avoid doing
anything in those cases? Ideally, a bearer shouldn't ask to modify the
modem behaviour; but the modem can check its own bearers and do
different things based on what it sees. Think of modems with multiple
bearers.

This whole thing of needing to ignore the unsolicited messages during
the connection and disconnection attempts is the one complicating the
logic a lot. How sure/unsure are you that we cannot use the unsolicited
messages to complete the connection/disconnection attempt with these?
Are really not reliable? Or are they and we can just use them (that
would simplify the logic quite a lot)?

Also, I would just modify the regex to accept either NDISSTATQRY or
NDISSTAT in the message; instead of creating a new regex with the
specific string each time.


> Thanks,
> Ben
> 
> 
> 
>  plugins/huawei/mm-broadband-bearer-huawei.c      |  12 +++
>  plugins/huawei/mm-broadband-modem-huawei.c       | 100 +++++++++++++++++--
>  plugins/huawei/mm-broadband-modem-huawei.h       |   3 +
>  plugins/huawei/mm-modem-helpers-huawei.c         |  74 +++++++++++---
>  plugins/huawei/mm-modem-helpers-huawei.h         |   8 ++
>  plugins/huawei/tests/test-modem-helpers-huawei.c | 120 ++++++++++++++---------
>  6 files changed, 245 insertions(+), 72 deletions(-)
> 
> diff --git a/plugins/huawei/mm-broadband-bearer-huawei.c b/plugins/huawei/mm-broadband-bearer-huawei.c
> index eec37f3..4d79fac 100644
> --- a/plugins/huawei/mm-broadband-bearer-huawei.c
> +++ b/plugins/huawei/mm-broadband-bearer-huawei.c
> @@ -63,6 +63,9 @@ typedef struct {
>  static void
>  connect_3gpp_context_complete_and_free (Connect3gppContext *ctx)
>  {
> +    mm_broadband_modem_huawei_ignore_ndisstat_unsolicited_msg (MM_BROADBAND_MODEM_HUAWEI (ctx->modem),
> +                                                               FALSE /* ignore */);
> +
>      g_simple_async_result_complete_in_idle (ctx->result);
>      g_object_unref (ctx->cancellable);
>      g_object_unref (ctx->result);
> @@ -399,6 +402,9 @@ connect_3gpp (MMBroadbandBearer *self,
>          return;
>      }
>  
> +    mm_broadband_modem_huawei_ignore_ndisstat_unsolicited_msg (MM_BROADBAND_MODEM_HUAWEI (ctx->modem),
> +                                                               TRUE /* ignore */);
> +
>      /* Run! */
>      connect_3gpp_context_step (ctx);
>  }
> @@ -426,6 +432,9 @@ typedef struct {
>  static void
>  disconnect_3gpp_context_complete_and_free (Disconnect3gppContext *ctx)
>  {
> +    mm_broadband_modem_huawei_ignore_ndisstat_unsolicited_msg (MM_BROADBAND_MODEM_HUAWEI (ctx->modem),
> +                                                               FALSE /* ignore */);
> +
>      g_simple_async_result_complete (ctx->result);
>      g_object_unref (ctx->result);
>      g_object_unref (ctx->primary);
> @@ -633,6 +642,9 @@ disconnect_3gpp (MMBroadbandBearer *self,
>      g_assert (ctx->self->priv->connect_pending == NULL);
>      g_assert (ctx->self->priv->disconnect_pending == NULL);
>  
> +    mm_broadband_modem_huawei_ignore_ndisstat_unsolicited_msg (MM_BROADBAND_MODEM_HUAWEI (ctx->modem),
> +                                                               TRUE /* ignore */);
> +
>      /* Start! */
>      disconnect_3gpp_context_step (ctx);
>  }
> diff --git a/plugins/huawei/mm-broadband-modem-huawei.c b/plugins/huawei/mm-broadband-modem-huawei.c
> index 45bc806..870103b 100644
> --- a/plugins/huawei/mm-broadband-modem-huawei.c
> +++ b/plugins/huawei/mm-broadband-modem-huawei.c
> @@ -34,6 +34,7 @@
>  #include "mm-log.h"
>  #include "mm-errors-types.h"
>  #include "mm-modem-helpers.h"
> +#include "mm-modem-helpers-huawei.h"
>  #include "mm-base-modem-at.h"
>  #include "mm-iface-modem.h"
>  #include "mm-iface-modem-3gpp.h"
> @@ -43,6 +44,7 @@
>  #include "mm-broadband-modem-huawei.h"
>  #include "mm-broadband-bearer-huawei.h"
>  #include "mm-broadband-bearer.h"
> +#include "mm-bearer-list.h"
>  #include "mm-sim-huawei.h"
>  
>  static void iface_modem_init (MMIfaceModem *iface);
> @@ -85,6 +87,7 @@ struct _MMBroadbandModemHuaweiPrivate {
>  
>      /* Regex for connection status related notifications */
>      GRegex *dsflowrpt_regex;
> +    GRegex *ndisstat_regex;
>  
>      /* Regex to ignore */
>      GRegex *boot_regex;
> @@ -96,7 +99,6 @@ struct _MMBroadbandModemHuaweiPrivate {
>      GRegex *srvst_regex;
>      GRegex *stin_regex;
>      GRegex *hcsq_regex;
> -    GRegex *ndisstat_regex;
>      GRegex *pdpdeact_regex;
>      GRegex *ndisend_regex;
>      GRegex *rfswitch_regex;
> @@ -106,6 +108,8 @@ struct _MMBroadbandModemHuaweiPrivate {
>  
>      gboolean sysinfoex_supported;
>      gboolean sysinfoex_support_checked;
> +
> +    gboolean ignore_ndisstat_msg;
>  };
>  
>  /*****************************************************************************/
> @@ -1509,6 +1513,83 @@ huawei_status_changed (MMAtSerialPort *port,
>      g_free (str);
>  }
>  
> +typedef struct {
> +    gboolean ipv4_available;
> +    gboolean ipv4_connected;
> +    gboolean ipv6_available;
> +    gboolean ipv6_connected;
> +} NdisstatResult;
> +
> +static void
> +bearer_report_connection_status (MMBearer *bearer,
> +                                 NdisstatResult *ndisstat_result)
> +{
> +    /* We already use ^NDISSTATQRY? to poll the connection status, so we only
> +     * handle network-initiated disconnection here. */
> +    if (ndisstat_result->ipv4_available && !ndisstat_result->ipv4_connected) {
> +        /* TODO: MMBroadbandBearerHuawei does not currently support IPv6.
> +         * When it does, we should check the IP family associated with each bearer. */
> +        mm_dbg ("Disconnect bearer '%s'", mm_bearer_get_path (bearer));
> +        mm_bearer_report_disconnection (bearer);
> +    }
> +}
> +
> +static void
> +huawei_ndisstat_changed (MMAtSerialPort *port,
> +                         GMatchInfo *match_info,
> +                         MMBroadbandModemHuawei *self)
> +{
> +    gchar *str;
> +    NdisstatResult ndisstat_result;
> +    GError *error = NULL;
> +    MMBearerList *list = NULL;
> +
> +    str = g_match_info_fetch (match_info, 1);
> +    if (!mm_huawei_parse_ndisstat_response (str,
> +                                            &ndisstat_result.ipv4_available,
> +                                            &ndisstat_result.ipv4_connected,
> +                                            &ndisstat_result.ipv6_available,
> +                                            &ndisstat_result.ipv6_connected,
> +                                            &error)) {
> +        mm_dbg ("Ignore invalid ^NDISSTAT unsolicited message: '%s' (error %s)",
> +                str, error->message);
> +        g_error_free (error);
> +        return;
> +    }
> +
> +    mm_dbg ("NDIS status: IPv4 %s, IPv6 %s",
> +            ndisstat_result.ipv4_available ?
> +            (ndisstat_result.ipv4_connected ? "connected" : "disconnected") : "not available",
> +            ndisstat_result.ipv6_available ?
> +            (ndisstat_result.ipv6_connected ? "connected" : "disconnected") : "not available");
> +
> +    /* When a pending connection / disconnection attempt is in progress, we use
> +     * ^NDISSTATQRY? to check the connection status and thus temporarily ignore
> +     * ^NDISSTAT unsolicited messages */
> +    if (self->priv->ignore_ndisstat_msg)
> +        return;
> +
> +    /* If empty bearer list, nothing else to do */
> +    g_object_get (self,
> +                  MM_IFACE_MODEM_BEARER_LIST, &list,
> +                  NULL);
> +    if (!list)
> +        return;
> +
> +    mm_bearer_list_foreach (list,
> +                            (MMBearerListForeachFunc)bearer_report_connection_status,
> +                            &ndisstat_result);
> +
> +    g_object_unref (list);
> +}
> +
> +void
> +mm_broadband_modem_huawei_ignore_ndisstat_unsolicited_msg (MMBroadbandModemHuawei *self,
> +                                                           gboolean ignore)
> +{
> +    self->priv->ignore_ndisstat_msg = ignore;
> +}
> +
>  static void
>  set_3gpp_unsolicited_events_handlers (MMBroadbandModemHuawei *self,
>                                        gboolean enable)
> @@ -1547,6 +1628,13 @@ set_3gpp_unsolicited_events_handlers (MMBroadbandModemHuawei *self,
>              enable ? (MMAtSerialUnsolicitedMsgFn)huawei_status_changed : NULL,
>              enable ? self : NULL,
>              NULL);
> +
> +        mm_at_serial_port_add_unsolicited_msg_handler (
> +            ports[i],
> +            self->priv->ndisstat_regex,
> +            enable ? (MMAtSerialUnsolicitedMsgFn)huawei_ndisstat_changed : NULL,
> +            enable ? self : NULL,
> +            NULL);
>      }
>  }
>  
> @@ -2987,10 +3075,6 @@ set_ignored_unsolicited_events_handlers (MMBroadbandModemHuawei *self)
>              NULL, NULL, NULL);
>          mm_at_serial_port_add_unsolicited_msg_handler (
>              ports[i],
> -            self->priv->ndisstat_regex,
> -            NULL, NULL, NULL);
> -        mm_at_serial_port_add_unsolicited_msg_handler (
> -            ports[i],
>              self->priv->pdpdeact_regex,
>              NULL, NULL, NULL);
>          mm_at_serial_port_add_unsolicited_msg_handler (
> @@ -3058,6 +3142,8 @@ mm_broadband_modem_huawei_init (MMBroadbandModemHuawei *self)
>                                            G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
>      self->priv->dsflowrpt_regex = g_regex_new ("\\r\\n\\^DSFLOWRPT:(.+)\\r\\n",
>                                                 G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
> +    self->priv->ndisstat_regex = g_regex_new ("\\r\\n(\\^NDISSTAT:.+)\\r+\\n",
> +                                              G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
>      self->priv->boot_regex = g_regex_new ("\\r\\n\\^BOOT:.+\\r\\n",
>                                            G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
>      self->priv->csnr_regex = g_regex_new ("\\r\\n\\^CSNR:.+\\r\\n",
> @@ -3076,8 +3162,6 @@ mm_broadband_modem_huawei_init (MMBroadbandModemHuawei *self)
>                                            G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
>      self->priv->hcsq_regex = g_regex_new ("\\r\\n\\^HCSQ:.+\\r+\\n",
>                                            G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
> -    self->priv->ndisstat_regex = g_regex_new ("\\r\\n\\^NDISSTAT:.+\\r+\\n",
> -                                              G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
>      self->priv->pdpdeact_regex = g_regex_new ("\\r\\n\\^PDPDEACT:.+\\r+\\n",
>                                                G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
>      self->priv->ndisend_regex = g_regex_new ("\\r\\n\\^NDISEND:.+\\r+\\n",
> @@ -3102,6 +3186,7 @@ finalize (GObject *object)
>      g_regex_unref (self->priv->hrssilvl_regex);
>      g_regex_unref (self->priv->mode_regex);
>      g_regex_unref (self->priv->dsflowrpt_regex);
> +    g_regex_unref (self->priv->ndisstat_regex);
>      g_regex_unref (self->priv->boot_regex);
>      g_regex_unref (self->priv->csnr_regex);
>      g_regex_unref (self->priv->cusatp_regex);
> @@ -3111,7 +3196,6 @@ finalize (GObject *object)
>      g_regex_unref (self->priv->srvst_regex);
>      g_regex_unref (self->priv->stin_regex);
>      g_regex_unref (self->priv->hcsq_regex);
> -    g_regex_unref (self->priv->ndisstat_regex);
>      g_regex_unref (self->priv->pdpdeact_regex);
>      g_regex_unref (self->priv->ndisend_regex);
>      g_regex_unref (self->priv->rfswitch_regex);
> diff --git a/plugins/huawei/mm-broadband-modem-huawei.h b/plugins/huawei/mm-broadband-modem-huawei.h
> index 06874bc..615bbac 100644
> --- a/plugins/huawei/mm-broadband-modem-huawei.h
> +++ b/plugins/huawei/mm-broadband-modem-huawei.h
> @@ -48,4 +48,7 @@ MMBroadbandModemHuawei *mm_broadband_modem_huawei_new (const gchar *device,
>                                                         guint16 vendor_id,
>                                                         guint16 product_id);
>  
> +void mm_broadband_modem_huawei_ignore_ndisstat_unsolicited_msg (MMBroadbandModemHuawei *self,
> +                                                                gboolean ignore);
> +
>  #endif /* MM_BROADBAND_MODEM_HUAWEI_H */
> diff --git a/plugins/huawei/mm-modem-helpers-huawei.c b/plugins/huawei/mm-modem-helpers-huawei.c
> index f5abe57..92812d8 100644
> --- a/plugins/huawei/mm-modem-helpers-huawei.c
> +++ b/plugins/huawei/mm-modem-helpers-huawei.c
> @@ -25,22 +25,28 @@
>  /*****************************************************************************/
>  /* ^NDISSTATQRY response parser */
>  
> -gboolean
> -mm_huawei_parse_ndisstatqry_response (const gchar *response,
> -                                      gboolean *ipv4_available,
> -                                      gboolean *ipv4_connected,
> -                                      gboolean *ipv6_available,
> -                                      gboolean *ipv6_connected,
> -                                      GError **error)
> +static gboolean
> +parse_ndisstat_response (const gchar *response,
> +                         const gchar *ndisstat_type,
> +                         gboolean *ipv4_available,
> +                         gboolean *ipv4_connected,
> +                         gboolean *ipv6_available,
> +                         gboolean *ipv6_connected,
> +                         GError **error)
>  {
>      GRegex *r;
>      GMatchInfo *match_info;
>      GError *inner_error = NULL;
> +    gchar *prefix;
> +    gchar *regex_str;
>  
> -    if (!response || !g_str_has_prefix (response, "^NDISSTATQRY:")) {
> -        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing ^NDISSTATQRY prefix");
> +    prefix = g_strdup_printf ("^%s:", ndisstat_type);
> +    if (!response || !g_str_has_prefix (response, prefix)) {
> +        g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing %s prefix", prefix);
> +        g_free (prefix);
>          return FALSE;
>      }
> +    g_free (prefix);
>  
>      *ipv4_available = FALSE;
>      *ipv6_available = FALSE;
> @@ -54,10 +60,12 @@ mm_huawei_parse_ndisstatqry_response (const gchar *response,
>       *     ^NDISSTATQRY:0,,,"IPV4",0,,,"IPV6"
>       *     OK
>       */
> -    r = g_regex_new ("\\^NDISSTATQRY:\\s*(\\d),([^,]*),([^,]*),([^,\\r\\n]*)(?:\\r\\n)?"
> -                     "(?:\\^NDISSTATQRY:)?\\s*,?(\\d)?,?([^,]*)?,?([^,]*)?,?([^,\\r\\n]*)?(?:\\r\\n)?",
> -                     G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW,
> -                     0, NULL);
> +    regex_str = g_strdup_printf ("\\^%s:\\s*(\\d),([^,]*),([^,]*),([^,\\r\\n]*)(?:\\r\\n)?"
> +                                 "(?:\\^%s:)?\\s*,?(\\d)?,?([^,]*)?,?([^,]*)?,?([^,\\r\\n]*)?(?:\\r\\n)?",
> +                                 ndisstat_type,
> +                                 ndisstat_type);
> +    r = g_regex_new (regex_str, G_REGEX_DOLLAR_ENDONLY | G_REGEX_RAW, 0, NULL);
> +    g_free (regex_str);
>      g_assert (r != NULL);
>  
>      g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, &inner_error);
> @@ -78,7 +86,8 @@ mm_huawei_parse_ndisstatqry_response (const gchar *response,
>                  (connected != 0 && connected != 1)) {
>                  inner_error = g_error_new (MM_CORE_ERROR,
>                                             MM_CORE_ERROR_FAILED,
> -                                           "Couldn't parse ^NDISSTATQRY fields");
> +                                           "Couldn't parse ^%s fields",
> +                                           ndisstat_type);
>              } else if (g_ascii_strcasecmp (ip_type_str, "IPV4") == 0) {
>                  *ipv4_available = TRUE;
>                  *ipv4_connected = (gboolean)connected;
> @@ -98,7 +107,8 @@ mm_huawei_parse_ndisstatqry_response (const gchar *response,
>      if (!ipv4_available && !ipv6_available) {
>          inner_error = g_error_new (MM_CORE_ERROR,
>                                     MM_CORE_ERROR_FAILED,
> -                                   "Couldn't find IPv4 or IPv6 info in ^NDISSTATQRY response");
> +                                   "Couldn't find IPv4 or IPv6 info in ^%s response",
> +                                   ndisstat_type);
>      }
>  
>      if (inner_error) {
> @@ -108,3 +118,37 @@ mm_huawei_parse_ndisstatqry_response (const gchar *response,
>  
>      return TRUE;
>  }
> +
> +gboolean
> +mm_huawei_parse_ndisstat_response (const gchar *response,
> +                                   gboolean *ipv4_available,
> +                                   gboolean *ipv4_connected,
> +                                   gboolean *ipv6_available,
> +                                   gboolean *ipv6_connected,
> +                                   GError **error)
> +{
> +    return parse_ndisstat_response (response,
> +                                    "NDISSTAT",
> +                                    ipv4_available,
> +                                    ipv4_connected,
> +                                    ipv6_available,
> +                                    ipv6_connected,
> +                                    error);
> +}
> +
> +gboolean
> +mm_huawei_parse_ndisstatqry_response (const gchar *response,
> +                                      gboolean *ipv4_available,
> +                                      gboolean *ipv4_connected,
> +                                      gboolean *ipv6_available,
> +                                      gboolean *ipv6_connected,
> +                                      GError **error)
> +{
> +    return parse_ndisstat_response (response,
> +                                    "NDISSTATQRY",
> +                                    ipv4_available,
> +                                    ipv4_connected,
> +                                    ipv6_available,
> +                                    ipv6_connected,
> +                                    error);
> +}
> diff --git a/plugins/huawei/mm-modem-helpers-huawei.h b/plugins/huawei/mm-modem-helpers-huawei.h
> index cc32087..2e8148b 100644
> --- a/plugins/huawei/mm-modem-helpers-huawei.h
> +++ b/plugins/huawei/mm-modem-helpers-huawei.h
> @@ -19,6 +19,14 @@
>  
>  #include "glib.h"
>  
> +/* ^NDISSTAT response parser */
> +gboolean mm_huawei_parse_ndisstat_response (const gchar *response,
> +                                            gboolean *ipv4_available,
> +                                            gboolean *ipv4_connected,
> +                                            gboolean *ipv6_available,
> +                                            gboolean *ipv6_connected,
> +                                            GError **error);
> +
>  /* ^NDISSTATQRY response parser */
>  gboolean mm_huawei_parse_ndisstatqry_response (const gchar *response,
>                                                 gboolean *ipv4_available,
> diff --git a/plugins/huawei/tests/test-modem-helpers-huawei.c b/plugins/huawei/tests/test-modem-helpers-huawei.c
> index ea4cd95..3b3d035 100644
> --- a/plugins/huawei/tests/test-modem-helpers-huawei.c
> +++ b/plugins/huawei/tests/test-modem-helpers-huawei.c
> @@ -20,7 +20,7 @@
>  #include "mm-modem-helpers-huawei.h"
>  
>  /*****************************************************************************/
> -/* Test ^NDISSTATQRY responses */
> +/* Test ^NDISSTAT / ^NDISSTATQRY responses */
>  
>  typedef struct {
>      const gchar *str;
> @@ -28,74 +28,95 @@ typedef struct {
>      gboolean expected_ipv4_connected;
>      gboolean expected_ipv6_available;
>      gboolean expected_ipv6_connected;
> -} NdisstatqryTest;
> -
> -static const NdisstatqryTest ndisstatqry_tests[] = {
> -    { "^NDISSTATQRY: 1,,,IPV4\r\n", TRUE,  TRUE,  FALSE, FALSE },
> -    { "^NDISSTATQRY: 0,,,IPV4\r\n", TRUE,  FALSE, FALSE, FALSE },
> -    { "^NDISSTATQRY: 1,,,IPV6\r\n", FALSE, FALSE, TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 0,,,IPV6\r\n", FALSE, FALSE, TRUE,  FALSE },
> -    { "^NDISSTATQRY: 1,,,IPV4\r\n"
> -      "^NDISSTATQRY: 1,,,IPV6\r\n", TRUE,  TRUE,  TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 1,,,IPV4\r\n"
> -      "^NDISSTATQRY: 0,,,IPV6\r\n", TRUE,  TRUE,  TRUE,  FALSE },
> -    { "^NDISSTATQRY: 0,,,IPV4\r\n"
> -      "^NDISSTATQRY: 1,,,IPV6\r\n", TRUE,  FALSE, TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 0,,,IPV4\r\n"
> -      "^NDISSTATQRY: 0,,,IPV6\r\n", TRUE,  FALSE, TRUE,  FALSE },
> -    { "^NDISSTATQRY: 1,,,IPV4",     TRUE,  TRUE,  FALSE, FALSE },
> -    { "^NDISSTATQRY: 0,,,IPV4",     TRUE,  FALSE, FALSE, FALSE },
> -    { "^NDISSTATQRY: 1,,,IPV6",     FALSE, FALSE, TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 0,,,IPV6",     FALSE, FALSE, TRUE,  FALSE },
> -    { "^NDISSTATQRY: 1,,,IPV4\r\n"
> -      "^NDISSTATQRY: 1,,,IPV6",     TRUE,  TRUE,  TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 1,,,IPV4\r\n"
> -      "^NDISSTATQRY: 0,,,IPV6",     TRUE,  TRUE,  TRUE,  FALSE },
> -    { "^NDISSTATQRY: 0,,,IPV4\r\n"
> -      "^NDISSTATQRY: 1,,,IPV6",     TRUE,  FALSE, TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 0,,,IPV4\r\n"
> -      "^NDISSTATQRY: 0,,,IPV6",     TRUE,  FALSE, TRUE,  FALSE },
> -    { "^NDISSTATQRY: 1,,,\"IPV4\",1,,,\"IPV6\"",     TRUE,  TRUE,  TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 1,,,\"IPV4\",0,,,\"IPV6\"",     TRUE,  TRUE,  TRUE,  FALSE },
> -    { "^NDISSTATQRY: 0,,,\"IPV4\",1,,,\"IPV6\"",     TRUE,  FALSE, TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 0,,,\"IPV4\",0,,,\"IPV6\"",     TRUE,  FALSE, TRUE,  FALSE },
> -    { "^NDISSTATQRY: 1,,,\"IPV4\",1,,,\"IPV6\"\r\n", TRUE,  TRUE,  TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 1,,,\"IPV4\",0,,,\"IPV6\"\r\n", TRUE,  TRUE,  TRUE,  FALSE },
> -    { "^NDISSTATQRY: 0,,,\"IPV4\",1,,,\"IPV6\"\r\n", TRUE,  FALSE, TRUE,  TRUE  },
> -    { "^NDISSTATQRY: 0,,,\"IPV4\",0,,,\"IPV6\"\r\n", TRUE,  FALSE, TRUE,  FALSE },
> +} NdisstatTest;
> +
> +static const NdisstatTest ndisstat_tests[] = {
> +    { "1,,,IPV4\r\n", TRUE,  TRUE,  FALSE, FALSE },
> +    { "0,,,IPV4\r\n", TRUE,  FALSE, FALSE, FALSE },
> +    { "1,,,IPV6\r\n", FALSE, FALSE, TRUE,  TRUE  },
> +    { "0,,,IPV6\r\n", FALSE, FALSE, TRUE,  FALSE },
> +    { "1,,,IPV4\r\n"
> +      "1,,,IPV6\r\n", TRUE,  TRUE,  TRUE,  TRUE  },
> +    { "1,,,IPV4\r\n"
> +      "0,,,IPV6\r\n", TRUE,  TRUE,  TRUE,  FALSE },
> +    { "0,,,IPV4\r\n"
> +      "1,,,IPV6\r\n", TRUE,  FALSE, TRUE,  TRUE  },
> +    { "0,,,IPV4\r\n"
> +      "0,,,IPV6\r\n", TRUE,  FALSE, TRUE,  FALSE },
> +    { "1,,,IPV4",     TRUE,  TRUE,  FALSE, FALSE },
> +    { "0,,,IPV4",     TRUE,  FALSE, FALSE, FALSE },
> +    { "1,,,IPV6",     FALSE, FALSE, TRUE,  TRUE  },
> +    { "0,,,IPV6",     FALSE, FALSE, TRUE,  FALSE },
> +    { "1,,,IPV4\r\n"
> +      "1,,,IPV6",     TRUE,  TRUE,  TRUE,  TRUE  },
> +    { "1,,,IPV4\r\n"
> +      "0,,,IPV6",     TRUE,  TRUE,  TRUE,  FALSE },
> +    { "0,,,IPV4\r\n"
> +      "1,,,IPV6",     TRUE,  FALSE, TRUE,  TRUE  },
> +    { "0,,,IPV4\r\n"
> +      "0,,,IPV6",     TRUE,  FALSE, TRUE,  FALSE },
> +    { "1,,,\"IPV4\",1,,,\"IPV6\"",     TRUE,  TRUE,  TRUE,  TRUE  },
> +    { "1,,,\"IPV4\",0,,,\"IPV6\"",     TRUE,  TRUE,  TRUE,  FALSE },
> +    { "0,,,\"IPV4\",1,,,\"IPV6\"",     TRUE,  FALSE, TRUE,  TRUE  },
> +    { "0,,,\"IPV4\",0,,,\"IPV6\"",     TRUE,  FALSE, TRUE,  FALSE },
> +    { "1,,,\"IPV4\",1,,,\"IPV6\"\r\n", TRUE,  TRUE,  TRUE,  TRUE  },
> +    { "1,,,\"IPV4\",0,,,\"IPV6\"\r\n", TRUE,  TRUE,  TRUE,  FALSE },
> +    { "0,,,\"IPV4\",1,,,\"IPV6\"\r\n", TRUE,  FALSE, TRUE,  TRUE  },
> +    { "0,,,\"IPV4\",0,,,\"IPV6\"\r\n", TRUE,  FALSE, TRUE,  FALSE },
>      { NULL, FALSE, FALSE, FALSE, FALSE }
>  };
>  
> +typedef gboolean (*ParseNdisstatResponseFn) (const gchar *response,
> +                                             gboolean *ipv4_available,
> +                                             gboolean *ipv4_connected,
> +                                             gboolean *ipv6_available,
> +                                             gboolean *ipv6_connected,
> +                                             GError **error);
> +
>  static void
> -test_ndisstatqry (void)
> +test_ndisstat_common (const gchar *ndisstat_type, ParseNdisstatResponseFn parser)
>  {
> +    gchar *response;
>      guint i;
>  
> -    for (i = 0; ndisstatqry_tests[i].str; i++) {
> +    for (i = 0; ndisstat_tests[i].str; i++) {
>          GError *error = NULL;
>          gboolean ipv4_available;
>          gboolean ipv4_connected;
>          gboolean ipv6_available;
>          gboolean ipv6_connected;
>  
> -        g_assert (mm_huawei_parse_ndisstatqry_response (
> -                      ndisstatqry_tests[i].str,
> -                      &ipv4_available,
> -                      &ipv4_connected,
> -                      &ipv6_available,
> -                      &ipv6_connected,
> -                      &error) == TRUE);
> +        response = g_strdup_printf ("^%s: %s", ndisstat_type, ndisstat_tests[i].str);
> +        g_assert (parser (response,
> +                          &ipv4_available,
> +                          &ipv4_connected,
> +                          &ipv6_available,
> +                          &ipv6_connected,
> +                          &error) == TRUE);
> +        g_free (response);
>          g_assert_no_error (error);
>  
> -        g_assert (ipv4_available == ndisstatqry_tests[i].expected_ipv4_available);
> +        g_assert (ipv4_available == ndisstat_tests[i].expected_ipv4_available);
>          if (ipv4_available)
> -            g_assert (ipv4_connected == ndisstatqry_tests[i].expected_ipv4_connected);
> -        g_assert (ipv6_available == ndisstatqry_tests[i].expected_ipv6_available);
> +            g_assert (ipv4_connected == ndisstat_tests[i].expected_ipv4_connected);
> +        g_assert (ipv6_available == ndisstat_tests[i].expected_ipv6_available);
>          if (ipv6_available)
> -            g_assert (ipv6_connected == ndisstatqry_tests[i].expected_ipv6_connected);
> +            g_assert (ipv6_connected == ndisstat_tests[i].expected_ipv6_connected);
>      }
>  }
>  
> +static void
> +test_ndisstat (void)
> +{
> +    test_ndisstat_common ("NDISSTAT", mm_huawei_parse_ndisstat_response);
> +}
> +
> +static void
> +test_ndisstatqry (void)
> +{
> +    test_ndisstat_common ("NDISSTATQRY", mm_huawei_parse_ndisstatqry_response);
> +}
> +
>  /*****************************************************************************/
>  
>  int main (int argc, char **argv)
> @@ -105,6 +126,7 @@ int main (int argc, char **argv)
>      g_type_init ();
>      g_test_init (&argc, &argv, NULL);
>  
> +    g_test_add_func ("/MM/huawei/ndisstat", test_ndisstat);
>      g_test_add_func ("/MM/huawei/ndisstatqry", test_ndisstatqry);
>  
>      return g_test_run ();
> 


-- 
Aleksander


More information about the ModemManager-devel mailing list