aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2010-01-05 14:29:19 -0600
committerDan Williams <dcbw@redhat.com>2010-01-05 14:29:19 -0600
commit216e49f8d8bbfbc0b7d2fbd00ac712a2de41b33a (patch)
tree20a91de71c45266abdde5fcfee9d0a8beae15483
parenta06b3f20cafab2ff2d1de16553f7ff578a9b761b (diff)
gsm: split out +COPS response parsing and add testcases
-rw-r--r--configure.ac15
-rw-r--r--src/Makefile.am18
-rw-r--r--src/mm-generic-gsm.c113
-rw-r--r--src/mm-modem-helpers.c140
-rw-r--r--src/mm-modem-helpers.h31
-rw-r--r--src/tests/Makefile.am22
-rw-r--r--src/tests/test-modem-helpers.c371
7 files changed, 601 insertions, 109 deletions
diff --git a/configure.ac b/configure.ac
index 4d5e6f88..140708fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -96,10 +96,25 @@ case $with_docs in
;;
esac
+dnl
+dnl Tests
+dnl
+AC_ARG_WITH(tests, AS_HELP_STRING([--with-tests], [Build ModemManager tests]))
+AM_CONDITIONAL(WITH_TESTS, test "x$with_tests" = "xyes")
+case $with_tests in
+ yes)
+ with_tests=yes
+ ;;
+ *)
+ with_tests=no
+ ;;
+esac
+
AC_CONFIG_FILES([
Makefile
marshallers/Makefile
src/Makefile
+src/tests/Makefile
plugins/Makefile
test/Makefile
introspection/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 8a5ccb89..9209b55f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,3 +1,16 @@
+SUBDIRS=. tests
+
+noinst_LTLIBRARIES = libmodem-helpers.la
+
+libmodem_helpers_la_CPPFLAGS = \
+ $(MM_CFLAGS)
+
+libmodem_helpers_la_SOURCES = \
+ mm-errors.c \
+ mm-errors.h \
+ mm-modem-helpers.c \
+ mm-modem-helpers.h
+
sbin_PROGRAMS = modem-manager
modem_manager_CPPFLAGS = \
@@ -9,14 +22,13 @@ modem_manager_CPPFLAGS = \
modem_manager_LDADD = \
$(MM_LIBS) \
$(GUDEV_LIBS) \
- $(top_builddir)/marshallers/libmarshallers.la
+ $(top_builddir)/marshallers/libmarshallers.la \
+ $(builddir)/libmodem-helpers.la
modem_manager_SOURCES = \
main.c \
mm-callback-info.c \
mm-callback-info.h \
- mm-errors.c \
- mm-errors.h \
mm-manager.c \
mm-manager.h \
mm-modem.c \
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index e5a69a21..25c6c1ee 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -27,6 +27,7 @@
#include "mm-errors.h"
#include "mm-callback-info.h"
#include "mm-serial-parsers.h"
+#include "mm-modem-helpers.h"
static void modem_init (MMModem *modem_class);
static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class);
@@ -1432,122 +1433,22 @@ gsm_network_scan_invoke (MMCallbackInfo *info)
}
static void
-destroy_scan_data (gpointer data)
-{
- GPtrArray *results = (GPtrArray *) data;
-
- g_ptr_array_foreach (results, (GFunc) g_hash_table_destroy, NULL);
- g_ptr_array_free (results, TRUE);
-}
-
-static void
scan_done (MMSerialPort *port,
GString *response,
GError *error,
gpointer user_data)
{
MMCallbackInfo *info = (MMCallbackInfo *) user_data;
- char *reply = response->str;
+ GPtrArray *results;
if (error)
info->error = g_error_copy (error);
- else if (strstr (reply, "+COPS: ")) {
- /* Got valid reply */
- GPtrArray *results;
- GRegex *r;
- GMatchInfo *match_info;
- GError *err = NULL;
- gboolean umts_format = TRUE;
-
- reply = strstr (reply, "+COPS: ") + 7;
-
- /* Pattern without crazy escaping using | for matching: (|\d|,"|.+|","|.+|","|.+|"\)?,|\d|) */
-
- /* Cell access technology (GSM, UTRAN, etc) got added later and not all
- * modems implement it. Some modesm have quirks that make it hard to
- * use one regular experession for matching both pre-UMTS and UMTS
- * responses. So try UMTS-format first and fall back to pre-UMTS if
- * we get no UMTS-formst matches.
- */
-
- /* Quirk: Sony-Ericsson TM-506 sometimes includes a stray ')' like so,
- * which is what makes it hard to match both pre-UMTS and UMTS in
- * the same regex:
- *
- * +COPS: (2,"","T-Mobile","31026",0),(1,"AT&T","AT&T","310410"),0)
- */
-
- r = g_regex_new ("\\((\\d),\"(.*)\",\"(.*)\",\"(.*)\"[\\)]?,(\\d)\\)", G_REGEX_UNGREEDY, 0, &err);
- if (err) {
- g_error ("Invalid regular expression: %s", err->message);
- g_error_free (err);
- info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "Could not parse scan results.");
- goto out;
- }
-
- /* If we didn't get any hits, try the pre-UMTS format match */
- if (!g_regex_match (r, reply, 0, &match_info)) {
- g_regex_unref (r);
- if (match_info) {
- g_match_info_free (match_info);
- match_info = NULL;
- }
-
- /* Pre-UMTS format doesn't include the cell access technology after
- * the numeric operator element.
- *
- * Ex: Motorola C-series (BUSlink SCWi275u) like so:
- *
- * +COPS: (2,"T-Mobile","","310260"),(0,"Cingular Wireless","","310410")
- */
- r = g_regex_new ("\\((\\d),\"(.*)\",\"(.*)\",\"(.*)\"\\)", G_REGEX_UNGREEDY, 0, &err);
- if (err) {
- g_error ("Invalid regular expression: %s", err->message);
- g_error_free (err);
- info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "Could not parse scan results.");
- goto out;
- }
-
- g_regex_match (r, reply, 0, &match_info);
- umts_format = FALSE;
- }
-
- /* Parse the results */
- results = g_ptr_array_new ();
- while (g_match_info_matches (match_info)) {
- GHashTable *hash;
- char *access_tech = NULL;
-
- hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- g_hash_table_insert (hash, g_strdup ("status"), g_match_info_fetch (match_info, 1));
- g_hash_table_insert (hash, g_strdup ("operator-long"), g_match_info_fetch (match_info, 2));
- g_hash_table_insert (hash, g_strdup ("operator-short"), g_match_info_fetch (match_info, 3));
- g_hash_table_insert (hash, g_strdup ("operator-num"), g_match_info_fetch (match_info, 4));
-
- /* Only try for access technology with UMTS-format matches */
- if (umts_format)
- access_tech = g_match_info_fetch (match_info, 5);
- if (access_tech && (strlen (access_tech) == 1)) {
- /* Recognized access technologies are between '0' and '6' inclusive... */
- if ((access_tech[0] >= 48) && (access_tech[0] <= 54))
- g_hash_table_insert (hash, g_strdup ("access-tech"), access_tech);
- } else
- g_free (access_tech);
-
- g_ptr_array_add (results, hash);
- g_match_info_next (match_info, NULL);
- }
-
- mm_callback_info_set_data (info, "scan-results", results, destroy_scan_data);
- g_match_info_free (match_info);
- g_regex_unref (r);
- } else
- info->error = g_error_new_literal (MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
- "Could not parse scan results.");
+ else {
+ results = mm_gsm_parse_scan_response (response->str, &info->error);
+ if (results)
+ mm_callback_info_set_data (info, "scan-results", results, mm_gsm_destroy_scan_data);
+ }
- out:
mm_callback_info_schedule (info);
}
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
new file mode 100644
index 00000000..809eab9a
--- /dev/null
+++ b/src/mm-modem-helpers.c
@@ -0,0 +1,140 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 - 2010 Red Hat, Inc.
+ */
+
+#include <glib.h>
+#include <string.h>
+
+#include "mm-errors.h"
+#include "mm-modem-helpers.h"
+
+GPtrArray *
+mm_gsm_parse_scan_response (const char *reply, GError **error)
+{
+ /* Got valid reply */
+ GPtrArray *results = NULL;
+ GRegex *r;
+ GMatchInfo *match_info;
+ GError *err = NULL;
+ gboolean umts_format = TRUE;
+
+ g_return_val_if_fail (reply != NULL, NULL);
+ if (error)
+ g_return_val_if_fail (*error == NULL, NULL);
+
+ if (!strstr (reply, "+COPS: ")) {
+ g_set_error_literal (error,
+ MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Could not parse scan results.");
+ return NULL;
+ }
+
+ reply = strstr (reply, "+COPS: ") + 7;
+
+ /* Cell access technology (GSM, UTRAN, etc) got added later and not all
+ * modems implement it. Some modesm have quirks that make it hard to
+ * use one regular experession for matching both pre-UMTS and UMTS
+ * responses. So try UMTS-format first and fall back to pre-UMTS if
+ * we get no UMTS-formst matches.
+ */
+
+ /* Quirk: Sony-Ericsson TM-506 sometimes includes a stray ')' like so,
+ * which is what makes it hard to match both pre-UMTS and UMTS in
+ * the same regex:
+ *
+ * +COPS: (2,"","T-Mobile","31026",0),(1,"AT&T","AT&T","310410"),0)
+ */
+
+ r = g_regex_new ("\\((\\d),\"(.*)\",\"(.*)\",\"(.*)\"[\\)]?,(\\d)\\)", G_REGEX_UNGREEDY, 0, &err);
+ if (err) {
+ g_error ("Invalid regular expression: %s", err->message);
+ g_error_free (err);
+ g_set_error_literal (error,
+ MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Could not parse scan results.");
+ return NULL;
+ }
+
+ /* If we didn't get any hits, try the pre-UMTS format match */
+ if (!g_regex_match (r, reply, 0, &match_info)) {
+ g_regex_unref (r);
+ if (match_info) {
+ g_match_info_free (match_info);
+ match_info = NULL;
+ }
+
+ /* Pre-UMTS format doesn't include the cell access technology after
+ * the numeric operator element.
+ *
+ * Ex: Motorola C-series (BUSlink SCWi275u) like so:
+ *
+ * +COPS: (2,"T-Mobile","","310260"),(0,"Cingular Wireless","","310410")
+ */
+ r = g_regex_new ("\\((\\d),\"(.*)\",\"(.*)\",\"(.*)\"\\)", G_REGEX_UNGREEDY, 0, &err);
+ if (err) {
+ g_error ("Invalid regular expression: %s", err->message);
+ g_error_free (err);
+ g_set_error_literal (error,
+ MM_MODEM_ERROR, MM_MODEM_ERROR_GENERAL,
+ "Could not parse scan results.");
+ return NULL;
+ }
+
+ g_regex_match (r, reply, 0, &match_info);
+ umts_format = FALSE;
+ }
+
+ /* Parse the results */
+ results = g_ptr_array_new ();
+ while (g_match_info_matches (match_info)) {
+ GHashTable *hash;
+ char *access_tech = NULL;
+
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ g_hash_table_insert (hash, g_strdup (MM_SCAN_TAG_STATUS), g_match_info_fetch (match_info, 1));
+ g_hash_table_insert (hash, g_strdup (MM_SCAN_TAG_OPER_LONG), g_match_info_fetch (match_info, 2));
+ g_hash_table_insert (hash, g_strdup (MM_SCAN_TAG_OPER_SHORT), g_match_info_fetch (match_info, 3));
+ g_hash_table_insert (hash, g_strdup (MM_SCAN_TAG_OPER_NUM), g_match_info_fetch (match_info, 4));
+
+ /* Only try for access technology with UMTS-format matches */
+ if (umts_format)
+ access_tech = g_match_info_fetch (match_info, 5);
+ if (access_tech && (strlen (access_tech) == 1)) {
+ /* Recognized access technologies are between '0' and '6' inclusive... */
+ if ((access_tech[0] >= 48) && (access_tech[0] <= 54))
+ g_hash_table_insert (hash, g_strdup (MM_SCAN_TAG_ACCESS_TECH), access_tech);
+ } else
+ g_free (access_tech);
+
+ g_ptr_array_add (results, hash);
+
+ g_match_info_next (match_info, NULL);
+ }
+
+ g_match_info_free (match_info);
+ g_regex_unref (r);
+
+ return results;
+}
+
+void
+mm_gsm_destroy_scan_data (gpointer data)
+{
+ GPtrArray *results = (GPtrArray *) data;
+
+ g_ptr_array_foreach (results, (GFunc) g_hash_table_destroy, NULL);
+ g_ptr_array_free (results, TRUE);
+}
+
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
new file mode 100644
index 00000000..ddc9cbce
--- /dev/null
+++ b/src/mm-modem-helpers.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2008 - 2009 Novell, Inc.
+ * Copyright (C) 2009 - 2010 Red Hat, Inc.
+ */
+
+#ifndef MM_MODEM_HELPERS_H
+#define MM_MODEM_HELPERS_H
+
+#define MM_SCAN_TAG_STATUS "status"
+#define MM_SCAN_TAG_OPER_LONG "operator-long"
+#define MM_SCAN_TAG_OPER_SHORT "operator-short"
+#define MM_SCAN_TAG_OPER_NUM "operator-num"
+#define MM_SCAN_TAG_ACCESS_TECH "access-tech"
+
+GPtrArray *mm_gsm_parse_scan_response (const char *reply, GError **error);
+
+void mm_gsm_destroy_scan_data (gpointer data);
+
+#endif /* MM_MODEM_HELPERS_H */
+
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
new file mode 100644
index 00000000..74255dbc
--- /dev/null
+++ b/src/tests/Makefile.am
@@ -0,0 +1,22 @@
+INCLUDES = \
+ -I$(top_srcdir)/src
+
+noinst_PROGRAMS = test-modem-helpers
+
+test_modem_helpers_SOURCES = \
+ test-modem-helpers.c
+
+test_modem_helpers_CPPFLAGS = \
+ $(MM_CFLAGS)
+
+test_modem_helpers_LDADD = \
+ $(top_builddir)/src/libmodem-helpers.la \
+ $(MM_LIBS)
+
+if WITH_TESTS
+
+check-local: test-modem-helpers
+ $(abs_builddir)/test-modem-helpers
+
+endif
+
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
new file mode 100644
index 00000000..e2cbf103
--- /dev/null
+++ b/src/tests/test-modem-helpers.c
@@ -0,0 +1,371 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ */
+
+#include <glib.h>
+#include <string.h>
+
+#include "mm-modem-helpers.h"
+
+#define MM_SCAN_TAG_STATUS "status"
+#define MM_SCAN_TAG_OPER_LONG "operator-long"
+#define MM_SCAN_TAG_OPER_SHORT "operator-short"
+#define MM_SCAN_TAG_OPER_NUM "operator-num"
+#define MM_SCAN_TAG_ACCESS_TECH "access-tech"
+
+typedef struct {
+ const char *status;
+ const char *oper_long;
+ const char *oper_short;
+ const char *oper_num;
+ const char *tech;
+} OperEntry;
+
+#define ARRAY_LEN(i) (sizeof (i) / sizeof (i[0]))
+
+static void
+test_results (const char *desc,
+ const char *reply,
+ OperEntry *expected_results,
+ guint32 expected_results_len)
+{
+ guint i;
+ GError *error = NULL;
+ GPtrArray *results;
+
+ g_print ("\nTesting %s +COPS response...\n", desc);
+
+ results = mm_gsm_parse_scan_response (reply, &error);
+ g_assert (results);
+ g_assert (error == NULL);
+
+ g_assert (results->len == expected_results_len);
+
+ for (i = 0; i < results->len; i++) {
+ GHashTable *entry = g_ptr_array_index (results, i);
+ const char *value;
+ OperEntry *expected = &expected_results[i];
+
+ value = g_hash_table_lookup (entry, MM_SCAN_TAG_STATUS);
+ g_assert (value);
+ g_assert (strcmp (value, expected->status) == 0);
+
+ value = g_hash_table_lookup (entry, MM_SCAN_TAG_OPER_LONG);
+ if (expected->oper_long) {
+ g_assert (value);
+ g_assert (strcmp (value, expected->oper_long) == 0);
+ } else
+ g_assert (value == NULL);
+
+ value = g_hash_table_lookup (entry, MM_SCAN_TAG_OPER_SHORT);
+ if (expected->oper_short) {
+ g_assert (value);
+ g_assert (strcmp (value, expected->oper_short) == 0);
+ } else
+ g_assert (value == NULL);
+
+ value = g_hash_table_lookup (entry, MM_SCAN_TAG_OPER_NUM);
+ if (expected->oper_num) {
+ g_assert (value);
+ g_assert (strcmp (value, expected->oper_num) == 0);
+ } else
+ g_assert (value == NULL);
+
+ value = g_hash_table_lookup (entry, MM_SCAN_TAG_ACCESS_TECH);
+ if (expected->tech) {
+ g_assert (value);
+ g_assert (strcmp (value, expected->tech) == 0);
+ } else
+ g_assert (value == NULL);
+ }
+
+ mm_gsm_destroy_scan_data (results);
+}
+
+static void
+test_cops_response_tm506 (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"\",\"T-Mobile\",\"31026\",0),(2,\"T - Mobile\",\"T - Mobile\",\"310260\"),2),(1,\"AT&T\",\"AT&T\",\"310410\"),0)";
+ static OperEntry expected[] = {
+ { "2", "", "T-Mobile", "31026", "0" },
+ { "2", "T - Mobile", "T - Mobile", "310260", "2" },
+ { "1", "AT&T", "AT&T", "310410", "0" }
+ };
+
+ test_results ("TM-506", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_gt3gplus (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (1,\"T-Mobile US\",\"TMO US\",\"31026\",0),(1,\"Cingular\",\"Cingular\",\"310410\",0),,(0, 1, 3),(0-2)";
+ static OperEntry expected[] = {
+ { "1", "T-Mobile US", "TMO US", "31026", "0" },
+ { "1", "Cingular", "Cingular", "310410", "0" },
+ };
+
+ test_results ("GlobeTrotter 3G+ (nozomi)", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_ac881 (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (1,\"T-Mobile\",\"TMO\",\"31026\",0),(1,\"AT&T\",\"AT&T\",\"310410\",2),(1,\"AT&T\",\"AT&T\",\"310410\",0),,(0,1,2,3,4),)";
+ static OperEntry expected[] = {
+ { "1", "T-Mobile", "TMO", "31026", "0" },
+ { "1", "AT&T", "AT&T", "310410", "2" },
+ { "1", "AT&T", "AT&T", "310410", "0" },
+ };
+
+ test_results ("Sierra AirCard 881", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_gtmax36 (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T-Mobile US\",\"TMO US\",\"31026\",0),(1,\"AT&T\",\"AT&T\",\"310410\",2),(1,\"AT&T\",\"AT&T\",\"310410\",0),,(0, 1,)";
+ static OperEntry expected[] = {
+ { "2", "T-Mobile US", "TMO US", "31026", "0" },
+ { "1", "AT&T", "AT&T", "310410", "2" },
+ { "1", "AT&T", "AT&T", "310410", "0" },
+ };
+
+ test_results ("Option GlobeTrotter MAX 3.6", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_ac860 (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T-Mobile\",\"TMO\",\"31026\",0),(1,\"Cingular\",\"Cinglr\",\"310410\",2),(1,\"Cingular\",\"Cinglr\",\"310410\",0),,)";
+ static OperEntry expected[] = {
+ { "2", "T-Mobile", "TMO", "31026", "0" },
+ { "1", "Cingular", "Cinglr", "310410", "2" },
+ { "1", "Cingular", "Cinglr", "310410", "0" },
+ };
+
+ test_results ("Sierra AirCard 860", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_gtm378 (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T-Mobile\",\"T-Mobile\",\"31026\",0),(1,\"AT&T\",\"AT&T\",\"310410\",2),(1,\"AT&T\",\"AT&T\",\"310410\",0),,(0, 1, 3),(0-2)";
+ static OperEntry expected[] = {
+ { "2", "T-Mobile", "T-Mobile", "31026", "0" },
+ { "1", "AT&T", "AT&T", "310410", "2" },
+ { "1", "AT&T", "AT&T", "310410", "0" },
+ };
+
+ test_results ("Option GTM378", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_motoc (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T-Mobile\",\"\",\"310260\"),(0,\"Cingular Wireless\",\"\",\"310410\")";
+ static OperEntry expected[] = {
+ { "2", "T-Mobile", "", "310260", NULL },
+ { "0", "Cingular Wireless", "", "310410", NULL },
+ };
+
+ test_results ("BUSlink SCWi275u (Motorola C-series)", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_mf627a (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"AT&T@\",\"AT&TD\",\"310410\",0),(3,\"Voicestream Wireless Corporation\",\"VSTREAM\",\"31026\",0),";
+ static OperEntry expected[] = {
+ { "2", "AT&T@", "AT&TD", "310410", "0" },
+ { "3", "Voicestream Wireless Corporation", "VSTREAM", "31026", "0" },
+ };
+
+ test_results ("ZTE MF627 (A)", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_mf627b (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"AT&Tp\",\"AT&T@\",\"310410\",0),(3,\"\",\"\",\"31026\",0),";
+ static OperEntry expected[] = {
+ { "2", "AT&Tp", "AT&T@", "310410", "0" },
+ { "3", "", "", "31026", "0" },
+ };
+
+ test_results ("ZTE MF627 (B)", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_e160g (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T-Mobile\",\"TMO\",\"31026\",0),(1,\"AT&T\",\"AT&T\",\"310410\",0),,(0,1,2,3,4),(0,1,2)";
+ static OperEntry expected[] = {
+ { "2", "T-Mobile", "TMO", "31026", "0" },
+ { "1", "AT&T", "AT&T", "310410", "0" },
+ };
+
+ test_results ("Huawei E160G", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_mercury (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"\",\"\",\"310410\",2),(1,\"AT&T\",\"AT&T\",\"310410\",0),(1,\"T-Mobile\",\"TMO\",\"31026\",0),,(0,1,2,3,4),(0,1,2)";
+ static OperEntry expected[] = {
+ { "2", "", "", "310410", "2" },
+ { "1", "AT&T", "AT&T", "310410", "0" },
+ { "1", "T-Mobile", "TMO", "31026", "0" },
+ };
+
+ test_results ("Sierra AT&T USBConnect Mercury", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_quicksilver (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"AT&T\",\"\",\"310410\",0),(2,\"\",\"\",\"3104100\",2),(1,\"AT&T\",\"\",\"310260\",0),,(0-4),(0-2)";
+ static OperEntry expected[] = {
+ { "2", "AT&T", "", "310410", "0" },
+ { "2", "", "", "3104100", "2" },
+ { "1", "AT&T", "", "310260", "0" },
+ };
+
+ test_results ("Option AT&T Quicksilver", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_icon225 (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T-Mobile US\",\"TMO US\",\"31026\",0),(1,\"AT&T\",\"AT&T\",\"310410\",0),,(0, 1, 3),(0-2)";
+ static OperEntry expected[] = {
+ { "2", "T-Mobile US", "TMO US", "31026", "0" },
+ { "1", "AT&T", "AT&T", "310410", "0" },
+ };
+
+ test_results ("Option iCON 225", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_icon452 (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (1,\"T-Mobile US\",\"TMO US\",\"31026\",0),(2,\"T-Mobile\",\"T-Mobile\",\"310260\",2),(1,\"AT&T\",\"AT&T\",\"310410\",2),(1,\"AT&T\",\"AT&T\",\"310410\",0),,(0,1,2,3,4),(0,1,2)";
+ static OperEntry expected[] = {
+ { "1", "T-Mobile US", "TMO US", "31026", "0" },
+ { "2", "T-Mobile", "T-Mobile", "310260", "2" },
+ { "1", "AT&T", "AT&T", "310410", "2" },
+ { "1", "AT&T", "AT&T", "310410", "0" }
+ };
+
+ test_results ("Option iCON 452", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_f3507g (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T - Mobile\",\"T - Mobile\",\"31026\",0),(1,\"AT&T\",\"AT&T\",\"310410\",0),(1,\"AT&T\",\"AT&T\",\"310410\",2)";
+ static OperEntry expected[] = {
+ { "2", "T - Mobile", "T - Mobile", "31026", "0" },
+ { "1", "AT&T", "AT&T", "310410", "0" },
+ { "1", "AT&T", "AT&T", "310410", "2" }
+ };
+
+ test_results ("Ericsson F3507g", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_f3607gw (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T - Mobile\",\"T - Mobile\",\"31026\",0),(1,\"AT&T\",\"AT&T\",\"310410\"),2),(1,\"AT&T\",\"AT&T\",\"310410\"),0)";
+ static OperEntry expected[] = {
+ { "2", "T - Mobile", "T - Mobile", "31026", "0" },
+ { "1", "AT&T", "AT&T", "310410", "2" },
+ { "1", "AT&T", "AT&T", "310410", "0" }
+ };
+
+ test_results ("Ericsson F3607gw", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+static void
+test_cops_response_mc8775 (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T-Mobile\",\"T-Mobile\",\"31026\",0),(1,\"AT&T\",\"AT&T\",\"310410\",2),(1,\"AT&T\",\"AT&T\",\"310410\",0),,(0,1,2,3,4),(0,1,2)";
+ static OperEntry expected[] = {
+ { "2", "T-Mobile", "T-Mobile", "31026", "0" },
+ { "1", "AT&T", "AT&T", "310410", "2" },
+ { "1", "AT&T", "AT&T", "310410", "0" }
+ };
+
+ test_results ("Sierra MC8775", reply, &expected[0], ARRAY_LEN (expected));
+}
+
+#if 0
+static void
+test_cops_response_n80 (void *f, gpointer d)
+{
+ const char *reply = "+COPS: (2,\"T - Mobile\",,\"31026\"),(1,\"Einstein PCS\",,\"31064\"),(1,\"Cingular\",,\"31041\"),,(0,1,3),(0,2)";
+ static OperEntry expected[] = {
+ { "2", "T - Mobile", "", "31026", NULL },
+ { "1", "Einstein PCS", "", "31064", NULL },
+ { "1", "Cingular", "", "31041", NULL },
+ };
+ GError *error = NULL;
+ GPtrArray *results;
+
+ results = mm_gsm_parse_scan_response (reply, &error);
+ g_assert (results);
+ g_assert (error == NULL);
+
+ g_assert (results->len == ARRAY_LEN (expected));
+ test_results ("Nokia N80", results, &expected[0]);
+
+ mm_gsm_destroy_scan_data (results);
+}
+#endif
+
+typedef void (*TCFunc)(void);
+
+#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (TCFunc) t, NULL)
+
+int main (int argc, char **argv)
+{
+ GTestSuite *suite;
+
+ g_test_init (&argc, &argv, NULL);
+
+ suite = g_test_get_root ();
+
+ g_test_suite_add (suite, TESTCASE (test_cops_response_tm506, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_gt3gplus, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_ac881, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_gtmax36, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_ac860, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_gtm378, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_motoc, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_mf627a, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_mf627b, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_e160g, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_mercury, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_quicksilver, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_icon225, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_icon452, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_f3507g, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_f3607gw, NULL));
+ g_test_suite_add (suite, TESTCASE (test_cops_response_mc8775, NULL));
+#if 0
+ g_test_suite_add (suite, TESTCASE (test_cops_response_n80, NULL));
+#endif
+
+ return g_test_run ();
+}
+